Skip to content

Facilitator API

The facilitator is a public, account-less REST service that verifies and settles canonical x402 payments. Anyone can call the public endpoints — no API key required.

Base URL: https://x402.0xgasless.com — one URL for all networks, mainnet and testnet alike. The chain is chosen per request via paymentRequirements.chainId (or network slug); there is no separate testnet facilitator.

MethodPathPurpose
GET/HTML homepage
GET/healthLiveness check + relayer addresses + supported tokens per chain
GET/listSupported chains + known tokens
GET/tokensSupported tokens per chain with settlement mode (EIP-3009 vs A402) and how to pay
GET/apiThis endpoint reference, as JSON
GET/identity/infoChains with ERC-8004 sponsored registration
POST/verifyVerify a payment signature (no on-chain submit)
POST/settleSubmit a payment on-chain. Facilitator pays gas.

There are also platform-internal endpoints under /identity/* that require an admin key and are only used by the 0xGasless agent platform. They aren’t documented here because external clients don’t need them.

Liveness probe. Returns 200 with chain + relayer details if all configured chains are reachable.

Terminal window
curl https://x402.0xgasless.com/health
{
"status": "healthy",
"service": "x402-facilitator",
"chains": [
{
"chainId": 43114, "name": "avalanche", "relayer": "0x6c2d1A79...a993f1",
"tokens": [
{ "symbol": "USDC", "address": "0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e" },
{ "symbol": "USDT", "address": "0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7" },
{ "symbol": "USDT.e", "address": "0xc7198437980c041c805a1edcba50c1ce5db95118" },
{ "symbol": "USDC.e", "address": "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664" },
{ "symbol": "XSGD", "address": "0xb2f85b7ab3c2b6f62df06de6ae7d09c010a5096e" }
]
},
{
"chainId": 43113, "name": "avalanche-fuji", "relayer": "0x6c2d1A79...a993f1",
"tokens": [
{ "symbol": "USDC", "address": "0x5425890298aed601595a70ab815c96711a31bc65" },
{ "symbol": "XSGD", "address": "0xd769410dc8772695a7f55a304d2125320a65c2a5" }
]
},
{
"chainId": 8453, "name": "base", "relayer": "0x6c2d1A79...a993f1",
"tokens": [
{ "symbol": "USDC", "address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" }
]
}
],
"tokenDetails": "/tokens"
}

For the settlement mode of each token (does it need an approve first? which EIP-712 domain do I sign?), use GET /tokens.

Enumerate supported chains and the tokens the facilitator knows about. Used by clients to discover networks at runtime.

Terminal window
curl https://x402.0xgasless.com/list
{
"facilitator": "x402",
"version": "2.0.0",
"networks": [
{
"network": "avalanche",
"chainId": 43114,
"aliases": ["avalanche-mainnet", "avax"],
"isTestnet": false,
"relayerContract": "0x457Db7ceBAdaF6A043AcE833de95C46E982cEdC8",
"explorer": "https://snowtrace.io",
"supportedAssets": [
{
"asset": "0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e",
"symbol": "USDC",
"name": "USD Coin",
"decimals": 6,
"network": "avalanche"
}
// …
]
}
// … avalanche-fuji, base
],
"features": [
"gasless-payments",
"eip712-signatures",
"eip3009-canonical",
"multi-chain",
"evm"
]
}

The user-facing token support listing. For every chain, every supported token plus how it settles — this is the endpoint to check before integrating a new token.

Terminal window
curl https://x402.0xgasless.com/tokens
{
"service": "x402-facilitator",
"chains": [
{
"network": "avalanche",
"chainId": 43114,
"isTestnet": false,
"tokens": [
{
"symbol": "USDC",
"name": "USD Coin",
"address": "0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e",
"decimals": 6,
"settlement": "eip3009", // one signature, gasless, NO approve
"approveRequired": false,
"eip712Domain": { "name": "USD Coin", "version": "2" }
},
{
"symbol": "XSGD",
"name": "XSGD",
"address": "0xb2f85b7ab3c2b6f62df06de6ae7d09c010a5096e",
"decimals": 6,
"settlement": "eip3009",
"approveRequired": false,
"eip712Domain": { "name": "XSGD", "version": "2" }
},
{
"symbol": "USDT",
"name": "Tether USD",
"address": "0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7",
"decimals": 6,
"settlement": "a402", // payer must approve() the relayer once
"approveRequired": true,
"relayerContract": "0x457Db7ceBAdaF6A043AcE833de95C46E982cEdC8"
}
// …
]
}
// … avalanche-fuji, base
],
"howToPay": ""
}

Reading the response:

  • settlement: "eip3009" — the token natively supports transferWithAuthorization. Sign a TransferWithAuthorization typed message under the token’s own EIP-712 domain: the eip712Domain name/version from the response, chainId of the chain, and verifyingContract = the token address. POST it to /settle. No approve, no gas, one signature.
  • settlement: "a402" — the token has no EIP-3009 support. The payer must approve() the listed relayerContract once, and signs under the A402 relayer domain (name: "A402", version: "1", verifyingContract: relayerContract) instead.
  • Tokens not in this list are still accepted: the facilitator probes EIP-3009 support on-chain at request time and falls back to the A402 path if absent.

The listing is computed with the same detection logic /verify and /settle use, so it always matches actual settlement behavior.

Verify that a signed authorization is well-formed and currently valid. Doesn’t submit on-chain, doesn’t consume gas, doesn’t burn the nonce.

Use it to gate access to a paid resource without actually moving funds yet.

{
"paymentPayload": {
"token": "0x5425890298aed601595a70AB815c96711a31Bc65", // USDC on Fuji
"payload": {
"authorization": {
"from": "0xb0e6ec46cd2d97de006f9318ac5c7994b7aadd2b",
"to": "0xMerchant...",
"value": "500000", // atomic units
"validAfter": 1781000040,
"validBefore": 1781000340,
"nonce": "0x..." // 32 bytes hex
},
"signature": "0x..." // 65 bytes hex
}
},
"paymentRequirements": {
"chainId": 43113, // preferred — unambiguous
"network": "fuji" // alternative — slug
}
}

Success:

{
"isValid": true,
"payer": "0xb0e6ec46cd2d97de006f9318ac5c7994b7aadd2b"
}

Failure:

{
"isValid": false,
"invalidReason": "Invalid signature"
}

Common invalidReason values:

ReasonMeaning
Invalid signatureThe signature doesn’t recover to the from address under either the token’s EIP-712 domain or the A402 relayer domain.
Nonce already usedThe authorization has already been settled. Nonces are single-use per (payer, token).
Authorization not yet validnow < validAfter. Clock skew or scheduled payment.
Authorization expirednow ≥ validBefore. Sign a new one.
StatusBodyMeaning
400{ isValid: false, invalidReason: "Missing paymentPayload or paymentRequirements" }Malformed request.
400{ isValid: false, invalidReason: "Unsupported chain ..." }The chain isn’t registered with this facilitator.
500{ isValid: false, invalidReason: "Verification failed" }An RPC node or chain hiccupped. Retry.

Submit the authorization on-chain. The facilitator’s relayer wallet pays the gas. Returns the transaction hash on success.

Use this when you’ve verified the authorization (or trust the source) and want to actually move the funds.

Same shape as /verify.

Success:

{
"success": true,
"transaction": "0x5972437a3695b2641855416da6b7f936ceda300c7536189a5dc237e1cc21a8e7",
"network": "avalanche-fuji",
"payer": "0xb0e6ec46cd2d97de006f9318ac5c7994b7aadd2b",
"blockNumber": 56206516
}
StatuserrorReasonMeaning
400Invalid signature (not valid under token or A402 domain)Sign with the right domain. For canonical x402, sign against the token’s own EIP-712 domain.
400No A402Relayer configured on this chainThe chain only supports the canonical scheme; sign against the token domain.
500... revert reason ...The on-chain call reverted. Common causes: payer has insufficient USDC balance; payer hasn’t approved the relayer (only relevant for non-EIP-3009 tokens); nonce already consumed.

The facilitator does a pre-broadcast signature check, so a bad signature never costs the facilitator gas.

Public read of which chains support ERC-8004 sponsored registration. Useful if you’re building a UI that shows identity options.

Terminal window
curl https://x402.0xgasless.com/identity/info
{
"sponsoredRegistration": "enabled",
"chains": [
{
"chain": "avalanche",
"chainId": 43114,
"registry": "0x06d49e79da8a241dd2c412bf5d22e19c619a39d1",
"sponsor": "0x6c2d1A79...a993f1",
"explorer": "https://snowtrace.io"
},
{
"chain": "avalanche-fuji",
"chainId": 43113,
"registry": "0x372d406040064a9794d14f3f8fec0f2e13e5b99f",
"sponsor": "0x6c2d1A79...a993f1",
"explorer": "https://testnet.snowtrace.io"
}
]
}

To actually register an agent identity, use client.identity.link() on the Agent SDK. The underlying POST /identity/register is platform-internal.

The facilitator returns permissive CORS headers (Access-Control-Allow-Origin: *) so it’s safe to call from browser code.

100 requests / minute / IP (default). Hitting the cap returns 429 Too many requests, please try again later.

If you need higher throughput, self-host or contact us.

A full pay-an-x402-endpoint flow using /settle directly. The hardest part is building the EIP-3009 signature off-chain. The Agent SDK does this for you; if you’re rolling it yourself, you’ll need to sign the typed data using whatever wallet library you prefer.

Terminal window
# Once you have a signed payload (somehow), submit it to the facilitator
curl -X POST 'https://x402.0xgasless.com/settle' \
-H 'Content-Type: application/json' \
-d '{
"paymentPayload": {
"token": "0x5425890298aed601595a70AB815c96711a31Bc65",
"payload": {
"authorization": {
"from": "0xb0e6...dd2b",
"to": "0xMerchant...",
"value": "500000",
"validAfter": 1781000040,
"validBefore": 1781000340,
"nonce": "0x..."
},
"signature": "0x..."
}
},
"paymentRequirements": { "chainId": 43113 }
}'