Draft v0.1 · open spec · no custody
x402 receipt verification
Verify an x402 payment receipt: amount, asset, network, payee, tx hash, mandate, usage and refund. Proof of Spend v0.1 spec and validator.
Written scope and written report — no calls. No wallet access for the first scan.
200 OK is not a payment
x402 makes payment part of the HTTP request. A 402 challenge is followed by an authorization and a settlement. The response can be 200 while the receipt is wrong, missing, replayed, or for a different payee.
- Amount, asset, network, payee
- Transaction hash and settlement time
- Mandate and expiry
- Usage × unit price
- Refund and remaining amount
- Replay / receipt ID
- Verdict and policy version
- On-chain verification (v0.2)
What the validator checks
schema → signature → mandate expiry → amount → usage × price → refund ≤ payment → verdict = allow → receipt id
v0.1 does not query the chain; it says onchain_verified=false explicitly. That is the honest boundary.
Run it yourself
No account and no key of ours: generate a keypair, sign the example receipt, verify it. Then move the amount by one cent and watch the signature break.
python3 -m nidhipati_proof keygen --out-dir keys
python3 -m nidhipati_proof sign examples/proof-of-spend.example.json --key keys/private.pem
nidhipati-proof verify examples/proof-of-spend.example.json.signed.json --pubkey <b64 from keygen>
# OK
# ✓ schema ✓ signature_alg: Ed25519 ✓ signature: Ed25519
# ✓ mandate_expiry: settled <= expires ✓ usage_amount: quantity * unit_price == amount
# ✓ refund: 0 <= refund <= amount
# after changing the amount by one cent:
# error: signature: invalid
# error: usage: quantity * unit_price does not match payment amount
# exit code 1
Synthetic example; the verification is real, local, and needs no service of ours.
Verify a Proof of Spend receipt in your browser — Ed25519, no upload.