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 long context costs half of buying direct. No API key. You pay in USDC, USDG, ODDBALLER, IOU, ROBINHOODS, wTOKENx3 or LEOS — on Solana, Base or Robinhood Chain — 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.
POST https://x402-tokens.fly.dev/v1/chat/completions
Content-Type: application/json
Body is a normal OpenRouter/OpenAI 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-schnell","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:
- yUSDCx mint 6ZjjxcoicqM4nniddkuPVwew4PDwY3swbfHsGbCuLuTv solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp decimals 6 20bps tax price $1 stable
- USDC token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 eip155:8453 decimals 6 0bps tax price $1 stable
- wUSDGx token 0x9bdD78296f758af1b048E14E101c90Daa511ADC5 eip155:4663 decimals 6 20bps tax price $1 stable
- ODDBALLER token 0x1AE410a93C8b05c872D2FE2718e9BB66392AF903 eip155:4663 decimals 18 2bps tax price DexScreener 0x923eb7BD5B84a1a114CB57212cE2F2e87AE60E2A at the 402
- IOU token 0x90c2B5DA6097DbbB3632469108A38F4F91eD0434 eip155:4663 decimals 18 2bps tax price DexScreener 0xf391999FACbEE613D4024191Dd31060540BF0bEd at the 402
- ROBINHOODS token 0xD906653C147cF35329161665a4AaaAd3bc118743 eip155:4663 decimals 18 2bps tax price DexScreener 0xC42cF61C16aaC797b991cf9C1ac8Ae70bA74A286 at the 402
- wTOKENx3 mint HSyCKU5bBErNao3h4ujZygQ2btdXz4CHfBKsYszitKYf solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp decimals 6 20bps tax price Birdeye EVULoNF4DeMBN4dGiZiDfpiiTfNZgoCvXWWgaV3epump at the 402
- wLEOSx mint 3FViQRMqtG6dUDFxZyyVvpM9xTHsKdX7uqZ5jvL8NZ35 solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp decimals 9 20bps tax price Birdeye 5xgsnby6P9zqGK71J7H4yJLxzqPvNbC7rDZxNzjHmj7e at the 402
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). "markup" = small bodies, priced
3× cost. Long context is cheaper HERE than direct because leCore memory
means we never forward the whole body.
- facilitator: https://x402.accrue.fund
IF THE ROW YOU PICKED IS A SOLANA ROW — build one legacy Transaction:
1. feePayer = the row's extra.feePayer (WzMaL78srutrF6CsxEkWuhMaDF5HZA6jNRaEPengqpb) ← 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…"}}}
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.
ON SOLANA, raw TOKEN (EVULoNF4DeMBN4dGiZiDfpiiTfNZgoCvXWWgaV3epump), raw LEOS
(5xgsnby6P9zqGK71J7H4yJLxzqPvNbC7rDZxNzjHmj7e) and raw USDC will not settle. Wrap first:
- USDC → yUSDCx via FrSERTNCPvTtaDS9AvQp9u1nYGzXDb3kC9MdL8Xxn2NE escrow 2qLm8aCvn6gQVUFeQ7EC5J62Y95gFzc3vReHzD5d5Gj2
- TOKEN → wTOKENx via the same program, escrow 7j682FdwSdTkXNjbMrrLd5wcXQoh23UTZaDReqKXbL2q
- LEOS → wLEOSx via the same program, escrow 62kjFPGb2RnPXfShFdeYuvyN72hg5EC4N8UVkuN1RiMc
All three wraps are Token-2022 with a 20bps transfer tax. Yield is that tax.
LEOS is NINE decimals and a legacy SPL mint, so its escrow lives under
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA — do not assume Token-2022 or 6dp
on that row.
ON BASE there is no wrap step — the row is native Circle USDC, held directly.
ON ROBINHOOD CHAIN the row is wUSDGx, an ERC-4626 wrapper over Paxos USDG
(0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168): approve the wrapper, then
deposit(uint256,address). See https://x402.accrue.fund/start.
On both eip155 rails you pay no gas — the facilitator relays your signature.
Do not use api.cdp.coinbase.com. This service names https://x402.accrue.fund. 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: fund with USDC, TOKEN or LEOS, then pay via the row's settlement mint (raw USDC/TOKEN will not settle — the 402 and https://x402.accrue.fund/start spell out the deposit step). One
TransferCheckedofmaxAmountRequired; the fee payer is sponsored, you need no SOL. - Base / Robinhood Chain rows: no transaction at all — EIP-712-sign an EIP-3009
TransferWithAuthorizationand the facilitator relays it and pays the gas. Base takes native Circle USDC directly; Robinhood Chain settles USDG (deposit path at /start). - POST the same body again with header
X-PAYMENT= base64 of the x402 payload for your rail. On 200 you get a normal OpenRouter chat completion. The key never leaves this host.
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 — extra.directUsd and extra.savesVsDirect are on the 402, so you can check it. Short bodies (nothing to spill): the published USD rate times 3. USDC and USDG rails are $1 stable. TOKEN is Birdeye spot at the 402. 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 · wTOKENx3 · LEOS · settled real payments
Base — USDC · settled real payments
Robinhood Chain — USDG · ODDBALLER · IOU · ROBINHOODS · settled real payments
TOKEN is EVULo…pump on pump.fun. New rails appear in accepts[] the moment they go live — the 402 is the source of truth, not this page.