Paying with x402
Open an entity page in TraceFast →
x402 is an open payment protocol built on the HTTP status
code 402 Payment Required. Every TraceFast API method is sold this way too:
it answers an unpaid request with a machine-readable price; the client pays in
USDC and repeats the request with a proof of payment. No sign-up, no API key,
no session. The path is the method's REST path on
https://mpp.tracefast.xyz/api/v1, and so are the answer and the refusals.
What you need
- A wallet holding USDC on Base (
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913). No ETH is needed: the payment is an EIP-3009 authorization and the facilitator sponsors the gas. - An x402 v2 client. The reference client is
@x402/fetch; themppxCLI also pays x402 challenges. Any client that implements the x402 v2exactscheme works.
The flow
-
Request the method. The response is
402 Payment Requiredwith aPAYMENT-REQUIREDheader: base64-encoded JSON describing what to pay.curl -i https://mpp.tracefast.xyz/api/v1/chains/1/entities/0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97/attributesDecoded, the header carries:
{ "x402Version": 2, "accepts": [{ "scheme": "exact", "network": "eip155:8453", "amount": "50000", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "payTo": "0x…", "maxTimeoutSeconds": 300, "extra": { "name": "USD Coin", "version": "2", "assetTransferMethod": "eip3009" } }], "resource": { "url": "https://mpp.tracefast.xyz/api/v1/chains/1/entities/0x4838…5f97/attributes" }, "extensions": { "offer-receipt": { "info": { "offers": [{ "format": "jws", "acceptIndex": 0, "signature": "eyJhbGciOiJFZERTQSIs…" }] } } } }amountis in USDC base units (6 decimals):50000= 0.05 USDC. Treat the 402 as the source of truth for the price and the network.Each
acceptsentry comes with a signed offer — a JWS inextensions["offer-receipt"].info.offers[], matched to its entry byacceptIndex. Its payload is what TraceFast commits to before you pay:{ "version": 1, "resourceUrl": "https://mpp.tracefast.xyz/api/v1/chains/1/entities/0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97/attributes", "scheme": "exact", "network": "eip155:8453", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "payTo": "0x…", "amount": "50000", "validUntil": 1790958400 }resourceUrlis the full URL you requested, query string included;validUntilis the Unix time the offer stands until. Keep the offer: it is the signed half that the receipt answers. The 402 also names the method's id, unsigned, inextensions["tracefast-receipt"].info.method— the id the receipt will carry. -
Pay and retry. The client signs an EIP-3009
transferWithAuthorizationforamounttopayToand repeats the same request with the signature in thePAYMENT-SIGNATUREheader. With@x402/fetchthis is automatic:import { wrapFetchWithPaymentFromConfig } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`); const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, { schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }], // Base mainnet }); const res = await fetchWithPayment( "https://mpp.tracefast.xyz/api/v1/chains/1/entities/0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97/attributes" ); console.log(res.status); // 200 console.log(await res.json()); // { data: {...}, meta: {...} } console.log(res.headers.get("PAYMENT-RESPONSE")); // base64 receiptInstall with
npm install @x402/fetch @x402/evm viem. -
Read the receipt. A successful call returns
200with the data and aPAYMENT-RESPONSEheader (base64 JSON). Settlement is on-chain and synchronous, so a paid call takes a few seconds. What the header states is described below.
Read the receipt
Decoded, PAYMENT-RESPONSE carries the settlement and two signed documents:
{
"success": true,
"payer": "0x…",
"transaction": "0x…",
"network": "eip155:8453",
"extensions": {
"offer-receipt": { "info": { "receipt": { "format": "jws", "signature": "eyJhbGciOiJFZERTQSIs…" } } },
"tracefast-receipt": { "info": { "format": "jws", "signature": "eyJhbGciOiJFZERTQSIs…" } }
}
}payer is the wallet that paid, transaction the settlement transaction on
Base. Both signatures are JWS strings; the payload is the middle,
base64url-encoded part.
The x402 receipt
extensions["offer-receipt"].info.receipt is the standard receipt of the x402
offer and receipt extension.
It states that this payer paid for this URL.
| Field | Meaning |
|---|---|
version | Version of the receipt format, 1 |
resourceUrl | The full URL that was requested, query string included — the same string the offer signs |
payer | The wallet that paid |
network | The network of the payment, eip155:8453 |
transaction | Hash of the settlement transaction |
issuedAt | Unix time, in seconds, the receipt was issued |
The TraceFast receipt
extensions["tracefast-receipt"].info is TraceFast's own record of the call:
it binds the payment to the answer that was served.
| Field | Meaning |
|---|---|
version | Version of the record, 1 |
requestId | The id of this call — equal to the answer's X-Request-Id header. Quote it to support |
method | The method's id, as https://mpp.tracefast.xyz/.well-known/x402 lists it |
resourceUrl | The full requested URL — the same string as in the offer and in the x402 receipt |
payer | The wallet that paid |
network | The network of the payment |
asset | The token contract that was paid in |
payTo | The address that was paid |
transaction | Hash of the settlement transaction |
paymentNonce | The nonce of the EIP-3009 authorization you signed — the id of this payment attempt |
quotedAmount | The amount the accepted accepts entry asked for, in base units |
settledAmount | The amount that was moved, in base units |
settledAmountSource | Where settledAmount was read: authorization — the value of your signed authorization (the exact scheme settles exactly that) — or settle, the settlement result |
requirementsSha256 | SHA-256 of the accepted accepts entry in canonical JSON (JCS, RFC 8785) |
status | HTTP status of the answer |
contentType | Content-Type of the answer |
bytes | Length of the answer's body |
bodySha256 | SHA-256 of the answer's body |
issuedAt | Unix time, in seconds, the record was issued |
bytes and bodySha256 are taken over the body after content decoding —
the bytes an HTTP client hands to your code, not the compressed bytes on the
wire. Hash the body as you received it, before parsing it.
The offer carries no request id: it is signed before the request runs;
requestId exists only in the TraceFast receipt. What joins an offer to the
receipts of the call it led to:
resourceUrl— one string in all three documents;requirementsSha256— names theacceptsentry you paid, the one the offer points at withacceptIndex;paymentNonce— the nonce of your own signed authorization.
Verify the signatures
The offer and both receipts are signed with EdDSA (Ed25519), with a key that
is not the payTo wallet's. The JWS header names the key in kid, a
did:web identifier:
{ "alg": "EdDSA", "kid": "did:web:mpp.tracefast.xyz#2026-10" }Resolve the kid at https://mpp.tracefast.xyz/.well-known/did.json — a free
request — and verify against the publicKeyJwk of the entry with that id.
Keys rotate and earlier ones stay published, so always resolve the kid of
the document in hand; do not pin a key.
The x402 SDK resolves the key itself: verifyOfferSignatureJWS checks the
offer, verifyReceiptSignatureJWS either receipt.
import { verifyOfferSignatureJWS, verifyReceiptSignatureJWS } from "@x402/extensions/offer-receipt";
await verifyOfferSignatureJWS({ format: "jws", signature: offerJws });
await verifyReceiptSignatureJWS({ format: "jws", signature: receiptJws });
await verifyReceiptSignatureJWS({ format: "jws", signature: tracefastReceiptJws });Each returns the signed payload and throws if the signature does not verify. All three are plain compact JWS, so any JOSE library verifies them with the same key. A sample to run this against is below.
What is charged
The request runs before the money moves, and the data is released only after the payment settles.
- An answer with data is charged, once, at the offered amount.
- An answer whose data is empty is charged too. An empty list is an answer about the chain: nothing matched.
- An error is not charged. If the method answers with status 400 or above
— a malformed address, a block outside the data — you get that status and
its JSON error body as Conventions describes, no
PAYMENT-RESPONSEheader and no receipt. Your signed authorization is never settled. - A rejected payment is not charged. See below.
A sample to verify
Two real calls on Base mainnet, made on 2026-10-02 and published as they were received. Nothing is redacted — a changed byte would break a signature or the hash — and the payer is a wallet of TraceFast's own. The amounts inside are facts of these two calls, not a price list.
The same bytes as files, under https://docs.tracefast.xyz/samples/x402/2026-10-02/:
| File | What it is |
|---|---|
served/payment-required.b64 | The PAYMENT-REQUIRED header of the 402, as received |
served/offer.jws | The signed offer from that header |
served/payment-response.b64 | The PAYMENT-RESPONSE header of the paid answer, as received |
served/receipt.jws | The x402 receipt |
served/tracefast-receipt.jws | The TraceFast receipt |
served/body.json | The body of the paid answer |
refused/payment-required.b64 | The PAYMENT-REQUIRED header of the refused call's 402 |
refused/offer.jws | Its signed offer |
refused/body.json | The error body the paid request got |
A paid call that was served
GET https://mpp.tracefast.xyz/api/v1/chains/1/blocks/latest
The offer, from the 402:
eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6bXBwLnRyYWNlZmFzdC54eXojMjAyNi0xMCJ9.eyJhbW91bnQiOiIxMDAwMCIsImFzc2V0IjoiMHg4MzM1ODlmQ0Q2ZURiNkUwOGY0YzdDMzJENGY3MWI1NGJkQTAyOTEzIiwibmV0d29yayI6ImVpcDE1NTo4NDUzIiwicGF5VG8iOiIweDJBNjU0OTFFOTNBZDBkNDg0Yjc0NDA1NDAxQTM4ZTJFMEU1RURkN2UiLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vbXBwLnRyYWNlZmFzdC54eXovYXBpL3YxL2NoYWlucy8xL2Jsb2Nrcy9sYXRlc3QiLCJzY2hlbWUiOiJleGFjdCIsInZhbGlkVW50aWwiOjE3OTA5NTg1NjgsInZlcnNpb24iOjF9.jwTRdUHkEFWJP78Y0dnZi2rCJyTPj7dXorFXPE9p-VlHrhPf0Dqw3-2HH0WXswtZwNmFyaRwC_woSS8RcKzMBAIts payload:
{
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"network": "eip155:8453",
"payTo": "0x2A65491E93Ad0d484b74405401A38e2E0E5EDd7e",
"resourceUrl": "https://mpp.tracefast.xyz/api/v1/chains/1/blocks/latest",
"scheme": "exact",
"validUntil": 1790958568,
"version": 1
}The paid answer: status 200, X-Request-Id: 01a0fd6e-729d-7711-b362-0acbaf50d173, and
this body, 1155 bytes:
{"data":{"chainId":1,"number":26105813,"hash":"0x6255d2f14d40747304d0e60fabfa2088d640485c9fa917dfc41b3b0bf4ae398a","parentHash":"0xbcf3fd1cb817d6ab60c3cc5d97e04472e41027384abdd812bf48cf615812cafb","timestamp":1790958263,"feeRecipient":"0xdadb0d80178819f2319190d340ce9a924f783711","stateRoot":"0xaec925a22431289cdb666f9b2c00ae078b5bb108bae0a6ebdc36f815d7f108e2","transactionsRoot":"0xb769d125aa61f479ee56fc78520c50e5739782f63ed5b5eb67f8d87aabf8160a","receiptsRoot":"0x7a83d954104e9f3c48b18e6dd493b71f6495ce79045c9e7f2b445a8322aa0f6a","gasLimit":"60000000","gasUsed":"27110211","baseFeePerGas":"401371541","blobGasUsed":"2097152","excessBlobGas":"197738163","txCount":288,"successfulTxCount":286,"failedTxCount":2,"contractCreationCount":0,"blobTxCount":4,"logCount":718,"totalWithdrawalGwei":"224997063","totalValueWei":"12169290841988197897","burntFees":"10881267165905151","totalGasFees":"26222353767286005","totalTips":"15341086601380854","difficulty":"0","extraData":"0x4275696c6465724e6574","ommersCount":0},"meta":{"chain":"ethereum","timestamp":1790958269180,"cached":false,"asOfBlock":26105813,"docs":"https://docs.tracefast.xyz/api/block-latest"}}The x402 receipt, from PAYMENT-RESPONSE:
eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6bXBwLnRyYWNlZmFzdC54eXojMjAyNi0xMCJ9.eyJpc3N1ZWRBdCI6MTc5MDk1ODI3MCwibmV0d29yayI6ImVpcDE1NTo4NDUzIiwicGF5ZXIiOiIweDBBZjgzMmMzMzgxOGQ3OTVhN0UzM2ZhMDc3REY1Q2MyNzAyYzU2ZGEiLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vbXBwLnRyYWNlZmFzdC54eXovYXBpL3YxL2NoYWlucy8xL2Jsb2Nrcy9sYXRlc3QiLCJ0cmFuc2FjdGlvbiI6IjB4MGQzMWRkZTk2MWE4OTUyYzhjYTdjYmM3YWJkMzdhNjg4MjhmMGQ5NmExNDZkZGYyZDkyNzE4YzM4MGQxZGViZCIsInZlcnNpb24iOjF9.WlTTjpcBFniITtwj5CJd-p35urKZljV384U3PNOfziJrXFd1no3JzsaFjpSb4KVSAVKyLKHm275KLT4fy840AwIts payload:
{
"issuedAt": 1790958270,
"network": "eip155:8453",
"payer": "0x0Af832c33818d795a7E33fa077DF5Cc2702c56da",
"resourceUrl": "https://mpp.tracefast.xyz/api/v1/chains/1/blocks/latest",
"transaction": "0x0d31dde961a8952c8ca7cbc7abd37a68828f0d96a146ddf2d92718c380d1debd",
"version": 1
}The TraceFast receipt, from the same header:
eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6bXBwLnRyYWNlZmFzdC54eXojMjAyNi0xMCJ9.eyJhc3NldCI6IjB4ODMzNTg5ZkNENmVEYjZFMDhmNGM3QzMyRDRmNzFiNTRiZEEwMjkxMyIsImJvZHlTaGEyNTYiOiIzM2E1ZWQ1OGRlY2Q1NjcxMDI5MWNhMjhkMDMwZDQyNjMwMTI3MDE0NjZhNmJmNzc1MGQ5Y2E4MDNmNTA0MGIyIiwiYnl0ZXMiOjExNTUsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImlzc3VlZEF0IjoxNzkwOTU4MjcwLCJtZXRob2QiOiJibG9jay1sYXRlc3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJwYXlUbyI6IjB4MkE2NTQ5MUU5M0FkMGQ0ODRiNzQ0MDU0MDFBMzhlMkUwRTVFRGQ3ZSIsInBheWVyIjoiMHgwQWY4MzJjMzM4MThkNzk1YTdFMzNmYTA3N0RGNUNjMjcwMmM1NmRhIiwicGF5bWVudE5vbmNlIjoiMHgwNzNmMTNiYzc5MjU5MTM4NDEyYTA5ZWE0MjhiMzJjYjYyNDljNjQxYjk3YjQ4M2ZiYTcxOWNmNmY1ODAyYWE2IiwicXVvdGVkQW1vdW50IjoiMTAwMDAiLCJyZXF1ZXN0SWQiOiIwMWEwZmQ2ZS03MjlkLTc3MTEtYjM2Mi0wYWNiYWY1MGQxNzMiLCJyZXF1aXJlbWVudHNTaGEyNTYiOiI3MDllM2IyNjg5NTRiNTZlNDRkNzhlMmU1Y2FiNjRjYjZiYTZjNmRiNGQzOTU5M2E0MjA1YjFiNjY5ZDZmNWFlIiwicmVzb3VyY2VVcmwiOiJodHRwczovL21wcC50cmFjZWZhc3QueHl6L2FwaS92MS9jaGFpbnMvMS9ibG9ja3MvbGF0ZXN0Iiwic2V0dGxlZEFtb3VudCI6IjEwMDAwIiwic2V0dGxlZEFtb3VudFNvdXJjZSI6ImF1dGhvcml6YXRpb24iLCJzdGF0dXMiOjIwMCwidHJhbnNhY3Rpb24iOiIweDBkMzFkZGU5NjFhODk1MmM4Y2E3Y2JjN2FiZDM3YTY4ODI4ZjBkOTZhMTQ2ZGRmMmQ5MjcxOGMzODBkMWRlYmQiLCJ2ZXJzaW9uIjoxfQ.krTJQIsNAztU2cgE6tcXU5poF8UgKM6dBFFl8rrciOPDolafaM9gLnY7YocN4E78IpFeuih-_Tqflg0NWgrqAwIts payload:
{
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"bodySha256": "33a5ed58decd56710291ca28d030d4263012701466a6bf7750d9ca803f5040b2",
"bytes": 1155,
"contentType": "application/json",
"issuedAt": 1790958270,
"method": "block-latest",
"network": "eip155:8453",
"payTo": "0x2A65491E93Ad0d484b74405401A38e2E0E5EDd7e",
"payer": "0x0Af832c33818d795a7E33fa077DF5Cc2702c56da",
"paymentNonce": "0x073f13bc79259138412a09ea428b32cb6249c641b97b483fba719cf6f5802aa6",
"quotedAmount": "10000",
"requestId": "01a0fd6e-729d-7711-b362-0acbaf50d173",
"requirementsSha256": "709e3b268954b56e44d78e2e5cab64cb6ba6c6db4d39593a4205b1b669d6f5ae",
"resourceUrl": "https://mpp.tracefast.xyz/api/v1/chains/1/blocks/latest",
"settledAmount": "10000",
"settledAmountSource": "authorization",
"status": 200,
"transaction": "0x0d31dde961a8952c8ca7cbc7abd37a68828f0d96a146ddf2d92718c380d1debd",
"version": 1
}What you can check without trusting this page:
-
All three signatures verify with the key resolved from their
kid. -
resourceUrlis one string in the offer and in both receipts, and it is the URL that was requested. -
The offer's
amount,quotedAmountandsettledAmountare equal. -
requestIdequals the answer'sX-Request-Id. The offer has no request id. -
bodySha256is the SHA-256 of the body, andbytesits length:curl -s https://docs.tracefast.xyz/samples/x402/2026-10-02/served/body.json | sha256sum # 33a5ed58decd56710291ca28d030d4263012701466a6bf7750d9ca803f5040b2 -
requirementsSha256is the SHA-256 of the 402'saccepts[0]in canonical JSON. -
transactionis a USDC transfer on Base frompayertopayTo, and the USDC contract answerstruetoauthorizationState(payer, paymentNonce): the authorization was used.
import { verifyOfferSignatureJWS, verifyReceiptSignatureJWS } from "@x402/extensions/offer-receipt";
const base = "https://docs.tracefast.xyz/samples/x402/2026-10-02/served";
const jws = async (name: string) => (await (await fetch(`${base}/${name}`)).text()).trim();
// The key is resolved from each document's kid; none is passed by hand.
await verifyOfferSignatureJWS({ format: "jws", signature: await jws("offer.jws") });
await verifyReceiptSignatureJWS({ format: "jws", signature: await jws("receipt.jws") });
await verifyReceiptSignatureJWS({ format: "jws", signature: await jws("tracefast-receipt.jws") });A paid call that was refused
GET https://mpp.tracefast.xyz/api/v1/chains/1/transactions/0x00 — 0x00
is not a transaction hash, so the method refuses the request.
The offer, from the 402:
eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6bXBwLnRyYWNlZmFzdC54eXojMjAyNi0xMCJ9.eyJhbW91bnQiOiIxMDAwMCIsImFzc2V0IjoiMHg4MzM1ODlmQ0Q2ZURiNkUwOGY0YzdDMzJENGY3MWI1NGJkQTAyOTEzIiwibmV0d29yayI6ImVpcDE1NTo4NDUzIiwicGF5VG8iOiIweDJBNjU0OTFFOTNBZDBkNDg0Yjc0NDA1NDAxQTM4ZTJFMEU1RURkN2UiLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vbXBwLnRyYWNlZmFzdC54eXovYXBpL3YxL2NoYWlucy8xL3RyYW5zYWN0aW9ucy8weDAwIiwic2NoZW1lIjoiZXhhY3QiLCJ2YWxpZFVudGlsIjoxNzkwOTU4NTYyLCJ2ZXJzaW9uIjoxfQ.2Vi4Osfw63sV46xPPWIg2zSeLzRe_seiG7t9ccoN18HKUMPWCEqqgi-eAesU-L1o3M_1l3fbZ2XLNGGtGgaOCgIts payload:
{
"amount": "10000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"network": "eip155:8453",
"payTo": "0x2A65491E93Ad0d484b74405401A38e2E0E5EDd7e",
"resourceUrl": "https://mpp.tracefast.xyz/api/v1/chains/1/transactions/0x00",
"scheme": "exact",
"validUntil": 1790958562,
"version": 1
}The client accepted it and repeated the request with a signed authorization,
nonce 0x42db76c00cf692f469320fa609e14776793b846a610521fd2eff343d5d759e5c.
The answer: status 400, X-Request-Id: 01a0fd6e-5b81-7272-9134-39ff34ad3137, and this
body:
{"error":{"code":"bad_request","details":{"reason":"tx_hash_invalid"},"message":"invalid transaction hash format: expected 0x-prefixed 64 hex chars","requestId":"01a0fd6e-5b81-7272-9134-39ff34ad3137"}}There is no PAYMENT-RESPONSE header and no receipt. The signed
authorization was never settled: the USDC contract answers false to
authorizationState(payer, paymentNonce) for that nonce. Nothing was
charged.
When payment fails
You get a second 402 instead of a 5xx. Its body carries a detail
from the payment facilitator, for example
ERC20: transfer amount exceeds balance for an unfunded wallet, or an expired
authorization. Nothing is charged for a rejected payment, and verification is
free.
Prices and settlement
- Each method has its own price — today between 0.01 and 0.20 USDC per
call, listed in
https://mpp.tracefast.xyz/llms.txt. The method's own402states its price before anything is charged, and it is authoritative. One payment buys one call, whatever itslimit. Over x402 there are no subscriptions, minimums or monthly fees. - Payments settle on Base mainnet through the payment facilitator. One on-chain transaction per paid call.
- TraceFast is listed on Agentic Market, with route templates and prices.
Discovery for agents
Before paying, an agent can read everything it needs for free:
https://mpp.tracefast.xyz/llms.txt— methods and prices in plain text;https://mpp.tracefast.xyz/.well-known/x402— a manifest of every method with its price, as JSON;https://mpp.tracefast.xyz/api/v1/openapi.json— the OpenAPI document;- the Agentic Market listing — the x402 Bazaar catalog, where TraceFast is indexed with its route template, parameters and price.
Related pages
- All methods — every method, its path and what it returns
- API overview — the three ways to call
- Conventions — responses, errors and data freshness
- Connect an AI agent over MCP — the same methods as tools, with a key or a sign-in
Last updated 22 Oct 2026, 08:06 UTC · verified against TraceFast v1.0.261 · Markdown