x402 allows AI agents and users to access services that are hard for an AI agent to reach or that take a lot of time. In simple words, an AI agent may need access to some resource, or there may be some information that is hard for it to get. Normally you would need a subscription to that service to access its resources, but does this make sense for AI agents?

AI agents are not humans; they may use a resource only once. So instead of paying a monthly/yearly subscription, the agent just needs one-time access to fill its need, and this is the model x402 adopts.

The x402 protocol allows AI agents to request a given resource only once, by paying a fixed amount and giving the input, and then they receive the output. But how does the actual process work?

Initiating request

x402 is built on HTTP and uses status code 402, the "Payment Required" code. You simply make a GET/POST request to the seller's entry point. Some services require an input, so they use a POST request; others do not require input, so they use a GET request. Once you make this request, you get a reply with the x402 payment header:

http
HTTP/1.1 402 Payment Required
Content-Type: ...
PAYMENT-REQUIRED: <BASE64>
...

The HTTP version depends on the server. Behind a CDN you will often see HTTP/2 402 instead. What matters is the 402 status code and the PAYMENT-REQUIRED header. The body is empty, and everything the agent needs in order to pay is inside that base64 header.

Payment header information

The payment header is encoded in base64. AI agents and servers making the request decode it, and the output looks like this:

json
{
  "x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "http://your-website/entrypoint",
    "description": "What service/data you provide",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:84532",
      "amount": "100000",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "payTo": "0x5164fbAe70634a3e42BC45BD5c7aA46f102bb2E5",
      "maxTimeoutSeconds": 300,
      "extra": {
        "name": "USDC",
        "version": "2"
      }
    }
  ]
}
  • x402Version: this field contains the version of x402. There are currently two versions, 1 and 2. Most well-known x402 sellers now use version 2, and the ones built on v1 are migrating to v2.
  • error: a short, human-readable message explaining why the server returned 402. This field is optional. When the request carries no payment, it contains Payment required; when the agent sent a payment that failed, it contains the reason for the failure instead.
  • resource: this contains the information about the seller's entry point: the URL of the entry point, a free-text description of the service it provides, and the mimeType, which is the format of the data the seller returns after you pay, written as a standard MIME type such as application/json, text/plain or image/png. Only url is required; description and mimeType are optional, and the seller can also add optional fields like serviceName, tags and iconUrl.
  • accepts: this is an array of the payment options the seller accepts. Each object is one complete way to pay (scheme + network + token + amount + receiver), so the same token can appear more than once, for example USDC on Base and USDC on Solana.

Each object in accepts contains these fields:

  • scheme: the payment scheme: exact, upto or batch-settlement. Each type has its own rules, and the seller chooses the best option for its service. The field accepts any string, so more schemes can be added later.
  • network: the network the payment will happen on. It is represented using the CAIP-2 format (namespace:chainId), for example eip155:84532 for Base Sepolia, eip155:8453 for Base mainnet, or solana:... for Solana, which makes it easy to represent both EVM and non-EVM chains.
  • amount: the amount to be paid, written as an integer in the token's smallest unit. USDC has 6 decimals, so "100000" = 0.1 USDC, not 100,000 tokens. With the upto scheme, this is the maximum amount, not the exact charge.
  • asset: the address of the token to be paid with.
  • payTo: the address that should receive the payment.
  • maxTimeoutSeconds: how long, in seconds, the payment stays valid. When the agent signs the payment, the signature expires maxTimeoutSeconds after signing.
  • extra: optional, scheme-specific information. For EVM payments, it holds the token's name and version, which the agent needs to sign the payment correctly.

There can be other fields too, for example extensions, which can contain popular extensions for that seller, like bazaar, which lets the seller publish how to call the endpoint (its input schema and an example output), so AI agents and discovery services can find the service and use it correctly without reading external docs. Sellers can also add their own custom fields.

Signing and sending payment

After this, the buyer, who is the user or the user's AI agent, must create a signature so that the seller can collect the money needed from them. If accepts contains more than one object, the buyer picks one payment option: some sellers accept payment in more than one token, so the buyer takes the one most suitable for them to complete the payment.

The buyer doesn't send the money directly to the payTo address. Instead, they create a signature that allows the facilitator to pull the assets from them and send them to payTo. There are different methods for doing this: the buyer can use authorized payments EIP-3009 if the token supports it, like USDC, or they can use the Permit2 global gateway. On the Solana network, they sign a real transaction.

After creating the payment signature, the buyer requests the seller's entry point again, but this time they add a PAYMENT-SIGNATURE header, which contains the payment details encoded in base64.

The base64-encoded value is a JSON object that contains different fields:

json
{
  "x402Version": 2,
  "payload": {},
  "resource": {},
  "accepted": {},
  "extensions": {}
}
  • x402Version: always present.
  • payload: changes with the scheme and transfer method.
  • resource: optional, copied from the 402.
  • accepted: always present; the accepts item being paid.
  • extensions: optional.

The payload changes according to the payment method, whether you use authorized payments or Permit2. On EVM, it always contains signature, and the other fields differ according to the payment method.

Authorization payment

Authorization payments (EIP-3009) don't need any prior action from the buyer. The payment token contract contains logic that accepts a signature from the buyer, and if the signature is valid, the tokens are sent to the destination address. The facilitator is the one that submits this signature to the token contract.

The payload object:

json
{
  "payload": {
    "authorization": {
      "from": "0x3a34BF3437498102996481325E379FE86F49cEf7",
      "to": "0x5164fbAe70634a3e42BC45BD5c7aA46f102bb2E5",
      "value": "100000",
      "validAfter": "0",
      "validBefore": "1792934576",
      "nonce": "0xbd14b9adc7b5f4a4a7362d132e3fea08ac44dff0197c28692eb6e6a37e6bc9a9"
    },
    "signature": "0xda0748c9c504...91667171c"
  }
}

The authorization payment payload contains authorization, which contains:

  • from: the buyer's address.
  • to: the seller's address (payTo).
  • value: the amount to be sent.
  • validAfter: the payment can only happen after this time.
  • validBefore: the payment must be processed before this time.
  • nonce: a random 32-byte value that makes each signature unique. The token contract records every nonce it has used, so the same signature can never be used twice.

Permit2 payment

Before a Permit2 payment can be processed, the buyer must first give Permit2 approval to access their tokens. Permit2 is a global gateway made by Uniswap that lets users manage and transfer tokens securely just by signing messages from their wallets.

If the buyer has already allowed Permit2 to access their tokens, they are ready to sign. If not, the buyer's wallet must first send an approval transaction to the Permit2 gateway, on the chain of the accepted option, for the token being used to pay. If the seller supports gas sponsoring (the eip2612GasSponsoring or erc20ApprovalGasSponsoring extensions), the buyer can instead sign the approval together with the payment, and the facilitator submits it, so the buyer pays no gas.

The buyer's wallet then signs a Permit2 payment, and this time the payload contains permit2Authorization, which contains:

json
{
  "payload": {
    "permit2Authorization": {
      "from": "0xPayer",
      "permitted": { "token": "0xAsset", "amount": "100000" },
      "spender": "0x402085c248EeA27D92E8b30b2C58ed07f9E20001",
      "nonce": "8391...",
      "deadline": "1792934576",
      "witness": { "to": "0xPayTo", "validAfter": "0" }
    },
    "signature": "0x..."
  }
}

The Permit2 payment is executed by the main x402 Permit2 contracts, x402ExactPermit2Proxy and x402UptoPermit2Proxy, where the facilitator calls the settle function on the contract using the data from the payload the seller got from the buyer.

  • from: the buyer's address.
  • permitted: an object containing the token used for payment and its amount.
  • spender: the contract that is allowed to use this signature to move the tokens. In x402 this is not the seller but the x402 Permit2 proxy contract (x402ExactPermit2Proxy for exact, x402UptoPermit2Proxy for upto), which makes sure the tokens can only go to the to address in the witness.
  • nonce: a random number that makes each signature unique. Permit2 marks it as used once the payment goes through, so the same signature can't be used twice.
  • deadline: the time after which the signature becomes invalid. In most cases, the buyer's wallet sets it to the signing time plus maxTimeoutSeconds.
  • witness: this object adds extra validation to the Permit2 process.

For x402 payments the witness has 2 or 3 fields:

  • to: the receiver address; this is the payTo address in accepts.
  • validAfter: the time after which the signature becomes valid.
  • facilitator: this only exists in upto payments, to prevent anyone else from consuming the maximum amount approved.

Solana

On Solana, the process is different: there is no Permit2, and none of the x402 contracts exist on Solana.

In the case of exact payments, it's a plain SPL Token TransferChecked plus a Memo, partially signed by the buyer, with the facilitator as the fee payer. The fee payer is included in the extra field of the accepted option; this is the facilitator that will pay the transaction fees. The payload contains only the signed transaction, encoded in base64:

json
{
  "payload": {
    "transaction": "AQAAAA...base64 serialized transaction..."
  }
}

Instead of validBefore or deadline, the transaction expires on its own when its recent blockhash gets too old, which takes about a minute or two.

In the case of upto and batch-settlement, the payment goes through the payment-channels program deployed on Solana.

  1. The buyer signs a transaction that opens a channel with the maximum amount to be paid.
  2. Then, the seller signs a voucher for the metered amount to be taken.
  3. The facilitator submits settle_and_seal and then distribute, and the seller is paid the real amount.

In the case of upto, the buyer is refunded the remaining amount and the channel closes. In the case of batch-settlement, the channel is kept open so that it can handle many requests: each request adds to a cumulative voucher, which can be signed by the buyer or the seller, and the facilitator calls settle repeatedly instead of settle_and_seal until the channel is closed.

Verification and settlement

After the buyer prepares the signature, they send it to the seller in the PAYMENT-SIGNATURE header. The seller forwards it to the facilitator, which doesn't execute the transaction as soon as it receives the signature and the payment method.

The facilitator first verifies that the payment is correct:

  • verifying that the payment header is correct and no field is missing.
  • making sure the buyer's wallet chose the correct chain, picked a supported token, and set the recipient address correctly.
  • verifying that the signature belongs to the from address, the amount matches, and the current time is between validAfter and validBefore.
  • simulating the transaction, which is the most important part: the facilitator runs the transaction privately and makes sure that everything goes well and the seller receives their money correctly.

After verification succeeds, the facilitator runs the onchain transaction. The transaction flow differs according to the blockchain, the payment scheme, and the payment method used. Then, the facilitator returns the settlement result, which contains the transaction hash, to the seller.

The seller's handler runs and builds the response, usually right after verification; in most cases, it doesn't wait for settlement. However, some sellers don't create the response until the settlement has happened and succeeded.

Lastly, the seller puts the settlement result in the PAYMENT-RESPONSE header (the transaction hash along with other fields like payer and network), attaches it to the response, and delivers it to the buyer.

If you want to make your AI agents support x402 payments, or you want the ones you have reviewed before they hold funds, get in touch.