Skip to main content
x402 paymentsVerifying on-chain proofs
x402 payments

Verifying on-chain proofs

Double-check on-chain payment proof before you ship files, unlock access, or close accounting.

How to belt-and-braces-verify settlement — PAYMENT-RESPONSE header, receipt status, confirmations, recipient and amount checks.

x402 settles after the response is sent. The transaction hash arrives in the PAYMENT-RESPONSEheader on the 200 reply. If you're building anything that needs absolute confirmation — accounting, anti-fraud, post-purchase fulfillment — verify the tx on-chain before treating the order as final.

What you get back

http
HTTP/1.1 200 OKPAYMENT-RESPONSE: {"txHash":"0xfa3c...e0","network":"base","blockNumber":12345678,"settled":true}

The body also includes the same payment record on the order.payment field, so server-side consumers don't need to parse the header.

On-chain check

Verify with any RPC provider for the chosen network.

typescript
import { createPublicClient, http } from "viem";import { base } from "viem/chains"; const client = createPublicClient({ chain: base, transport: http() }); const receipt = await client.getTransactionReceipt({  hash: "0xfa3c...e0",}); if (receipt.status !== "success") {  throw new Error("Settlement failed — void the order locally.");} // Optionally confirm the transferred amount + recipient.const log = receipt.logs.find(  (l) => l.address.toLowerCase() === USDC_BASE.toLowerCase());// Parse the ERC-20 Transfer log: from, to, amount.

What to confirm

  • Network — the tx is on the chain advertised in PAYMENT-RESPONSE.network.
  • Receipt statussuccess, not reverted.
  • Confirmations — enough block depth for your risk tolerance (Base/Polygon: 5+ blocks; Ethereum: 12+).
  • Recipient — the to in the ERC-20 Transfer log matches the merchant's cryptoWalletAddress.
  • Amount — exactly the maxAmountRequired from the challenge.
Aly already verifies, but trust-but-verify
Aly's server validates the EIP-712 signature and rejects invalid/expired payments before the handler runs, and the x402 framework attempts settlement after the response. Your on-chain check is a belt-and-braces step — useful for audit and to catch reorgs or settlement failures.

Refund paths

If settlement fails after a 200 response (rare — usually a reorg or an exhausted-balance race), Aly emits order.refunded via webhook and the order moves to refunded. There is no on-chain refund — settlement simply never completed. If settlement succeeded but the buyer requests a refund, the merchant initiates a manual on-chain return from the dashboard.

Tx schema

The order's payment field has the canonical shape:

json
{  "scheme": "exact",  "network": "base",  "asset": "USDC",  "asset_address": "0x8335...",  "amount": "5000000",  "pay_from": "0x111...",  "pay_to": "0xabc...",  "tx_hash": "0xfa3c...",  "block_number": 12345678,  "confirmed_at": "2026-05-19T08:35:21.000Z"}

Webhooks

Subscribe to order.created (fires when the order is persisted, pre-settlement) and order.refunded (fires if settlement fails or is rolled back). See Webhooks.

Updated

Was this page helpful?