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 integration

Accept HTTP payments with Radius
View as Markdown

x402 is an HTTP-native payment protocol for paid APIs and paid content.

Your service returns 402 Payment Required with payment requirements, the client signs payment data, and retries with an X-Payment header.

On Radius, this pattern suits micropayments well: transaction costs are low and predictable.

What x402 enables

Per-request API billing — meter each call and settle instantly, no monthly invoices or credit card rails

Pay-per-visit content — gate articles, data feeds, or downloads behind a single micropayment instead of a subscription

Streaming payments — combine x402 with a payment loop to charge continuously for compute, bandwidth, or inference by the second

Request lifecycle

Understanding this flow before writing code makes the endpoint pattern and facilitator role easier to follow.

  1. A client requests a protected resource.
  2. Your service responds with 402 Payment Required and an x402 requirement object.
  3. The client signs payment data and retries with an X-Payment header.
  4. The facilitator verifies and settles the payment on Radius.
  5. Your service returns 200 OK and serves the protected response.

Minimal endpoint pattern

This structure works in a gateway, API server, or edge worker. The key branches are: return 402 with requirements when there's no X-Payment header, verify and settle when there is one, and return 200 on success.

function handleRequest(request):
  if not isProtectedPath(request.path):
    return serveResource(request)
 
  xPayment = request.headers["X-Payment"]
 
  if xPayment is missing:
    requirement = {
      scheme: "exact",
      network: "radius",
      maxAmountRequired: toBaseUnits("0.10"),
      resource: request.url,
      description: "Access to protected resource",
      payTo: "{{MERCHANT_ADDRESS}}",
      asset: "{{TOKEN_ADDRESS}}"
    }
 
    return response(
      status=402,
      headers={ "X-Accept-Payment": stringify(requirement) },
      body={
        error: "Payment required",
        x402Version: 1,
        accepts: [requirement]
      }
    )
 
  result = facilitator.verifyAndSettle(xPayment)
 
  if result.ok is false:
    return response(status=402, body={ error: result.error })
 
  return response(
    status=200,
    body=serveResource(request),
    headers={
      "X-Payment-Verified": "true",
      "X-Payment-Payer": result.payer,
      "X-Payment-Transaction": result.txHash
    }
  )

Sample 402 response

This is the core payload your service returns when payment is required.

{
  "error": "Payment required",
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "radius",
      "maxAmountRequired": "100000000000000000",
      "resource": "https://api.example.com/premium/report",
      "description": "Access to /premium/report",
      "mimeType": "application/json",
      "payTo": "0x{{MERCHANT_ADDRESS}}",
      "asset": "0x{{TOKEN_ADDRESS}}",
      "maxTimeoutSeconds": 300
    }
  ]
}

Choose your facilitator

Use a hosted facilitator when

  • You need the fastest path to production
  • You want lower operational overhead
  • You want to validate product demand before running settlement infrastructure

Build your own facilitator when

  • You need custom policy, risk, or compliance checks
  • You need custom settlement routing or treasury controls
  • You want full ownership of keys, infrastructure, and observability

Stablecoin.xyz hosted facilitator

If you're on the hosted path, Stablecoin.xyz offers a facilitator configured for x402 on Radius:

Token compatibility for x402

The token you use for settlement determines which settlement strategies are available to you. This table compares USDC and SBC against the EIP standards x402 facilitators rely on.

EIP support at a glance

StandardUSDC (FiatTokenV2_2)SBC (Radius native)x402 impact
EIP-20No gap for basic token transfers
EIP-712Typed data signing supported
EIP-2612 (permit)Signature-based approvals supported
EIP-3009 (transferWithAuthorization)Standard one-transaction x402 settlement path is unavailable
EIP-1271 (smart contract wallet signature validation)Smart account compatibility is reduced for signature-based payment flows
EIP-1967 (proxy slots)Not a functional blocker for x402 flow design

Why EIP-3009 matters for x402

EIP-3009 enables direct signed transfer execution via transferWithAuthorization. In practice, that means:

  • one on-chain settlement call
  • no persistent allowance footprint
  • random nonce model that supports concurrent authorizations
  • explicit validity window controls (validAfter and validBefore)

Without EIP-3009, a facilitator falls back to an EIP-2612 pattern:

  1. Submit permit() to set allowance.
  2. Submit transferFrom() to move funds.

That two-transaction path increases gas usage, adds latency, and creates a non-atomic gap where allowance is set before transfer finalizes.

Why EIP-1271 matters

EIP-1271 standardizes signature validation for smart contract wallets. Without it in the token flow, compatibility narrows for smart accounts and multisig-style wallets in signature-based payment patterns.

For teams targeting account abstraction-heavy user bases, this affects wallet support expectations and integration testing scope.

x402 implications on Radius

Given the SBC capability profile, the practical settlement path is:

  • Use a custom facilitator flow based on EIP-2612 permit + transferFrom.
  • Enforce strict nonce, amount, and expiry checks.
  • Implement robust idempotency and replay protection.
  • Monitor settlement outcomes to detect partial or failed two-step execution.

The Radius reference implementation includes both strategy paths and makes permit-transferFrom the baseline fallback when EIP-3009 is not available.

Validation checklist

Before settlement, validate all of the following:

  • scheme matches your expected scheme (for example, exact)
  • network matches Radius
  • asset is the token contract you accept
  • payTo matches your payment address
  • Signed amount is greater than or equal to required amount
  • Signature is valid and signer identity matches payload
  • Nonce and validity window checks pass
  • Payer balance is sufficient
  • Settlement wallet has enough native gas balance

After settlement:

  • Wait for transaction receipt.
  • Return deterministic success metadata.
  • Record idempotency key and tx hash for replay protection.

Facilitator settlement pseudocode

function verifyAndSettlePayment(xPayment, config):
  payment = decodeXPayment(xPayment)
 
  require payment.scheme == "exact"
  require payment.network == config.networkName
  require payment.asset == config.asset
  require payment.payTo == config.paymentAddress
 
  if config.strategy == "permit-transferFrom":
    require payment.payload.kind == "permit-eip2612"
    require payment.payload.spender == config.settlementSpender
    require now < payment.payload.deadline
    require payment.payload.value >= config.requiredAmount
 
    signer = recoverPermitSigner(payment.payload, config.domain)
    require signer == payment.payload.owner
 
    submitPermitTransaction(...)
    assertAllowanceAtLeast(config.requiredAmount)
    txHash = submitTransferFrom(...)
 
    return { ok: true, payer: payment.payload.owner, txHash: txHash }
 
  if config.strategy == "transferWithAuthorization":
    require payment.payload.kind == "eip3009-transfer-with-authorization"
    require payment.payload.to == config.paymentAddress
    require payment.payload.value >= config.requiredAmount
    require payment.payload.validAfter <= now <= payment.payload.validBefore
 
    txHash = submitTransferWithAuthorization(...)
    return { ok: true, payer: payment.payload.from, txHash: txHash }
 
  return { ok: false, error: "Unsupported settlement strategy" }

Radius implementation notes

  • Configure clients and settlement services for Radius network settings.
  • Use Radius-compatible gas handling in your transaction path.
  • Keep settlement wallets funded for native gas.
  • Use short validity windows to reduce replay risk.
  • Add structured logs for verification failures and settlement outcomes.