BlockRun

Payment Flow

Step-by-step breakdown of how x402 payments work — from the first unpaid request to on-chain settlement.

Overview

Every x402 payment follows this sequence:

  1. Client sends request without payment
  2. Server returns 402 with payment requirements
  3. Client signs payment authorization
  4. Client retries with signed payment
  5. Server verifies, executes, and settles

Detailed Flow

1
Initial Request

Client sends a normal API request:

curl -X POST https://blockrun.ai/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-5.4", "messages": [...]}'
2
402 Response

Server returns payment requirements:

HTTP/1.1 402 Payment Required
X-Payment-Required: <base64-encoded-requirements>

{
  "error": "Payment Required",
  "price": {"amount": "0.001000", "currency": "USD"}
}

The X-Payment-Required header contains:

{
  "x402Version": 2,
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:8453",
    "amount": "1000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x..."
  }],
  "resource": {
    "url": "https://blockrun.ai/api/v1/chat/completions",
    "mimeType": "application/json"
  }
}
3
Sign Authorization

The client creates an EIP-3009 TransferWithAuthorization signature:

const authorization = {
  from: walletAddress,
  to: paymentDetails.payTo,
  value: paymentDetails.amount,
  validAfter: Math.floor(Date.now() / 1000) - 600,
  validBefore: Math.floor(Date.now() / 1000) + 300,
  nonce: randomBytes32()
};

const signature = await wallet.signTypedData({
  domain: USDC_DOMAIN,
  types: TRANSFER_WITH_AUTHORIZATION_TYPES,
  primaryType: 'TransferWithAuthorization',
  message: authorization
});

The domain and types are the standard EIP-3009 definition for USDC. On Base (chain eip155:8453):

const USDC_DOMAIN = {
  name: 'USD Coin',
  version: '2',
  chainId: 8453,
  verifyingContract: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
};

const TRANSFER_WITH_AUTHORIZATION_TYPES = {
  TransferWithAuthorization: [
    { name: 'from',        type: 'address' },
    { name: 'to',          type: 'address' },
    { name: 'value',       type: 'uint256' }, // amount in micro-USDC (6 decimals)
    { name: 'validAfter',  type: 'uint256' }, // unix seconds
    { name: 'validBefore', type: 'uint256' }, // unix seconds
    { name: 'nonce',       type: 'bytes32' }, // random 32 bytes, single-use
  ],
};

Key points:

  • Private key never leaves the client
  • Authorization expires in 5 minutes (validBefore)
  • Clock skew tolerance of 10 minutes (validAfter)
  • value is micro-USDC: $0.001"1000"
  • The header value is the base64 of the JSON payment payload shown in the next step (btoa(JSON.stringify(payload)))
Paying on Solana

On the Solana gateway (sol.blockrun.ai, network solana:…) the 402 advertises USDC-SPL (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v, 6 decimals) and the authorization is signed for the SPL transfer instead of EIP-3009. The SDKs pick the right scheme automatically from the accepts[] entry.

4
Retry with Payment

Client sends the request again with the PAYMENT-SIGNATURE header (x402 v2):

curl -X POST https://blockrun.ai/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: <base64-encoded-payment>" \
  -d '{"model": "openai/gpt-5.4", "messages": [...]}'

The payment payload contains:

{
  "x402Version": 2,
  "resource": {
    "url": "https://blockrun.ai/api/v1/chat/completions",
    "mimeType": "application/json"
  },
  "accepted": {
    "scheme": "exact",
    "network": "eip155:8453",
    "amount": "1000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x..."
  },
  "payload": {
    "signature": "0x...",
    "authorization": {
      "from": "0x...",
      "to": "0x...",
      "value": "1000",
      "validAfter": "1234567890",
      "validBefore": "1234568190",
      "nonce": "0x..."
    }
  }
}
5
Verify, Execute, Settle

The server:

  1. Verifies the payment signature with the Facilitator
  2. Executes the API request (calls the AI model)
  3. Settles the payment on-chain
Server                          Facilitator                    Blockchain
  |                                 |                              |
  |  1. Verify signature            |                              |
  |-------------------------------->|                              |
  |                                 |                              |
  |  2. Signature valid             |                              |
  |<--------------------------------|                              |
  |                                 |                              |
  |  3. Execute AI request          |                              |
  |  (route to the model)           |                              |
  |                                 |                              |
  |  4. Settle payment              |                              |
  |-------------------------------->|                              |
  |                                 |  5. Execute transfer         |
  |                                 |----------------------------->|
  |                                 |                              |
  |  6. Settlement confirmed        |                              |
  |<--------------------------------|                              |
  |                                 |                              |
  |  7. Return response to client   |                              |

SDK Handling

The SDKs handle this entire flow automatically:

Error Scenarios

Insufficient Balance

If your wallet doesn't have enough USDC:

{
  "error": "Payment verification failed",
  "details": "Insufficient balance"
}

Expired Authorization

If too much time passed between signing and settling:

{
  "error": "Payment verification failed",
  "details": "Authorization expired"
}

Invalid Signature

If the signature doesn't match:

{
  "error": "Payment verification failed",
  "details": "Invalid signature"
}

Timing

Typical payment flow timing:

StepTime
Initial 402 response~50ms
Client signing~10ms
Signature verification~100ms
AI model execution1-30s (varies)
On-chain settlement~2s
Total overhead~200ms

The payment overhead is minimal compared to AI model execution time.

What's next?