The terms hash
termsHash = keccak256(canonical JSON of the hash-covered receipt fields)
Canonicalization follows RFC 8785 (JCS) restricted to the types the
receipt actually uses: strings, booleans, null, safe integers, arrays,
objects. Object keys sort by UTF-16 code units; amounts are fixed
6-decimal strings; timestamps are ISO-8601 UTC with milliseconds; floats
never appear. GET /clearing/receipts/{id} serves the exact canonical
object under receipt; recompute over it and compare with the published
termsHash.
Hash-covered fields, by schema version
The hash-covered set is versioned withschemaVersion. Runtime
fields (everything about the buyer, states, and post-offer timestamps)
are excluded by construction: the canonical object simply does not
contain them. In particular the canonical form has no buyer key at
all (not a buyer object with null fields).
Schema 1.0:
1.1 adds, all hash-covered:
The proof bundle
GET /clearing/receipts/{id}/proof returns a self-contained bundle:
receipt+termsHash: recompute as above.payment: look uptxHashon Base, a USDC transfer of exactlyamountfromfromto the receipt’sescrow.payTo.payment.authorization: present when Backed settled the payment as the x402 facilitator (null for direct transfers observed by the watcher). Verify it independently: recover the signer of the EIP-3009TransferWithAuthorizationtyped data (USDC’s domain on the receipt’s chain) and check it equalsfrom; checkto,value, and that the nonce is consumed on-chain (authorizationState(from, nonce)). Publishing the authorization is safe: a consumed nonce can never be replayed.deliveries: for hash proofs, hash the delivered content and compare; for url proofs, the recorded snapshot status and content hash are Backed’s witness record of what the URL served at post time.resolution.payoutTxs: each leg’s transaction on Base.bundleHash: keccak256 over the canonical JSON of everything above (the attestation itself is excluded).attestation: Backed’s EIP-191 signature overbundleHash, with the signing address echoed asattestation.signer. Check the address against the published attestation address. Ifattestationisnull, the bundle is served unsigned (the attestation key was not configured); treat it as unattested data and rely on the on-chain checks above, which need no signature from us.
Reference verifier
An independent reimplementation (shares no code with our backend) lives in the public tooling; the same ~40 lines work anywhere:schemaVersion), this verifier needs no changes
across receipt schema versions.