Picture this: your agent just received a job from a stranger on the open web. The stranger claims to be a "verified data provider." Before your agent hands over USDC, it wants a second opinion — a fast, cheap, automated trust check. The provider's API returns a 402. Your agent panics. Why is it asking for money? What does it expect? How does the signed authorization actually settle?
We've heard this story from teams shipping autonomous agents in 2026. The 402 dance confuses almost every developer the first time. Here's the thing — once you've watched the bytes move once, the protocol is small. This walkthrough pulls apart our x402 pay-per-call MCP server at evidiq.dev/mcp, the same endpoint your agents hit in production.
The Wire Protocol, Byte by Byte
An x402 pay-per-call MCP server is an HTTP service that exposes Model Context Protocol tools behind a payment wall — each call to a paid tool returns an HTTP 402 challenge, the client signs a one-time authorization, and the server settles it atomically. EVIDIQ runs one at evidiq.dev/mcp, where agents fetch the trust skill or pay per verify_agent call in USDT0.
The full sequence is five steps. No hidden servers, no callbacks, no websockets. Just plain HTTP, exactly the way the EVIDIQ docs describe it.
- The agent sends a normal JSON-RPC POST to
https://evidiq.dev/mcpwithtools/callforverify_agentand a target agent identifier. - Our x402 pay-per-call MCP server returns
HTTP 402 Payment Requiredwith a JSON body containing anacceptsarray. No work happens until the price is paid. - The client parses
accepts[0], signs anEIP-3009TransferWithAuthorizationmessage off-chain, and base64-encodes the signature + payload into anX-PAYMENTheader. - The agent re-sends the original POST, identical except for the new header. Our server validates the signature, checks the nonce against a short-lived store, and submits the on-chain transfer to the settler.
- If settlement succeeds, we execute the real tool (
verify_agent), build the trust report, anchor the evidence on 0G Storage, and return the JSON-RPCresultalong with the receipt headers.
That's it. The retry in step 4 is identical to step 1 — same URL, same body, same headers minus X-PAYMENT. The 402 is the only thing standing between the agent and the answer.
Worth noting: the protocol is stateless from the client's perspective. We don't issue sessions, we don't track cookies, and we don't care if your agent switches IP addresses between requests. The signature binds the payment to a specific amount, recipient, and time window — that's the whole contract.
Reading an accepts[] Object
[IMAGE_PROMPT: A clean modern flat illustration showing a JSON accepts[] object expanding into labeled callouts for scheme, network, amount, asset, payTo, and extra.name/version, drawn in a developer-focused aesthetic with monospace styling, soft teal and amber accent colors, no text other than field labels, no brand logos]
When the 402 lands, your client should parse the body and pick one offer from the accepts array. For our endpoint, the body looks roughly like this:
{
"x402Version": 2,
"accepts": [
{
"scheme": "exact",
"network": "x-layer",
"amount": "100000",
"asset": "USDT0",
"payTo": "0xEVIDIQ...settler",
"extra": {
"name": "USD₮0",
"version": "1"
}
}
]
}
Every field has a job:
scheme— currently"exact"for us. Means the amount in the signature must equalamountexactly. No batching, no streaming, no IOU.network—"x-layer"(X Layer, OKX's L2). The chain id must match what your wallet signs against, or the EIP-712 domain separator will be wrong and the transaction reverts.amount— the price in atomic units. For a singleverify_agentcall we charge100000, which is 0.10 USDT0 given USDT0's 6 decimals.asset— the token contract address. On X Layer, USDT0 lives at a stable address; if you sign against the wrong contract, the transfer reverts at the settler.payTo— the recipient. We route through our settler contract, not a plain EOA, so disputes and batching are possible downstream.extra.name/extra.version— used by EIP-712 domain construction. Change the version and every existing signature breaks.
Get any one wrong and the retry returns a fresh 402 with a different error field, not a 200. We've watched clients fat-finger amount ("0.1" instead of "100000"), use mainnet instead of x-layer, or copy a stale extra.version from old example code. All three produce the same wall: a polite 402 and zero trust report.
EIP-3009 Without the Cryptography Lecture
You don't need to read the yellowpaper. Here's the practical shape.
EIP-3009 lets a wallet sign a TransferWithAuthorization message off-chain that says: "I authorize exactly amount of asset to move from from (me) to to (payTo), and this authorization is valid only until validBefore, and only usable once via nonce." The signature uses EIP-712 typed data — the same format your wallet already shows when you swap on Uniswap.
What that gives us, the server, is gasless authorization. Your agent doesn't need native X Layer gas tokens. It just needs an EVM private key. The signature is a string the client sends in the header. Settlement — actually moving the USDT0 — happens later, paid by us, with a real on-chain transaction.
Our EVIDIQ Operator docs walk through the exact settled transaction path. Briefly: the signed payload is handed to a settler contract that calls transferWithAuthorization on the USDT0 contract. Because the signature already authorized that specific (from, to, value, validBefore, nonce) tuple, the token contract moves the funds and emits a Transfer event. The settler returns the tx hash, which we attach to the receipt.
Honestly? The mental model is "signed check." Your agent writes a check, we cash it once, and the bank (USDT0 contract) refuses any second attempt.
What Happens on a Bad Signature or Late Nonce
[IMAGE_PROMPT: A modern flat illustration of a stylized diagnostic flowchart showing five failure-path branches from a central HTTP 402 node, each branch ending in a labeled terminal state (expired, reused, wrong network, unknown asset, amount drift), drawn in muted slate with bright red accent states, developer wireframe aesthetic, abstract blockchain nodes, no brand logos or text beyond short labels]
Most integrator bugs aren't clever — they're clock skew, copy-paste errors, or aggressive retries. Here's the failure map we've actually seen when teams wire their client to our pay-per-call MCP server, so you can debug your own client without pinging support.
- Expired
validBefore— the signer set a window too short (or your local clock is five minutes behind). The on-chain call reverts withFiatTokenV2_2: authorization is expiredor equivalent. We surface this as a 402 witherror: "invalid_authorization". Fix: regenerate the signature withvalidBefore = now + 60s. - Reused nonce — your retry logic signed once and replayed the same payload. The token contract reverts with
authorization is used. We return a 402 witherror: "nonce_consumed". Fix: never cache signed payloads; sign per call. - Wrong domain separator — usually caused by signing on Ethereum mainnet (
chainId: 1) and posting against X Layer (chainId: 196). EIP-712 binds the domain to a chain; cross-chain replay is structurally rejected. We returnerror: "wrong_network". Fix: pin the EIP-712 domain to X Layer. - Wrong
assetaddress — your client signed for USDC on X Layer instead of USDT0. The token contract at the USDT0 address won't recognize the authorization and reverts. Our server logs this aserror: "unknown_asset". Fix: readassetfrom the 402 body and trust the server. - Amount drift — you signed for
0.1(10^17 wei) but the server expects100000(10^5 units because USDT0 has 6 decimals). The signature validates against the typed data you signed, but the caller's value doesn't match the server'samount, so we reject before submitting. Fix: always parseamountas a string and pass it verbatim to the signer.
Each of these returns a 402, not a 500. That's deliberate — per the EVIDIQ Sentinel docs, every payment failure is a payment decision the client gets to retry, not a server crash. We'd rather your agent see "wrong_network" and fix its chain id than watch the request disappear into a void.
If settlement succeeds, the response includes three receipt headers worth saving: X-PAYMENT-RESPONSE (the settled tx hash on X Layer), X-REPORT-HASH (the keccak256 of the canonical trust report), and X-REPORT-SIGNER (the EVIDIQ address that signed the verdict, recoverable by anyone via EIP-191). Those three headers let a downstream agent prove what it paid for, who said the target was trustworthy, and where the evidence is anchored.