# x402 API reference

Three routes, all under `https://api.kryard.com/x402/v1`. **None require
authentication** — no `X-Stamp`, no API key. That's what the x402 spec calls for,
and it's why the facilitator carries hard limits instead.

## `GET /supported`

What this deployment settles. No body.

```json
{
  "kinds": [{ "x402Version": 1, "scheme": "exact", "network": "base-sepolia" }],
  "signers": { "eip155:*": ["0x433ff8253Faa9A57b6326f69Abc8Ad0bf208f5c1"] }
}
```

`signers` is the relayer that fronts gas. One deployment serves **one chain**.

## `POST /verify`

Read-only. Recovers the signature and checks balance, nonce, and validity window
against the chain. Never broadcasts, never costs anyone gas.

```json
{
  "paymentPayload": {
    "x402Version": 1,
    "scheme": "exact",
    "network": "base-sepolia",
    "payload": {
      "signature": "0x…",
      "authorization": {
        "from": "0x…", "to": "0x…", "value": "10000",
        "validAfter": "1753660000", "validBefore": "1753660120",
        "nonce": "0x…32 bytes…"
      }
    }
  },
  "paymentRequirements": {
    "scheme": "exact", "network": "base-sepolia",
    "maxAmountRequired": "10000",
    "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    "payTo": "0x…", "resource": "https://…",
    "maxTimeoutSeconds": 120,
    "extra": { "name": "USDC", "version": "2" }
  }
}
```

→ `{ "isValid": true, "payer": "0x…" }`
or `{ "isValid": false, "invalidReason": "…", "payer": "0x…" }`

## `POST /settle`

Same body. Re-verifies, then broadcasts the payer's `transferWithAuthorization`
with the relayer paying gas.

→ `{ "success": true, "transaction": "0x…", "network": "base-sepolia", "payer": "0x…" }`
or `{ "success": false, "errorReason": "…", "transaction": "", "network": "…", "payer": "0x…" }`

**Idempotent** on `(chain, asset, payer, nonce)`. A repeat returns the original
transaction hash rather than transferring twice — retry safely.

## Reason codes

Returned as `invalidReason` (verify) or `errorReason` (settle).

### The payment itself

| Code | Meaning |
| --- | --- |
| `invalid_request` | Malformed body, or a missing/non-address `authorization.from`. |
| `invalid_exact_evm_signature` | Signature doesn't recover to `from`. Usually a wrong EIP-712 domain. |
| `invalid_exact_evm_recipient_mismatch` | Signed `to` ≠ the `payTo` in `paymentRequirements`. |
| `invalid_exact_evm_insufficient_value` | Signed `value` < `maxAmountRequired`. |
| `invalid_exact_evm_insufficient_balance` | Payer's token balance won't cover it. |
| `invalid_exact_evm_authorization_expired` | Outside `validAfter`…`validBefore`. |
| `invalid_exact_evm_authorization_used` | That nonce is already spent on chain. |

### Facilitator policy

| Code | Meaning |
| --- | --- |
| `x402_policy_disabled` | No enabled policy for this chain. Fail-closed default. |
| `x402_asset_not_allowed` | Asset outside the allowlist. |
| `x402_payto_not_allowed` | Destination outside the allowlist, when one is configured. |
| `x402_amount_below_minimum` | Under the per-settle floor (0.01 USDC). |
| `x402_amount_exceeds_cap` | Over the per-settle ceiling (10 USDC). |
| `x402_daily_gas_cap_exceeded` | Facilitator's 24h gas budget is spent. |
| `x402_monthly_gas_cap_exceeded` | 30-day gas budget is spent. |
| `x402_gas_estimate_unavailable` | Gas couldn't be estimated, so the spend couldn't be bounded. Fails closed. |
| `x402_settlement_in_flight` | The same authorization is mid-settlement. Poll rather than retry hard. |
| `x402_relayer_not_configured` | Operator-side fault: the facilitator's relayer key isn't resolvable. Nothing you can fix as a caller — retry later or report it. |

### Throughput

| Code | HTTP | Meaning |
| --- | --- | --- |
| `x402_rate_limited` | 429 | A limit below was hit. Nothing was reserved or broadcast. |
| `x402_rate_limit_unavailable` | 503 | The limiter couldn't be consulted, so the request was refused. |

## Limits

| Scope | Limit |
| --- | --- |
| `/verify` per IP | 60 / minute |
| `/settle` per IP | 20 / minute |
| `/settle` per payer | 5 / minute |
| `/settle` facilitator-wide | 60 / minute |
| Per-settle amount | 0.01 – 10 USDC |
| Facilitator gas | 0.02 ETH / day · 0.1 ETH / month |

Per-IP limits are charged on **every** request. The payer and facilitator-wide
budgets are charged only after a payment verifies — so a flood of junk can't burn
another payer's allowance or the shared budget.

Gas caps are the operator's spend, not yours. When one is exhausted, settlement
stops until the window rolls.

## Deployment facts

| | |
| --- | --- |
| Base URL | `https://api.kryard.com` |
| Chain | Base Sepolia · `84532` |
| Asset | Testnet USDC `0x036CbD53842c5426634e7929541eC2318f3dCF7e` |
| Scheme | `exact` (EIP-3009 `transferWithAuthorization`) |
| Relayer | `0x433ff8253Faa9A57b6326f69Abc8Ad0bf208f5c1` |
| Auth | None |

::: warning Testnet only
No mainnet deployment, no SLA, no uptime guarantee. Suitable for integration work,
not for real value.
:::
