Rails
What each rail needs from the buyer — the account form, the signing request, and the inputs the build reads.
Most pairings need nothing from you beyond the seller's document and your signer. Where a build needs a value only the
buyer can supply (a recent blockhash, an account sequence, a deposit), you pass it in inputs. This page lists, rail by
rail, the account form each pairing accepts, the kind of request your signer receives, and every input the build reads.
A missing or malformed input declines with no-payable-option and a detail ending in /input-missing, before any
fetch of the ATR. Input values are JSON: a decimal is a string of digits ("1000000"), an integer is a JSON
number, hex is 0x followed by hex digits.
The pairings reference gives each pairing's binding export, its Python constant, and what its payment proves. The signers guide gives the answer each request kind takes.
Accounts
The signer's account is CAIP-10. Its namespace selects the pairings it can pay:
| Namespace | Rails | Example |
|---|---|---|
eip155 | EVM chains, Tempo, and MPP's EVM, Tempo and usdc/evm pairings | eip155:84532:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 |
solana | Solana | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:<base58 address> |
stellar, xrpl, hedera, algorand, aptos, sui, near, starknet, polkadot, tron, tvm, cardano, casper, ccd, stacks | The chain of that name (tvm is TON, ccd is Concordium) | <namespace>:<network>:<address> |
lnbtc | Lightning | lnbtc:000000000019d6689c085ae165831e93:<node id> |
cloudflare | x402/batch-settlement/cloudflare, where the account names your agent | cloudflare:402:agent.example |
| any | Card, AP2, UCP, ACP and ACK pairings, where the account names the buyer; MPP's card and Stripe pairings, which do not read it; mpp/charge/nearintents, on the challenge's origin network; mpp/charge/usdc/gateway, on a network the challenge accepts as a Gateway source |
EVM
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/eip155/eip3009 | eip712 | none |
x402/exact/eip155/permit2 | eip712 | none |
x402/exact/eip155/erc7710 | erc7710 | none |
x402/exact/eip155/erc7710-salt | erc7710 | none |
x402/upto/eip155/permit2 | eip712 | none |
x402/auth-capture/eip155/eip3009 | eip712 | none |
x402/auth-capture/eip155/permit2 | eip712 | none |
x402/batch-settlement/eip155 | batch of two eip712: the opening's token authorization, then the first voucher | payerAuthorizer (address, required); deposit (decimal, required unless the option's extra.minDeposit sets it); authSalt (32-byte hex, optional: drawn at random otherwise) |
mpp/charge/evm/authorization | eip712 | tokenDomain (object, required: the token's EIP-712 name and version) |
mpp/charge/evm/permit2 | eip712 | spender (string, required: the seller server's submitting address) |
mpp/charge/evm/transaction | evm-call | none |
mpp/charge/evm/hash | evm-call, broadcast by the signer | none |
mpp/charge/usdc/evm | eip712 | tokenDomain (object, required) |
mpp/charge/usdc/gateway | gateway-burn-intent | none |
mpp/session/evm | two steps: the funding (eip712, or evm-calls broadcast by the signer), then the first voucher (eip712) | deposit (decimal, required); authorizedSigner (address, optional); credentialType (authorization, permit2 or hash, optional); tokenDomain (object, optional) |
Tempo
| Pairing | Request | Inputs |
|---|---|---|
mpp/charge/tempo/memo | tempo-call, or tempo-calls for a charge with splits | clientId (string, optional) |
mpp/charge/tempo/push | tempo-call or tempo-calls, broadcast by the signer | clientId (string, optional) |
mpp/session/tempo | two steps: the signed open transaction (tempo-call), then the first voucher (eip712) | deposit (decimal, required); authorizedSigner, credentialType, tokenDomain (optional) |
mpp/subscription/tempo | tempo-key-authorization | none |
Solana
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/solana | solana-message | decimals (integer) and tokenProgram (string): the mint's; recentBlockhash (string, required unless the option's extra.recentBlockhash is a base58 key of 32 bytes); computeUnitLimit (integer, optional); computeUnitPrice (decimal, optional) |
x402/upto/solana | solana-message | openSlot (decimal), tokenProgram (string), recentBlockhash (string); nonce (decimal, optional: a random u64 otherwise); computeUnitLimit, computeUnitPrice (optional) |
x402/batch-settlement/solana | batch: the opening's solana-message, then the first voucher's ed25519-raw | payerAuthorizer (string), openSlot (decimal), tokenProgram (string); recentBlockhash (unless the option names one); deposit (unless extra.minDeposit sets it); salt, computeUnitLimit, computeUnitPrice (optional) |
mpp/charge/solana | solana-message | decimals, tokenProgram, recentBlockhash, each required only where the request's methodDetails leaves it out (none for native SOL besides the blockhash); computeUnitLimit, computeUnitPrice (optional) |
mpp/charge/usdc/solana | solana-message | as mpp/charge/solana, read from methodDetails.solana |
mpp/session/solana | solana-session-open; with an operator voucher signer, then ed25519-raw for the session proof | deposit (decimal, optional) |
Stellar
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/stellar | stellar-auth | simulatedXdr (string: your simulated transfer transaction), currentLedger (integer) |
mpp/charge/stellar | stellar-auth | simulatedXdr, currentLedger |
The gate passes your account's address to the build as the payer. Before anything reaches your signer, the build
compares the transfer your simulated transaction carries with what the seller asked for, and declines
offer-unreadable when they differ:
| Detail | The simulated transfer |
|---|---|
stellar/asset-mismatch | calls a token contract other than the option's asset (x402) or the request's currency (MPP). |
stellar/amount-mismatch | moves an amount other than the option's or the request's amount exactly. x402's Stellar scheme: argument 2, the amount, "MUST equal requirements.amount exactly". |
stellar/payer-mismatch | is from an account other than yours. |
XRP Ledger
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/xrpl | xrpl-tx | fee (decimal), lastLedgerSequence (integer), and sequence (integer) or, where the option's extra.assetTransferMethod is ticketSequence, ticketSequence (integer) |
mpp/charge/xrpl | xrpl-tx | fee (decimal), sequence (integer), lastLedgerSequence (integer) |
mpp/session/xrpl | xrpl-session-open | deposit (decimal) and xrpl (object): publicKey (hex), settleDelay (integer), fee (decimal), sequence (integer), lastLedgerSequence (integer), cancelAfter (integer, optional) |
An mpp/session/xrpl challenge's amount is the first claim's cumulative total in drops, which the claim signs as a
64-bit unsigned integer. A challenge whose amount is anything but such a number written as a decimal string, with no
sign, point or leading zero, does not offer the pairing (mpp/request-malformed): the gate declines
no-payable-option, and nothing is signed.
Hedera
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/hedera | hedera-body | node (string), validStart (object: seconds decimal, nanos integer), maxFee (decimal); decimals (integer, optional) |
x402/exact/hedera/transfer-executor | hedera-executor | none |
mpp/charge/hedera | hedera-body, broadcast by the signer unless credentialType is "transaction" | node, validStart, maxFee; clientId (string, optional); credentialType (hash, the default, or transaction; optional) |
mpp/session/hedera | hedera-session-open, broadcast by the signer | deposit (decimal) |
Other chains
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/algorand | algorand-txn | params (object: algod's firstValid and minFee and feePerByte as decimals, genesisHash, genesisId) |
x402/exact/aptos | aptos-transaction: the wallet builds and signs the scheme's payment. An answer that is not an object whose transaction is a string is declined signed-not-bound (x402/signature-malformed). The transaction is read as the seller's reference reads it, and declined signed-not-bound with reference's code for each fault: text that is not base64 of a transaction prefix that reads to the end of its fields, or that names a module, function or struct with a name that is not a Move identifier, aptos/tx-malformed; a transaction over 64 KiB decoded, aptos/tx-too-large; a payload that is not an entry function call, aptos/not-entry-function; a call that is not the framework primary_fungible_store::transfer or fungible_asset::transfer with one struct type argument and three arguments, aptos/not-an-x402-transfer; and a transaction for a chain other than the option's network, aptos/chain-mismatch | none |
x402/exact/sui | sui-transaction: the wallet builds the payment and adds the request's pureInput | none |
x402/exact/near | near-delegate | publicKey (string), accessKeyNonce (decimal), finalHeight (decimal): from your RPC |
mpp/charge/nearintents | none: the comparison is the buyer's whole step | none |
x402/exact/starknet | starknet-snip12 | none |
x402/exact/polkadot/lcp-assets-remark | substrate-call | none |
x402/exact/tron/lcp-trc20-memo | tron-txid | refBlock (object: { number, id } of a recent block), feeLimit (decimal) |
x402/exact/tvm | ton-w5 | walletId (integer), seqno (integer), jettonWallet (string), attachNanotons (decimal); stateInit (base64 BoC, for a wallet not yet deployed) |
x402/exact/cardano | cardano-transaction | none |
x402/exact/casper | casper-eip712 | none |
x402/exact/ccd | ccd-transfer | none |
mpp/charge/usdc/stacks | stacks-contract-call | none |
Lightning
| Pairing | Request | Inputs |
|---|---|---|
x402/exact/lnbtc | bolt11-pay | request (object, required): your own request, from which the gate recomputes x402's request hash. For HTTP, { method, url, body?, headers? }; for MCP, { server, name, arguments?, meta? }. |
x402/exact/lnbtc/invoice-named | bolt11-pay | request, as above |
mpp/charge/lightning | bolt11-pay | none |
mpp/session/lightning | bolt11-pay for the deposit invoice | returnInvoice (string, required) |
Your node moves the payment when it pays the invoice. A decline after that carries moved.
On x402/exact/lnbtc/invoice-named the ATR itself names the invoice. The gate pays only when the ATR's bytes are one
JSON object whose first members are atrVersion, id and x402, in that order, with no member name repeated, and
whose x402 slot holds the option's invoice; otherwise it declines offer-unreadable with ln/invoice-not-named
before your node is asked to pay. Every JSON reader then finds the same x402 slot, since RFC 8259 leaves a repeated
name to each reader.
Cloudflare
| Pairing | Request | Inputs |
|---|---|---|
x402/batch-settlement/cloudflare | none: the build is the payment, and your agent's HTTP message signature signs the request that carries it | none |
Cards and Stripe
| Pairing | Request | Inputs |
|---|---|---|
card/visa-tap | tap-field | none |
card/mastercard-vi/immediate | vi-checkout-mandate (the user's L2) | none |
card/mastercard-vi/autonomous | vi-checkout-mandate (the agent's L3b) | none |
card/seller-reference | none: the comparison is the buyer's whole step | none |
mpp/charge/card | none | none |
mpp/charge/stripe | none | none |
mpp/subscription/stripe | none | none |
Mandates and checkouts
| Pairing | Request | Inputs |
|---|---|---|
ap2/checkout-mandate | ap2-checkout-mandate | none |
ucp/checkout/ap2-mandate | ucp-checkout | none |
ucp/booking/ap2-mandate | ucp-checkout | none |
ucp/checkout/unsigned | none | none |
ucp/booking/unsigned | none | none |
acp/checkout/delegated | acp-allowance | max_amount (integer, minor units), currency (string), merchant_id (string), expires_at (string) |
acp/checkout/undelegated | none | none |
ack/payment-request | none | none |
Where the request is "none", confirm returns request: null. For x402/batch-settlement/cloudflare, whose build is
itself the payment, finish with a null signature completes it, and transact returns it as signed. For every
other such pairing, transact returns signed: null once the comparison and, where the pairing needs one, the
agreement payment are done, and the protocol's own flow completes the payment.
Pairings that pay an agreement first
With transact, every pairing whose payment is not itself a public proof of H pays the seller's agreement URL first,
once the buyer's agent has approved that payment. confirm and finish neither pay nor check the agreement; only
transact and agree do (see driving the steps yourself). The
pairings reference marks these pairings, and the
agreement payments guide describes the exchange. The agreement payment's build reads the
same inputs as the payment's own: a Solana agreement option reads the Solana inputs above. Pass agreementSigner to
transact when a different wallet pays the agreement, for example an EVM wallet beside a card.
Last updated on
Keeping the record
What to keep after a payment, how to confirm later that a payment carries the hash of the record you kept, and what to do with a moved payment.
MCP server
Give any MCP client the buyer gate as tools, install the skill that tells the agent how to use them, and serve the tools with your own signer.