Wire format
The HTTP headers and JSON envelope shapes used by x402 V2 and the aa-native scheme.
This page enumerates the wire-format JSON shapes for quick lookup. The full normative definitions are in the whitepaper §2.
HTTP headers
| Header | Direction | Carries (base64url JSON) |
|---|---|---|
PAYMENT-REQUIRED | server → client (on 402) | PaymentRequired |
PAYMENT-SIGNATURE | client → server (on retry) | PaymentPayload |
PAYMENT-RESPONSE | server → client (on 200) | SettlementResponse |
Header names are case-insensitive in HTTP; the canonical casing is uppercase with dashes (PAYMENT-REQUIRED). Implementations should accept either case when reading.
PaymentRequired (the 402 body)
{
"x402Version": 2,
"resource": {
"url": "/api/llm",
"description": "demo paid endpoint"
},
"accepts": [
{
"scheme": "aa-native",
"network": "eip155:1689",
"amount": "1000",
"asset": "0x...",
"payTo": "0x...",
"maxTimeoutSeconds": 60
}
]
}accepts[] is a list. Multi-scheme or multi-asset merchants list all options; the client picks one.
PaymentPayload (the retry body)
{
"x402Version": 2,
"accepted": {
"scheme": "aa-native",
"network": "eip155:1689",
"amount": "1000",
"asset": "0x...",
"payTo": "0x...",
"maxTimeoutSeconds": 60
},
"payload": { /* scheme-specific */ },
"extensions": null
}The accepted block repeats one entry from the merchant's accepts[]. The payload field is opaque per the V2 spec; each scheme defines its inner shape.
payload for aa-native
{
"userOp": {
"sender": "0x...",
"nonce": "0x...",
"initCode": "0x",
"callData": "0x...",
"callGasLimit": "...",
"verificationGasLimit": "...",
"preVerificationGas": "...",
"maxFeePerGas": "...",
"maxPriorityFeePerGas": "...",
"paymasterAndData": "0x...",
"signature": "0x..."
},
"settlementCallSpec": {
"merchant": "0x...",
"token": "0x...",
"amount": "1000",
"requestHash":"0x..."
}
}userOp is a full ERC-4337 v0.6 UserOperation. settlementCallSpec is what the agent claims userOp.callData resolves to; the verifier asserts equality.
payload for exact
{
"signature": "0x...",
"authorization": {
"from": "0x...",
"to": "0x...",
"value": "1000",
"validAfter": 0,
"validBefore": 9999999999,
"nonce": "0x..."
}
}signature is an EIP-712 typed signature over the authorization struct. from is the EOA that owns the source balance.
SettlementResponse (the receipt)
Success:
{
"success": true,
"x402Version": 2,
"scheme": "aa-native",
"network": "eip155:1689",
"transactionHash": "0x...",
"userOpHash": "0x...",
"requestHash": "0x...",
"payer": "0x...",
"amount": "1000",
"asset": "0x..."
}Failure:
{
"success": false,
"x402Version": 2,
"errorCode": "user_op_failed",
"message": "..."
}The full error code list is on the Errors page.
Network identifiers
CAIP-2 strings:
eip155:1689— NERO mainneteip155:689— NERO testnet
The network field carries the CAIP-2 string in both directions of the wire.
Encoding
Headers carry base64url of the UTF-8 bytes of the canonical JSON. URL-safe alphabet (- and _); no padding (=) on the wire. Implementations decode tolerantly (re-add padding to the next multiple of 4 if needed) but emit canonically (no padding).
encoded = base64url_no_pad(utf8(JSON.stringify(value)))