Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

x402 facilitator API

Payment verification and settlement endpoints

A facilitator is a service that verifies x402 payment signatures and settles them on-chain. This page documents the facilitator HTTP endpoints, TypeScript types, headers, status codes, and endorsed facilitators for Radius.

For integration patterns and settlement strategies, see x402 integration.

Endpoints

GET /supported

Returns the facilitator's supported networks, schemes, and signer addresses.

Parameters: None

Response body:
FieldTypeDescription
kindsarrayList of supported payment kinds
kinds[].x402VersionnumberProtocol version (1 or 2)
kinds[].schemestringPayment scheme (for example, exact)
kinds[].networkstringCAIP-2 network identifier
kinds[].extraobjectScheme-specific metadata
kinds[].extra.assetTransferMethodstringTransfer method (for example, erc2612)
kinds[].extra.namestringERC-2612 permit domain name
kinds[].extra.versionstringERC-2612 permit domain version
extensionsarraySupported protocol extensions
signersobjectMap of CAIP-2 patterns to signer addresses
Example response (Radius entries):
{
  "kinds": [
    {
      "x402Version": 2,
      "scheme": "exact",
      "network": "eip155:723487",
      "extra": {
        "assetTransferMethod": "erc2612",
        "name": "Stable Coin",
        "version": "1"
      }
    },
    {
      "x402Version": 2,
      "scheme": "exact",
      "network": "eip155:72344",
      "extra": {
        "assetTransferMethod": "erc2612",
        "name": "Stable Coin",
        "version": "1"
      }
    }
  ],
  "extensions": [],
  "signers": {
    "eip155:*": ["0xdeE710bB6a3b652C35B5cB74E7bdb03EE1F641E6"]
  }
}
Example request:
curl https://x402.stablecoin.xyz/supported

POST /verify

Verifies a payment signature without settling on-chain. Use this endpoint to validate payment data before committing to settlement.

Request body:

The server passes the decoded PAYMENT-SIGNATURE value directly as paymentPayload and adds a paymentRequirements object built from its own config:

FieldTypeDescription
x402VersionnumberProtocol version (2)
paymentPayloadobjectThe decoded client payload from the PAYMENT-SIGNATURE header
paymentPayload.x402VersionnumberProtocol version (2)
paymentPayload.resourceobject(Optional) Resource info echoed from the 402 response
paymentPayload.acceptedobjectThe payment method the client selected
paymentPayload.accepted.schemestringPayment scheme (for example, exact)
paymentPayload.accepted.networkstringCAIP-2 network identifier
paymentPayload.accepted.amountstringPayment amount in raw token units
paymentPayload.accepted.assetstringERC-20 token contract address
paymentPayload.accepted.payTostringRecipient address
paymentPayload.accepted.maxTimeoutSecondsnumberMaximum time the payment is valid
paymentPayload.accepted.extraobjectScheme-specific metadata
paymentPayload.payloadobjectSigned authorization data
paymentPayload.payload.signaturestringSingle 65-byte hex-encoded signature
paymentPayload.payload.authorizationobjectEIP-2612 permit fields
paymentPayload.payload.authorization.fromstringPayer address
paymentPayload.payload.authorization.tostringSpender address (the settlement wallet)
paymentPayload.payload.authorization.valuestringPayment amount in raw token units
paymentPayload.payload.authorization.validAfterstringEarliest valid timestamp
paymentPayload.payload.authorization.validBeforestringLatest valid timestamp
paymentPayload.payload.authorization.noncestringUnique nonce for replay protection
paymentPayload.extensionsobject(Optional) Protocol extensions data
paymentRequirementsobjectExpected payment parameters from the server config
paymentRequirements.schemestringPayment scheme (for example, exact)
paymentRequirements.networkstringCAIP-2 network identifier
paymentRequirements.amountstringRequired amount in raw token units
paymentRequirements.assetstringERC-20 token contract address
paymentRequirements.payTostringExpected recipient address
paymentRequirements.maxTimeoutSecondsnumberMaximum time the payment is valid
paymentRequirements.extraobjectToken permit domain metadata
Response body:
FieldTypeDescription
isValidbooleantrue if the payment signature and balance check pass
payerstringAddress of the payer
invalidReasonstring(Optional) Machine-readable reason for failure if isValid is false
invalidMessagestring(Optional) Human-readable failure message
extensionsobject(Optional) Protocol extensions data
Example request:
curl -X POST https://x402.stablecoin.xyz/verify \
  -H "Content-Type: application/json" \
  -d '{
    "x402Version": 2,
    "paymentPayload": {
      "x402Version": 2,
      "accepted": {
        "scheme": "exact",
        "network": "eip155:723487",
        "amount": "100",
        "asset": "0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb",
        "payTo": "{{MERCHANT_ADDRESS}}",
        "maxTimeoutSeconds": 300,
        "extra": {
          "assetTransferMethod": "erc2612",
          "name": "Stable Coin",
          "version": "1"
        }
      },
      "payload": {
        "signature": "{{SIGNATURE}}",
        "authorization": {
          "from": "{{PAYER_ADDRESS}}",
          "to": "{{MERCHANT_ADDRESS}}",
          "value": "100",
          "validAfter": "0",
          "validBefore": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
          "nonce": "{{NONCE}}"
        }
      }
    },
    "paymentRequirements": {
      "scheme": "exact",
      "network": "eip155:723487",
      "amount": "100",
      "asset": "0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb",
      "payTo": "{{MERCHANT_ADDRESS}}",
      "maxTimeoutSeconds": 300,
      "extra": { "name": "Stable Coin", "version": "1" }
    }
  }'
Example response (success):
{ "isValid": true, "payer": "{{PAYER_ADDRESS}}" }
Example response (failure):
{ "isValid": false, "invalidReason": "insufficient_funds", "invalidMessage": "Payer balance is below the required amount", "payer": "{{PAYER_ADDRESS}}" }

POST /settle

Settles a verified payment on-chain. The request body matches the /verify endpoint. On success, the facilitator submits the permit and transfer transactions to Radius and returns the transaction hash.

Request body: Same as POST /verify. The facilitator splits the signature into v, r, s internally when calling the on-chain permit() function.

Response body:
FieldTypeDescription
successbooleantrue if settlement completed
transactionstringOn-chain transaction hash (empty string if failed)
networkstringCAIP-2 network identifier where settlement occurred
payerstringAddress of the payer
errorReasonstring(Optional) Machine-readable reason for failure if success is false
errorMessagestring(Optional) Human-readable failure message
extensionsobject(Optional) Protocol extensions data
Example request:
curl -X POST https://x402.stablecoin.xyz/settle \
  -H "Content-Type: application/json" \
  -d '{
    "x402Version": 2,
    "paymentPayload": {
      "x402Version": 2,
      "accepted": {
        "scheme": "exact",
        "network": "eip155:723487",
        "amount": "100",
        "asset": "0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb",
        "payTo": "{{MERCHANT_ADDRESS}}",
        "maxTimeoutSeconds": 300,
        "extra": {
          "assetTransferMethod": "erc2612",
          "name": "Stable Coin",
          "version": "1"
        }
      },
      "payload": {
        "signature": "{{SIGNATURE}}",
        "authorization": {
          "from": "{{PAYER_ADDRESS}}",
          "to": "{{MERCHANT_ADDRESS}}",
          "value": "100",
          "validAfter": "0",
          "validBefore": "115792089237316195423570985008687907853269984665640564039457584007913129639935",
          "nonce": "{{NONCE}}"
        }
      }
    },
    "paymentRequirements": {
      "scheme": "exact",
      "network": "eip155:723487",
      "amount": "100",
      "asset": "0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb",
      "payTo": "{{MERCHANT_ADDRESS}}",
      "maxTimeoutSeconds": 300,
      "extra": { "name": "Stable Coin", "version": "1" }
    }
  }'
Example response (success):
{
  "success": true,
  "transaction": "0x...",
  "network": "eip155:723487",
  "payer": "{{PAYER_ADDRESS}}"
}
Example response (failure):
{
  "success": false,
  "errorReason": "insufficient_funds",
  "errorMessage": "Payer balance is below the required amount",
  "transaction": "",
  "network": "eip155:723487",
  "payer": "{{PAYER_ADDRESS}}"
}

GET /health

Returns the facilitator's health status.

Parameters: None

Example request:
curl https://x402.stablecoin.xyz/health

TypeScript types

X402Config

Configuration for x402 payment gating on a server or gateway.

interface X402Config {
  /** ERC-20 token contract address */
  asset: string;
  /** CAIP-2 chain identifier, e.g. "eip155:723487" */
  network: string;
  /** Wallet address that receives payments */
  payTo: string;
  /** Facilitator service base URL */
  facilitatorUrl: string;
  /** Payment amount in raw token units (e.g. "100" = 0.0001 SBC with 6 decimals) */
  amount: string;
  /** Optional API key for the facilitator */
  facilitatorApiKey?: string;
  /** ERC-2612 permit domain name (default: "Stable Coin") */
  tokenName?: string;
  /** ERC-2612 permit domain version (default: "1") */
  tokenVersion?: string;
  /** HTTP header carrying the payment (default: "PAYMENT-SIGNATURE") */
  paymentHeader?: string;
}

PaymentRequired

The object encoded in the PAYMENT-REQUIRED header when a resource requires payment.

interface PaymentRequired {
  x402Version: number;
  error?: string;
  resource: {
    url: string;
    description?: string;
    mimeType?: string;
  };
  accepts: PaymentRequirementsItem[];
  extensions?: Record<string, unknown>;
}

PaymentRequirementsItem

A single accepted payment method within PaymentRequired.accepts.

interface PaymentRequirementsItem {
  scheme: string;
  network: string;
  amount: string;
  asset: string;
  payTo: string;
  maxTimeoutSeconds: number;
  extra: Record<string, unknown>;
}

PaymentOutcome

All possible outcomes of a payment flow, used by server-side middleware to determine HTTP responses.

type PaymentOutcome =
  | { status: 'no-payment'; requirements: PaymentRequired }
  | { status: 'invalid-header' }
  | { status: 'verify-failed'; detail: any }
  | { status: 'verify-unreachable'; detail: string }
  | { status: 'settle-failed'; detail: any }
  | { status: 'settle-unreachable'; detail: string }
  | {
      status: 'settled';
      transaction: string | undefined;
      payer: string;
      network: string;
      verifyMs: number;
      settleMs: number;
      totalMs: number;
    }
  | { status: 'settle-pending'; verifyMs: number; totalMs: number };

HTTP headers

HeaderDirectionDescription
PAYMENT-REQUIREDResponseBase64-encoded PaymentRequired object returned in a 402 response
PAYMENT-SIGNATURERequestBase64-encoded payment payload sent by the client
PAYMENT-RESPONSEResponseBase64-encoded SettleResponse object returned on a 200 after settlement
x-api-keyRequestAPI key for facilitator authentication (required for mainnet)

The client reads the PAYMENT-REQUIRED header from the 402 response, constructs a signed payment, Base64-encodes it, and attaches it as PAYMENT-SIGNATURE on the retry request. On success, the server returns a PAYMENT-RESPONSE header containing the settlement details.

Status code mapping

Each PaymentOutcome status maps to an HTTP status code returned by the server middleware:

PaymentOutcome statusHTTP statusMeaning
no-payment402No PAYMENT-SIGNATURE header present
invalid-header400Malformed PAYMENT-SIGNATURE header
verify-failed402Signature or balance check failed
verify-unreachable502Facilitator /verify endpoint unreachable
settle-failed402On-chain settlement rejected
settle-unreachable502Facilitator /settle endpoint unreachable
settle-pending200Async settlement fired, resource served
settled200Payment confirmed on-chain, resource served

Facilitators supporting Radius

FacilitatorURLRadius networksNotes
Stablecoin.xyzhttps://x402.stablecoin.xyzMainnet + TestnetSBC via EIP-2612, v1 and v2
FareSidehttps://facilitator.x402.rsTestnetFree (testnet only)
Middlebithttps://middlebit.comMainnetMiddleware layer, uses Stablecoin.xyz for settlement

Network reference

PropertyMainnetTestnet
Chain ID72348772344
CAIP-2eip155:723487eip155:72344
SBC token0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb0x33ad9e4bd16b69b5bfded37d8b5d9ff9aba014fb
SBC decimals66
Permit domain nameStable CoinStable Coin
Permit domain version11

Raw token units use 6 decimals. A value of "100" equals 0.0001 SBC. A value of "1000000" equals 1 SBC.

Related pages