> ## Documentation Index
> Fetch the complete documentation index at: https://docs.faremeter.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Protocol Versions

> Differences between x402 v1 and v2, and how to migrate.

x402 has two protocol versions. **Version 2 is preferred for new integrations.** Faremeter supports both versions simultaneously, and the middleware can serve v1 and v2 clients at the same time.

## At a glance

|                                 | v1                            | v2                                            |
| ------------------------------- | ----------------------------- | --------------------------------------------- |
| **Client header**               | `X-PAYMENT`                   | `PAYMENT-SIGNATURE`                           |
| **Server requirement header**   | *(in response body only)*     | `PAYMENT-REQUIRED`                            |
| **Server response header**      | `X-PAYMENT-RESPONSE`          | `PAYMENT-RESPONSE`                            |
| **Payload location**            | Base64-encoded JSON in header | Base64-encoded JSON in header                 |
| **Payload includes `accepted`** | No                            | Yes — echoes the requirement the client chose |
| **Status**                      | Supported                     | **Preferred**                                 |

## Version 1

In v1, the server returns payment requirements in the `402` response body as JSON:

```json theme={null}
{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "solana-devnet",
      "asset": "USDC",
      "maxAmountRequired": "10000",
      "payTo": "7xKX..."
    }
  ]
}
```

The client sends its payment proof in the `X-PAYMENT` header:

```
X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwi...
```

The decoded payload contains:

```json theme={null}
{
  "x402Version": 1,
  "scheme": "exact",
  "network": "solana-devnet",
  "payload": { /* scheme-specific proof */ }
}
```

## Version 2

v2 uses dedicated HTTP headers for the payment protocol, separating payment data from the response body.

The server returns requirements in both the response body and the `PAYMENT-REQUIRED` header. On successful payment, it includes a `PAYMENT-RESPONSE` header with the settlement result.

The client sends its payment proof in the `PAYMENT-SIGNATURE` header. The v2 payload includes the `accepted` requirement the client chose, plus resource information:

```json theme={null}
{
  "x402Version": 2,
  "payload": { /* scheme-specific proof */ },
  "resource": { "url": "https://api.example.com/data", "method": "GET" },
  "accepted": {
    "scheme": "exact",
    "network": "solana-devnet",
    "asset": "USDC",
    "maxAmountRequired": "10000",
    "payTo": "7xKX..."
  }
}
```

Including the `accepted` requirement in the payload lets the facilitator verify that the client is paying for the correct requirement without relying on the server to re-send it.

## Configuring version support

The middleware uses `resolveSupportedVersions()` to determine which protocol versions to serve. By default, v1 is enabled and v2 is disabled.

```typescript theme={null}
import { resolveSupportedVersions } from "@faremeter/middleware/common"

// Default: v1 enabled, v2 disabled
const versions = resolveSupportedVersions()

// Enable both
const versions = resolveSupportedVersions({ x402v1: true, x402v2: true })

// v2 only
const versions = resolveSupportedVersions({ x402v1: false, x402v2: true })
```

Pass this to `createMiddleware` or `handleMiddlewareRequest`:

### With `createMiddleware` (Express)

```typescript theme={null}
import { createMiddleware } from "@faremeter/middleware/express"

app.use(
  "/api/protected",
  await createMiddleware({
    facilitatorURL: "https://facilitator.corbits.dev",
    accepts,
    supportedVersions: resolveSupportedVersions({ x402v1: true, x402v2: true }),
  }),
)
```

### With `handleMiddlewareRequest`

```typescript theme={null}
import { handleMiddlewareRequest, resolveSupportedVersions } from "@faremeter/middleware/common"

await handleMiddlewareRequest({
  facilitatorURL: "https://facilitator.corbits.dev",
  accepts,
  supportedVersions: resolveSupportedVersions({ x402v2: true }),
  resource: req.url,
  // ... other options
})
```

## Migrating from v1 to v2

1. **Enable both versions** during the transition so existing v1 clients continue to work:
   ```typescript theme={null}
   resolveSupportedVersions({ x402v1: true, x402v2: true })
   ```
2. **Update clients** to use the latest `@faremeter/rides` or `@faremeter/fetch`, which automatically negotiate the highest supported version.
3. **Disable v1** once all clients have migrated:
   ```typescript theme={null}
   resolveSupportedVersions({ x402v1: false, x402v2: true })
   ```

## Version adapters

If you are running your own facilitator and need to convert between v1 and v2 formats, use the adapter functions from `@faremeter/types/x402-adapters`:

| Function                               | Direction                      |
| -------------------------------------- | ------------------------------ |
| `adaptPayloadV1ToV2()`                 | v1 payment payload to v2       |
| `adaptPaymentRequiredResponseV1ToV2()` | v1 requirements response to v2 |
| `adaptSettleResponseV1ToV2()`          | v1 settle response to v2       |
| `adaptSettleResponseV2ToV1()`          | v2 settle response to v1       |

<Note>
  `adaptSettleResponseV2ToV1Legacy` is deprecated. Use `adaptSettleResponseV2ToV1` for spec-compliant v1 output.
</Note>

## Further reading

* [How x402 Works](/concepts/how-x402-works) -- The full payment flow.
* [x402 v1 Types API Reference](/api/types.src.Namespace.x402) -- v1 type definitions.
* [x402 v2 Types API Reference](/api/types.src.Namespace.x402v2) -- v2 type definitions.
* [Version Adapters API Reference](/api/types.src.Namespace.x402Adapters) -- Conversion functions.
