x402 · lecore memory · pay per request

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
TOKEN2 — the Robinhood Chain transit token
prompt your clanker

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.
pay in USDC · TOKEN · LEOS · USDG · TOKEN2 · on Solana · Base · Robinhood Chain · eip155:137 · eip155:42161 · eip155:10 · the 402 names each rail's exact mint, payTo and amount
prove it

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"}]}'
unpaid POST · expect HTTP 402
pictures and moving pictures

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://..."}}
video is asynchronous: you pay once at submit, then poll for free until status leaves in_progress · resolution is 720P or 1080P
for degenerates
  1. Pick ONE row from accepts[]. Every row carries its own network, asset, payTo and decimals — read them off the row, they differ per rail.
  2. Solana rows: pay in the row's own mint — USDC, TOKEN or LEOS, exactly as you hold it, no wrap. One TransferChecked of maxAmountRequired with the row's extra.feePayer as fee payer; the fee is sponsored, you need no SOL.
  3. 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 says extra.assetTransferMethod: "permit2", you approve Permit2 once per wallet, then sign a PermitWitnessTransferFrom — any stock x402 client does this for you. TOKEN rows are priced at half the USDC row.
  4. 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.