Token Pay Platform
Let each project monetize its native SPL token via x402 self-settle — without building RPC, price oracle, or on-chain verification infra. The default merchant today is SOON (Concierge utility token).
Concierge Token Pay complements USDC settlement via PayAI / Dexter. Users pay in the project token on Solana (user pays SOL gas); the server verifies the transfer on-chain — no facilitator hot wallet.
Status: SOON appears in the Lounge payment modal as Coming soon until the token launches. After launch, set SOON_TOKEN_MINT on Vercel — pricing flows from DexScreener with SOON_USDC_RATE as fallback.
What is Token Pay?
Token Pay lets your project monetize its own native SPL token as an x402 payment option (alongside USDC). Users sign the token transfer in their wallet; Concierge verifies and settles via self-settle on-chain.
For developers: register your token once on Concierge. After your merchant is live, callers can pay
with your token on supported x402 routes — revenue lands in your payTo wallet.
No need to build RPC, price oracle, or settlement verification yourself.
What you provide
- Token mint (live on Solana) + decimals
- Receive wallet (
payTo) — where x402 token payments are credited - Pricing: DexScreener (recommended) or a static USD fallback
- Routes: which paid APIs should list your token (
resourceKinds)
What Concierge handles
- Token amount resolution from USDC list pricing
- Token accept inside the
402response - Simulate → broadcast → confirm → verify the token delta on-chain (no facilitator hot wallet)
Public APIs
GET /api/token-pay— platform meta + merchant registry + readinessGET /api/token-pay-analytics?merchant=ID— tx count, volume, daily chart dataGET /api/token-pay-build-accept— server-built accept for partner APIsPOST /api/token-pay-verify— verify + settle on partner domainsGET /api/x402-config— includestokenPayconfig for your accept builder
Integrate Token Pay in your project
Use this flow when your team wants users or agents to pay with your native token for x402-gated APIs — whether they call Concierge directly or your app wraps Concierge calls.
Step 1 — Configure your merchant
Self-service: Onboarding wizard — fill the form, validate via POST /api/token-pay-preview, copy the env line. Or edit JSON manually:
Add your row to TOKEN_PAY_MERCHANTS_JSON in environment variables, then redeploy:
- Local test — copy
.env.example, setTOKEN_PAY_MERCHANTS_JSON, runnpm run dev - Production — append your row in Vercel env on the Concierge deploy and redeploy
{
"id": "acme",
"symbol": "ACME",
"name": "ACME Protocol",
"mint": "YourMintBase58…",
"decimals": 6,
"payTo": "YourSolanaReceiveWallet…",
"priceSource": "dexscreener",
"fallbackUsd": 0.001,
"resourceKinds": ["external", "concierge"],
"allowedOrigins": ["https://api.acme.xyz", "https://acme.xyz"],
"x402Enabled": true
}
Required: unique id, live mint, your payTo wallet, and decimals.
Create an ATA on payTo by sending a tiny amount of your token once.
Stuck after fixing readiness.blockers? Contact the Concierge team on
Telegram.
Step 2 — Confirm readiness (before launch)
curl -s "https://conc-exe.xyz/api/token-pay?merchant=acme" | jq '.merchant.readiness'
Target: status: "ready" and acceptReady: true. Or open
Token Pay Dashboard (/agent/token-pay?merchant=acme).
Step 3 — Wire your x402 client
On any supported route (e.g. POST /api/concierge):
- Call without payment → receive 402 +
PAYMENT-REQUIRED - Decode
accepts[]— pick entry withextra.settlement === "self"andextra.merchantId === "acme" - Sign SPL
transferCheckedtopayToforamountatomic units ofasset(mint) - Retry with
PAYMENT-SIGNATURE→ server verifies on-chain → 200 + JSON body
Browser reference: frontend/lib/x402-browser-client.ts + x402-solana-self-scheme.ts.
Load merchant config from GET /api/x402-config → tokenPay.merchants.
Agents can use pay curl or any x402 HTTP client the same way as USDC — select the token accept instead of USDC.
Step 4 — Ship in your product
- Agent / backend — call Concierge paid routes; pass
PAYMENT-SIGNATUREwith your token accept (users or treasury wallet signs) - Web app — embed pay flow like Executive Lounge: fetch config, show your token in the pay modal, self-settle in Phantom/OKX
- Community — publish
GET /api/token-pay?merchant=YOUR_IDfor liveconciergeAtomicamounts and pricing labels
Revenue: every successful settlement credits your payTo wallet. Track volume on
/agent/token-pay or GET /api/token-pay-analytics.
Step 5 — End-to-end test
- Run one paid call with your token (Playground, Lounge, or
curl+ x402 client) - Confirm HTTP 200 +
PAYMENT-RESPONSEheader contains Solanatransaction - Open the signature on Solscan — your
payTotoken balance increased - Dashboard tx count increments (requires KV in production for persistent analytics)
Token Pay on your own API (partner verify)
Gate your endpoints (e.g. api.acme.xyz) with x402 + your native token.
Concierge builds the accept, verifies the on-chain payment, and credits your payTo wallet —
no extra Vercel functions (uses the existing Edge router).
Merchant setup
Include "external" in resourceKinds. Optional allowedOrigins restricts browser calls to build/verify APIs.
curl -s "https://conc-exe.xyz/api/token-pay?merchant=acme&resource=external" | jq '.merchant.readiness'
1. Build accept (your backend)
curl -s -X POST https://conc-exe.xyz/api/token-pay-build-accept \
-H "Content-Type: application/json" \
-d '{"merchantId":"acme","usdAmount":0.1,"resourceUrl":"https://api.acme.xyz/v1/intel"}'
Returns accept — use it in your 402 + PAYMENT-REQUIRED response.
2. User pays (wallet signs SPL transfer)
Same self-settle flow as Concierge routes — client signs transferChecked to your payTo.
3. Verify via Concierge
curl -s -X POST https://conc-exe.xyz/api/token-pay-verify \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <base64 payment payload>" \
-d '{"merchantId":"acme","usdAmount":0.1,"resourceUrl":"https://api.acme.xyz/v1/intel"}'
On success: HTTP 200, JSON with transaction, header PAYMENT-RESPONSE. Then return your API response to the user.
SDK — @conc-exe/token-x402
TypeScript helper in packages/token-x402 (monorepo). Wraps build + verify:
import { createConciergeTokenPayClient } from "@conc-exe/token-x402";
const tp = createConciergeTokenPayClient({ origin: "https://conc-exe.xyz" });
const { accept } = await tp.buildAccept({ merchantId: "acme", usdAmount: 0.1, resourceUrl });
const verified = await tp.verifyPayment({ merchantId: "acme", usdAmount: 0.1, resourceUrl, paymentSignature });
Optional dedicated host: point pay.conc-exe.xyz to the same Vercel project (add domain in Vercel) and use it as origin.
Verify connection & monitor usage
Token Pay includes a per-merchant dashboard. Use the Concierge checks below to verify and monitor your merchant.
1. Readiness API (before any user pays)
After your merchant row is deployed, poll:
curl -s "https://conc-exe.xyz/api/token-pay?merchant=YOUR_ID" | jq '.merchant.readiness'
Target: status: "ready" and acceptReady: true. If not, read blockers[] (missing ATA, price, mint, etc.).
| status | Meaning |
|---|---|
ready | Will appear in 402 accepts for the probed resource |
ata_missing | Send a tiny token transfer to payTo once |
price_unavailable | Set fallbackUsd or list on DexScreener |
coming_soon | Mint not live yet (e.g. SOON pre-launch) |
Browser UI: Agent Discover · Token Pay Dashboard shows live readiness + settlement analytics.
2. 402 accept probe (integration wired)
curl -s -X POST https://conc-exe.xyz/api/concierge \
-H "Content-Type: application/json" \
-d '{"mode":"chat","message":"probe"}' -D - -o /dev/null 2>&1 | grep -i payment-required
Decode the base64 PAYMENT-REQUIRED header → accepts[] must include your token with extra.merchantId: "YOUR_ID" and extra.settlement: "self".
3. Successful payment (end-to-end)
- HTTP 200 on the paid route + JSON body (e.g.
replyfor Concierge) - Response header
PAYMENT-RESPONSE(base64) containstransaction= Solana signature - On-chain: open the signature in Solscan — merchant
payTotoken balance increased
Concierge monitoring tools
| Tool | What you see |
|---|---|
GET /api/token-pay | Per-merchant readiness, pricing, acceptReady |
| /agent/token-pay | Dashboard — readiness, tx count, volume chart, recent settlements + Solscan |
| /agent/discover | Live registry + readiness counts |
GET /api/token-pay-analytics | JSON totals, daily rollups, recent tx list |
| Solana explorer | On-chain proof — token credited to your payTo wallet |
Use readiness API + Token Pay Dashboard + one test payment + Solscan for definitive proof.
Security model (per merchant)
- Funds isolation — each partner must set their own
payTowallet; token payments never fall back to Concierge’sX402_SOL_PAY_TO. - Registry gate — settlement re-checks
merchantId, mint, payTo, andresourceKindsagainst the server registry before broadcast. - 402 matching — payment must match an accept the server issued (scheme, network, amount, asset, payTo).
- On-chain verify — simulate → broadcast → confirm → verify token delta to the merchant wallet.
- Price guards — optional
usdMin/usdMaxper merchant; DexScreener cache per merchant id. - No hot wallet — Concierge never holds partner private keys; users sign transfers in their own wallet.
Reserved slug soon cannot be registered via JSON. Merchant ids must be lowercase a-z0-9_- (max 16 partners per deploy).
vs USDC facilitators
| PayAI / Dexter | Token Pay | |
|---|---|---|
| Model | Facilitator (gasless USDC) | Self-settle (user pays SOL gas) |
| Asset | USDC | Project native token |
| Price | Fixed USDC list price | DexScreener + env fallback |
| Phase 1 route | All paid APIs | POST /api/concierge (more routes later) |
Public APIs
GET /api/token-pay— platform meta + merchant registryGET /api/token-pay?merchant=soon— single merchant configGET /api/x402-config— includestokenPay(and legacysoonX402)
curl -s https://conc-exe.xyz/api/token-pay | jq '{live: .liveMerchantCount, merchants: [.merchants[] | {id, symbol, live, conciergeAtomic}]}'
curl -s "https://conc-exe.xyz/api/token-pay?merchant=acme" | jq '.merchant'
Pay with a partner token (agents & apps)
After your merchant is live, callers can pay Concierge with your SPL token instead of USDC:
POST /api/concierge(or another route in yourresourceKinds) → receive 402 +PAYMENT-REQUIRED- Decode
accepts— pick the entry whereextra.settlement === "self"andextra.merchantId === "your-id" - Sign an SPL
transferCheckedtopayToforamountatomic units ofasset(mint) - Retry with
PAYMENT-SIGNATURE— server simulates, broadcasts, confirms on-chain delta
USDC routes still use PayAI/Dexter facilitators. Token Pay accepts are separate Solana entries in the same accepts array. Browser reference: frontend/lib/x402-browser-client.ts + x402-solana-self-scheme.ts.
# Inspect accepts (decode PAYMENT-REQUIRED header from 402)
curl -s -X POST https://conc-exe.xyz/api/concierge \
-H "Content-Type: application/json" \
-d '{"mode":"chat","message":"test"}' -D - -o /dev/null 2>&1 | grep -i payment-required
Merchant JSON fields
| Field | Required | Description |
|---|---|---|
id | yes | Stable slug (a-z0-9_-, 2–32 chars). Reserved: soon |
symbol | yes | Ticker shown in UI |
mint | yes | SPL mint (base58) |
payTo | yes | Your Solana receive wallet — where token payments are credited |
decimals | yes | Token decimals (usually 6) |
priceSource | no | dexscreener (default) or env |
fallbackUsd | recommended | USD per 1 token when oracle fails |
usdMin / usdMax | no | Price sanity bounds |
resourceKinds | no | concierge, external (your own API), etc. |
allowedOrigins | no | Browser origins allowed for build/verify APIs |
x402Enabled | no | Set false to disable without removing row |
Resource kinds
Your token appears in 402 accepts only for routes listed in resourceKinds:
| resourceKind | API route | USDC price |
|---|---|---|
concierge | POST /api/concierge | $0.10 |
news | POST /api/news-open | $0.10 |
signal-open | POST /api/lounge-signal-open | $0.10 |
signal-publish | POST /api/lounge-signal-publish | $1.00 |
intel-* | POST /api/concierge-intel-* | $0.10 |
Default for new merchants is ["concierge"]. Request additional routes when you expand your integration.
Merchant registration checklist
Add your token via TOKEN_PAY_MERCHANTS_JSON in environment variables and redeploy.
When your merchant is live (mint + payTo + resolvable price), every 402 response
for matching resource kinds includes a self-settle accept for your token — alongside USDC.
Checklist
- Add your row to
TOKEN_PAY_MERCHANTS_JSON(local.envor Vercel env) and redeploy - Ensure
payTowallet has an ATA for your mint (send a tiny amount once) - Set
fallbackUsdor list on DexScreener for live price - Confirm
GET /api/token-pay?merchant=YOUR_ID→readiness.acceptReady: true - Confirm
GET /api/x402-configshows your merchantlive: trueandconciergeAtomic - Run a test paid call — inspect
PAYMENT-REQUIREDfor yourmerchantIdaccept - Verify Solscan + dashboard after first settlement
Example registry row
TOKEN_PAY_MERCHANTS_JSON=[
{
"id": "acme",
"symbol": "ACME",
"name": "ACME Protocol",
"mint": "YourMintBase58…",
"decimals": 6,
"payTo": "YourSolanaReceiveWallet…",
"priceSource": "dexscreener",
"fallbackUsd": 0.001,
"resourceKinds": ["external", "concierge"],
"allowedOrigins": ["https://api.acme.xyz"],
"x402Enabled": true
}
]
resourceKinds controls which paid APIs list your token:
concierge, news, signal-open, signal-publish, and intel routes as configured.
Multiple live merchants appear as separate options in the Lounge pay modal.
Need help after self-service setup? Telegram — Theconcierge33
x402 accept (self-settle)
When live, Concierge 402 responses include one or more Solana token accepts alongside USDC (one per live merchant):
{
"scheme": "exact",
"network": "solana:…",
"amount": "<atomic SOON>",
"asset": "<SOON mint>",
"payTo": "<merchant receive wallet>",
"extra": {
"settlement": "self",
"merchantId": "soon",
"name": "SOON",
"decimals": 6
}
}
Executive Lounge signs transferChecked in the browser; the Edge API simulates, broadcasts, and confirms the merchant token delta.
Environment (SOON merchant)
TOKEN_PAY_DEFAULT_MERCHANT=soon
SOON_TOKEN_MINT= # set after pump.fun launch
SOON_TOKEN_DECIMALS=6
SOON_PRICE_SOURCE=dexscreener
SOON_PRICE_MAX_AGE_SEC=60
SOON_USDC_RATE=0.00008 # fallback
X402_SOL_PAY_TO= # merchant receive (USDC + SOON)
Add partner merchants via TOKEN_PAY_MERCHANTS_JSON (see registration checklist). SOON uses X402_SOL_PAY_TO for receive. See Architecture and docs/token-pay-platform.md in the repository.
For your community (end users)
Once live, your token appears in the Executive Lounge pay modal alongside USDC. Users need:
- Phantom or OKX with Solana connected
- Enough of your token for the quoted atomic amount
- A small amount of SOL for transaction fees (self-settle)
Promote: GET /api/token-pay?merchant=YOUR_ID for live pricing labels and conciergeAtomic amounts.
Related
- SOON tokenomics — operating policy · holder tiers
- SOON transparency — weekly buyback & burn ledger
- Executive Lounge — pay modal lists USDC + all live Token Pay merchants
- For Builders — integration paths for agents
- x402 Protocol — USDC flow via PayAI/Dexter
Concierge · Executive Lounge · Not financial advice