# 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](/whitepaper.pdf).

## 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)

```json
{
  "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)

```json
{
  "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`

```json
{
  "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`

```json
{
  "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:

```json
{
  "success": true,
  "x402Version": 2,
  "scheme": "aa-native",
  "network": "eip155:1689",
  "transactionHash": "0x...",
  "userOpHash": "0x...",
  "requestHash": "0x...",
  "payer": "0x...",
  "amount": "1000",
  "asset": "0x..."
}
```

Failure:

```json
{
  "success": false,
  "x402Version": 2,
  "errorCode": "user_op_failed",
  "message": "..."
}
```

The full error code list is on the [Errors page](/docs/reference/errors).

## Network identifiers

CAIP-2 strings:

- `eip155:1689` — NERO mainnet
- `eip155: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)))
```
