POST /v1/verify

Read a settlement transaction and report the payment inside it. Stores nothing.

POST https://api.x402spend.dev/v1/verify
Content-Type: application/json

This is the question underneath POST /v1/reviews, asked without a claim attached. A review says this payer paid this recipient this amount and is kept only if the transaction proves all three. Here there is nothing to prove: you supply a hash, and the server reports what moved.

Try it in the browser — the form is prefilled with a real settlement.

Request

FieldTypeRequiredNotes
transactionstringyesHash on EVM, signature on Solana
networkstringyesCAIP-2, or a common alias

Strict: no other field is accepted. Spelling is checked per family before any round trip, so a Solana signature sent with base is 422 rather than a wasted RPC call.

{ "transaction": "0x58156f…", "network": "base-sepolia" }

Response

{
  "found": true,
  "network": "eip155:84532",
  "transaction": "0x58156f…",
  "truncated": false,
  "transfers": [
    {
      "asset": "0x036cbd53842c5426634e7929541ec2318f3dcf7e",
      "assetLabel": "USDC",
      "payer": "0xa2290443ca0a5a599dccc14e4db4df5196e91a59",
      "payTo": "0x209693bc6afc0c5328ba36faf03c514ef312287c",
      "amount": "10000",
      "proof": "payment_traced",
      "proofLabel": "payment traced"
    }
  ]
}
FieldNotes
assetContract address on EVM, mint on Solana. Lowercased on EVM
assetLabelUSDC when the asset is that chain's Circle-issued USDC. Absent otherwise
payerAbsent when the chain shows the credit but not its sender
payToThe recipient. On Solana this is the account owner, not the token account
amountAtomic units
proofpayment_traced · receipt_only
proofLabelThe same thing worded for a reader, sent so clients need no copy of the mapping
truncatedtrue when the transaction held more than 20 transfers

assetLabel is only ever set for the chain's own Circle USDC. Any other token is reported by address alone rather than by a name the server would have to guess at.

Found nothing

A transaction that proves no payment is 200 with found: false, not an error — the lookup succeeded and the answer is that there is nothing there.

{ "found": false, "reason": "no ERC-20 Transfer log in this transaction" }

reason uses the same vocabulary as a review rejection: transaction not found, transaction did not succeed on chain, network not supported, transaction has no metadata to verify against, or no ERC-20 Transfer log in this transaction / no SPL token transfer in this transaction.

StatusWhen
200The chain answered — with a payment, or with found: false
422Bad shape, or no RPC endpoint configured for that network
429Over 20 per minute
503The chain could not be reached. detail names the host and the failure

It does not write

This route touches no table. It is a lookup, and one that recorded what it was asked about would be building a log of who checked which transaction. The test suite asserts it by counting rows before and after.

Attribution differs by chain

On EVM every transfer is attributed: the Transfer log names its own sender, so payer is always present and proof is always payment_traced.

On Solana a bare transfer instruction names no authority. When the transaction also carries no balance record for the source account, the transfer is reported with no payer and proof: "receipt_only" — the credit demonstrably happened, and saying so while admitting the sender is unknown is more honest than dropping the transfer or naming a payer the chain did not.