pay tokens for tokens
Every model, with holographic memory in front. Send a book — we spill it into leCore and the model only ever sees the slice that answers you, so the 402 quotes a discount off what that same request costs bought direct, never a markup on it. No account, no API key, no subscription. You pay per request in USDC, TOKEN, LEOS, USDG or TOKEN2 — on Solana, Base, Robinhood Chain, eip155:137, eip155:42161 or eip155:10 — and the 402 names the exact amount in USD at that second.
try it yourself
Dump this into Claude / Grok / Codex. It has everything.
No SDK. No provider key. If it can POST and sign — a Solana TransferChecked, or an EIP-3009 authorization on Base or Robinhood Chain — it can buy inference here. Raw prompt also at /prompt.txt.
Use https://x402-tokens.fly.dev as an OpenAI-compatible inference endpoint. There is no API key,
no account and no subscription. You pay per request, and only for requests you make.
POST https://x402-tokens.fly.dev/v1/chat/completions
Content-Type: application/json
Body is a normal OpenAI-shaped chat completion:
{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":"..."}],"max_tokens":256}
IMAGE AND VIDEO ARE ALSO SERVED, on their own endpoints. /v1/chat/completions
cannot emit them — do not conclude from a text response that this endpoint has
no media. Same 402 and same rails; billed per image or per clip, not per token.
POST https://x402-tokens.fly.dev/v1/images/generations
{"model":"black-forest-labs/FLUX.1.1-pro","prompt":"...","width":1024,"height":1024}
-> {"data":[{"url":"https://..."}]}
POST https://x402-tokens.fly.dev/v1/videos/generations
{"model":"Wan-AI/wan2.7-t2v","prompt":"...","seconds":5,"resolution":"720P"}
-> {"id":"...","status":"in_progress"} resolution is "720P" or "1080P"
GET https://x402-tokens.fly.dev/v1/videos/{id}
-> {"status":"completed","outputs":{"video_url":"https://..."}}
Polling is FREE — the render was paid for at submit. Poll until status
leaves "in_progress"; a failed job explains itself in error.message.
GET /v1/models lists these alongside the text models, tagged kind:"image" or
kind:"video" with the per-unit price. leCore memory does NOT apply to a render
(a prompt that short never spills) — do not claim it improved the output.
You will get HTTP 402. That is the product, not an error.
accepts[] will include one row per offered rail. Pick ONE:
- USDC mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp decimals 6 0bps tax price $1 stable
- TOKEN mint 4JSgUyRRgrNSK5pA3wQMp61vP5RRuLeynmPbRwMkvrex solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp decimals 6 600bps tax price Birdeye EVULoNF4DeMBN4dGiZiDfpiiTfNZgoCvXWWgaV3epump at the 402
- LEOS mint 2tXdVsqrMYZhXGQSErTL5FmF2qCiL9tsQQ9pVafYmzf3 solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp decimals 9 600bps tax price Birdeye 5xgsnby6P9zqGK71J7H4yJLxzqPvNbC7rDZxNzjHmj7e at the 402
- USDC token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 eip155:8453 decimals 6 0bps tax price $1 stable
- USDG token 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 eip155:4663 decimals 6 0bps tax price $1 stable
- TOKEN token 0xC921Abbe67002f638dbD1e353b204767b280A369 eip155:4663 decimals 18 0bps tax price DexScreener 0xC921Abbe67002f638dbD1e353b204767b280A369 at the 402
- TOKEN2 token 0x987a59a076db1ace08c3dcba9032c93cd3691ba3 eip155:4663 decimals 18 0bps tax price DexScreener 0x987a59a076db1ace08c3dcba9032c93cd3691ba3 at the 402
- USDC token 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 eip155:137 decimals 6 0bps tax price $1 stable
- USDC token 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 eip155:42161 decimals 6 0bps tax price $1 stable
- USDC token 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 eip155:10 decimals 6 0bps tax price $1 stable
Every row carries its OWN network, payTo and decimals. READ THEM OFF THE ROW —
they are NOT the same across rails:
- network: the row's "network" (Solana CAIP-2, or eip155:<chainId>)
- payTo: the row's "payTo". Solana rows carry a base58 address; eip155 rows
carry a 0x address. They are different addresses. Never reuse one for the other.
- extra.decimals: the raw-unit exponent OF THAT ASSET. It is 6 on some rails and
18 on others. Do not assume.
- maxAmountRequired: the final amount ALREADY in that asset's raw units, grossed
up for its transfer tax. Do not reprice it and DO NOT multiply it by
10^decimals — that is already done. extra.decimals is for display only.
- extra.feePayer: Solana rows only.
- extra.pricing: "counterfactual" = a DISCOUNT off what this exact body would cost you
buying direct (extra.directUsd, extra.savesVsDirect), never a markup on it.
"markup" = the body was small enough that there was nothing to compress, so the
price is built off our own measured cost of serving it and extra.markup names the
effective multiple. Long context is cheaper HERE than direct because leCore memory
means we never forward the whole body.
- extra.assetTransferMethod: eip155 rows only. Absent = EIP-3009 (sign
TransferWithAuthorization). "permit2" = the token has no EIP-3009; sign a
Permit2 PermitWitnessTransferFrom instead (below).
- facilitator: https://x402-anychain.fly.dev (it verifies and settles every row)
PAY HALF: rows whose extra.symbol is TOKEN2, TOKEN or LEOS ask HALF what the USDC
row asks for the same call. TOKEN2 on Robinhood Chain (eip155:4663,
0x987a59a076db1ace08c3dcba9032c93cd3691ba3) is the token running openzoo.fun —
buy it on Robinhood and every call here costs half of what it costs in USDC.
The earlier Robinhood TOKEN (0xC921Abbe67002f638dbD1e353b204767b280A369) is
DEPRECATED, superseded by TOKEN2: still accepted while it is quoted, no longer
what anyone should buy.
IF THE ROW YOU PICKED IS A SOLANA ROW — build one legacy Transaction:
1. feePayer = the row's extra.feePayer (GrsWPcmfjURHAXRE2kuo6kMUDXL7mBGWh2tpUkkyc55w, the facilitator's signer) ← you do not pay SOL.
2. exactly one Token-2022 TransferChecked: your ATA of the chosen mint → payTo's
ATA, amount = maxAmountRequired (raw, as given),
decimals = the row's extra.decimals ← read it off the row, do not hardcode
3. you sign as the token owner. leave the feePayer signature empty.
4. serialize requireAllSignatures=false, base64 those bytes
X-PAYMENT header = base64 of this JSON (utf8):
{"x402Version":1,"scheme":"exact","network":"<the row's network>","payload":{"transaction":"<base64-tx>"}}
IF THE ROW YOU PICKED IS AN eip155 ROW — sign EIP-3009, send no transaction:
1. you pay NO gas. The facilitator relays your signature and pays it.
2. EIP-712 typed-data sign TransferWithAuthorization with domain
{name: extra.name, version: extra.version, chainId: <from eip155:chainId>,
verifyingContract: the row's asset}
← name/version come off the ROW. Guessing them recovers a different address
and the payment is rejected as "signature does not match payer".
3. message = {from: <your address>, to: <the row's payTo>,
value: maxAmountRequired (raw uint256, VERBATIM — no decimal
scaling, this is where an agent loses 10^12),
validAfter: 0, validBefore: <now + maxTimeoutSeconds>,
nonce: <random 32 bytes, 0x-hex>}
X-PAYMENT header = base64 of this JSON (utf8):
{"x402Version":1,"scheme":"exact","network":"<the row's network>","payload":{"signature":"0x…","authorization":{"from":"0x…","to":"0x…","value":"<maxAmountRequired>","validAfter":"0","validBefore":"<unix>","nonce":"0x…"}}}
IF THE eip155 ROW SAYS extra.assetTransferMethod = "permit2" (TOKEN2 / TOKEN on Robinhood
Chain) — sign Permit2 instead. Same idea, different domain and shape:
1. ONCE per wallet, ever: approve(0x000000000022D473030F116dDEE9F6B43aC78BA3, max)
on the row's asset. That is the only transaction you ever send; check
allowance(you, Permit2) first and skip it when it already covers the amount.
2. EIP-712 typed-data sign PermitWitnessTransferFrom with domain
{name: "Permit2", chainId: <from eip155:chainId>,
verifyingContract: 0x000000000022D473030F116dDEE9F6B43aC78BA3}
types: PermitWitnessTransferFrom(TokenPermissions permitted, address spender,
uint256 nonce, uint256 deadline, Witness witness)
TokenPermissions(address token, uint256 amount)
Witness(address to, uint256 validAfter)
message = {permitted: {token: the row's asset, amount: maxAmountRequired (raw,
VERBATIM)}, spender: 0x402085c248EeA27D92E8b30b2C58ed07f9E20001
(the x402 exact Permit2 proxy — NOT payTo), nonce: <random uint256>,
deadline: <now + maxTimeoutSeconds>, witness: {to: the row's payTo,
validAfter: 0}}
3. you pay no gas for the settle — the facilitator calls the proxy, which pulls
exactly the permitted amount from you and forwards it to witness.to.
X-PAYMENT header = base64 of this JSON (utf8):
{"x402Version":1,"scheme":"exact","network":"<the row's network>","payload":{"signature":"0x…","permit2Authorization":{"from":"0x…","permitted":{"token":"<asset>","amount":"<maxAmountRequired>"},"spender":"0x402085c248EeA27D92E8b30b2C58ed07f9E20001","nonce":"<uint256 decimal>","deadline":"<unix>","witness":{"to":"<payTo>","validAfter":"0"}}}}
Any stock x402 client (@x402/evm) does all of this for you when it sees
extra.assetTransferMethod = "permit2".
POST the SAME body again with X-PAYMENT set. Do not change model/messages/max_tokens after the 402 — the quote is for that body.
On 200 you get a normal chat.completion.
THERE IS NO WRAP STEP ON ANY RAIL. Every accepts[] row is the asset you already
hold: pay it directly, at the mint in the row.
Read asset, decimals and payTo OFF THE ROW you picked — they differ per rail and
LEOS is nine decimals, not six. maxAmountRequired is already in that asset's raw
units; do not rescale it.
On the eip155 rails you pay no gas — the facilitator relays your signature.
You never call the facilitator yourself — send the payment to THIS service in the X-PAYMENT header and it settles through https://x402-anychain.fly.dev. GET https://x402-tokens.fly.dev/.well-known/x402.json and https://x402-tokens.fly.dev/prompt.txt if you want this text again.
Hit the endpoint. It should 402 you.
No wallet in the browser. This button is a GET-equivalent POST with no X-PAYMENT. If the service is up you get a challenge, not a completion.
curl -sS https://x402-tokens.fly.dev/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":"say hi"}]}'
It is not only text.
Image and video generate on their own endpoints — same 402, same rails, but billed per image or per clip, not per token. GET /v1/models lists them with kind:"image" / kind:"video" and the price per unit.
POST /v1/images/generations
{"model":"black-forest-labs/FLUX.1-schnell","prompt":"...","width":1024,"height":1024}
-> 200 {"data":[{"url":"https://..."}]}
POST /v1/videos/generations
{"model":"Wan-AI/wan2.7-t2v","prompt":"...","seconds":5,"resolution":"720P"}
-> 200 {"id":"...","status":"in_progress"}
GET /v1/videos/{id} # free to poll — the render was paid for at submit
-> 200 {"status":"completed","outputs":{"video_url":"https://..."}}
- Pick ONE row from
accepts[]. Every row carries its own network, asset,payToanddecimals— read them off the row, they differ per rail. - Solana rows: pay in the row's own mint — USDC, TOKEN or LEOS, exactly as you hold it, no wrap. One
TransferCheckedofmaxAmountRequiredwith the row'sextra.feePayeras fee payer; the fee is sponsored, you need no SOL. - Base / Robinhood Chain rows: no transaction at all — EIP-712-sign and the facilitator relays it and pays the gas. Base takes native Circle USDC (EIP-3009
TransferWithAuthorization). Robinhood Chain settles USDG the same way, and TOKEN (0xC921…A369) via Permit2: the row saysextra.assetTransferMethod: "permit2", you approve Permit2 once per wallet, then sign aPermitWitnessTransferFrom— any stock x402 client does this for you. TOKEN rows are priced at half the USDC row. - POST the same body again with header
X-PAYMENT= base64 of the x402 payload for your rail. On 200 you get a normal OpenAI-shaped chat completion. You never held a provider key, so there is none of yours to leak.
Price
Two bases, and the 402 says which. Long context (leCore engaged): a DISCOUNT off what that exact body would have cost you buying direct, capped at that number — extra.directUsd and extra.savesVsDirect are on the 402, so you can check it before you pay. Short bodies (nothing to spill): priced off our own measured cost of serving the call, with extra.markup naming the effective multiple. Measured 2026-08-24 with prompt caching live: on a warm Claude Fable 5 session the real upstream cost of a 35,953-token prefix went $0.4497 → $0.0362 — 92% off, 12.42× cheaper. USDC and USDG rails are $1 stable. TOKEN is DexScreener spot at the 402, and its rows ask half what the USDC row asks for the same call — buy the token called TOKEN on Robinhood and spend half the fees you'd spend in USDC. Rails that settle through a yield wrap take 20bps on transfer — that's the yield, and maxAmountRequired already grosses it up.
Rails today
Solana — USDC · TOKEN · LEOS · settled real payments
Base — USDC · settled real payments
Robinhood Chain — USDG · TOKEN · TOKEN2 · settled real payments
eip155:137 — USDC · offered · no settlement yet
eip155:42161 — USDC · offered · no settlement yet
eip155:10 — USDC · offered · no settlement yet
TOKEN2 is 0x987a59a076db1ace08c3dcba9032c93cd3691ba3 on Robinhood Chain — the token running openzoo.fun. The earlier Robinhood TOKEN (0xC921Abbe67002f638dbD1e353b204767b280A369) is deprecated, superseded by TOKEN2. New rails appear in accepts[] the moment they go live — the 402 is the source of truth, not this page.