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.
{
"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.
{
"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 |
Testnet only
No mainnet deployment, no SLA, no uptime guarantee. Suitable for integration work, not for real value.