When a paid request lacks a valid X-PAYMENT header, the API responds with HTTP 402 and a JSON payment requirement using scheme exact_split.

Example 402 response

{
  "error": "payment_required",
  "x402Version": 1,
  "scheme": "exact_split",
  "resource": "POST /p/demo/summarize",
  "description": "Summarize text endpoint",
  "expiresAt": "2026-06-23T12:00:00.000Z",
  "nonce": "<random>",
  "requestHash": "<sha256>",
  "paymentRequirementId": "<convex id>",
  "accepts": [
    {
      "chain": "sui",
      "network": "mainnet",
      "asset": "USDC",
      "totalAmount": "0.002",
      "decimals": 6,
      "coinType": "0x...::usdc::USDC",
      "splits": [
        { "recipientType": "provider", "payTo": "0xprovider...", "amount": "0.0019" },
        { "recipientType": "platform", "payTo": "0xplatform...", "amount": "0.0001" }
      ]
    },
    {
      "chain": "solana",
      "network": "mainnet",
      "asset": "USDC",
      "totalAmount": "0.002",
      "decimals": 6,
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "splits": [
        { "recipientType": "provider", "payTo": "ProviderSolana...", "amount": "0.0019" },
        { "recipientType": "platform", "payTo": "PlatformSolana...", "amount": "0.0001" }
      ]
    }
  ],
  "cost": {
    "inference": { "amount": "0.002", "asset": "USDC" },
    "total": { "amount": "0.002", "asset": "USDC" },
    "pricingSourceVersion": "2026-06-20"
  }
}

Important fields

Field Purpose
scheme Always exact_split — atomic multi-leg USDC payment
accepts Payment options per chain; SDK selects one matching your chain config
accepts[].splits[] Provider and platform legs (recipientType, payTo, amount)
accepts[].totalAmount Sum of all split legs
paymentRequirementId Convex ID binding proof to stored requirement
nonce Single-use identifier; must appear in payment proof
requestHash Binds payment to this exact request — must match on retry
expiresAt Requirement expiry — pay before this timestamp
cost Optional breakdown (endpoint price, platform fee)

Free endpoints (price = 0) may have a single platform split (provider amount 0).

X-PAYMENT header

On retry, the SDK sends a base64-encoded JSON proof:

{
  "x402Version": 1,
  "scheme": "exact_split",
  "chain": "sui",
  "network": "mainnet",
  "asset": "USDC",
  "payer": "<user address>",
  "txHashOrDigest": "<on-chain id>",
  "paymentRequirementId": "<from 402>",
  "nonce": "<from 402>",
  "requestHash": "<from 402>",
  "expiresAt": "<from 402>"
}

Use encodePaymentProof() and decodePaymentProof() from the SDK if building custom integrations. Use buildPaymentProof() to construct proofs consistently.

Request hash binding

The requestHash binds payment to:

This prevents reusing payment on a different route, body, or pricing mode.

SDK selection

The SDK calls selectPaymentOption(requirement, chain) to pick the matching accept option. If your chain is not in accepts, you get unsupported_chain.

Your wallet adapter's pay() must send one atomic transaction covering all split legs.

Next steps