Agent Receipt Record ARR-1

An open format for verifiable records of what autonomous agents buy · Version 1.0 · Draft · 28 September 2026 · CC0 1.0

Schemas receipt · receipt-core · anchor · proof · statement  ·  Source GitHub

1. What this is

ARR-1 defines a record of a single purchase made by an autonomous software agent, and the way a set of such records is fingerprinted and anchored on a public ledger, so that a third party — an auditor, a counterparty, a finance team — can establish two things without trusting whoever produced them:

The second property is the reason this specification exists. Integrity alone is what a signed log gives you, and a signed log remains a document the audited party wrote about itself. Completeness can only be established against a source the audited party does not control. For payments made over x402, that source is the chain the payment settled on.

2. What this is not

3. Terms

Receipt — the record of one purchase. Core — the subset of its fields that is hashed. Fingerprint — the sha256 of the canonical core. Batch — a set of receipts fingerprinted together, typically one account-day. Root — the Merkle root of a batch. Anchor — the message carrying a root, written to a public ledger. Proof — the path from one fingerprint to its root. Issuer — the party that keeps the records, batches them and anchors them.

The key words MUST, MUST NOT, SHOULD and MAY are to be interpreted as in RFC 2119.

4. The receipt

An agent submits a receipt per purchase. The submission form is defined by receipt.schema.json; required fields are id, occurredAt, network, resource, method, requestHash and delivered.

Two rules matter more than the rest:

An issuer MAY accept amountAtomic + asset instead of amount + currency, and MUST normalise them to human units before hashing. An issuer MUST treat a repeated id as the same record and MUST NOT create a duplicate.

5. Canonical form and fingerprint

The hashed object is defined by receipt-core.schema.json: the core fields, all present, with null where a value is absent, plus v: 1 and the issuer's opaque workspaceId. Fields carried alongside the record but excluded from the fingerprint: the supplier's signed receipt, labels, and any issuer-specific metadata.

The canonical form is JSON with:

For the field types ARR-1 uses — strings, booleans, one small integer, and null — this is byte-identical to RFC 8785 (JCS). Implementations MAY use an RFC 8785 library.

The fingerprint is sha256(canonical(core)), lower-case hex. Worked example — this canonical string:

{"amount":"0.004","currency":"USDC","delivered":true,"id":"b0f2b1a4-9e1c-4c7a-8a5e-2f6d4c3b1a09","method":"POST","network":"eip155:8453","occurredAt":"2026-09-24T10:04:11.000Z","payee":"0x52E29e0d2Aa49bfBfC548C0A9F2196F4aa51f3ea","payer":"0x63100a3a5A2F593eCD3c7CB49d366b8Cb79E423d","requestHash":"3f786850e387550fdab836ed7e6dc881de23001b4d4e9d1b2c0f4dbc9c0e2b2a","resource":"https://api.exa.ai/search","responseHash":"89e6c98d92887913cadf06b2adb97f26cde4849b1f9b2e5b4a8f2b6c3d1e0f77","responseStatus":200,"txRef":"0x16115c795c202b55b08eb951a2fc220d3a3e110a363a44dc4ab2d14022b8b029","v":1,"workspaceId":"27f6d763-804b-47cc-b429-f8502d3995ea"}

has the fingerprint

57829beafbd3352836d5c0cfa3cfce95c2501cf273b429da42c712a532a45112

6. Batches and the root

Receipts are grouped into batches. A batch SHOULD cover one account and one day; an issuer MAY choose another period, and MUST state which.

The leaves are the fingerprints of the batch's receipts, as raw 32-byte values, in the batch's stated order. A parent is sha256(left ‖ right) over the concatenated bytes. A level with an odd number of nodes pairs the last node with itself. The root of an empty batch is sha256(""); an issuer SHOULD NOT anchor empty batches.

Worked example — a two-receipt batch whose fingerprints are 57829beafbd3352836d5c0cfa3cfce95c2501cf273b429da42c712a532a45112 and 05fc3e26d3d4c3e2aa8fc823260a6e1c6956e160eeb3d32dccf48c554270b45b has the root

150ad3ba12362b65432fe14c62d58ef27f3b3f1c67a6b69f691e168e87993b17

Batching is what makes the cost of evidence independent of volume: one anchor covers one receipt or ten thousand.

7. The anchor record

The message written to the ledger is defined by anchor.schema.json and MUST be submitted in the canonical form of §5. It carries the root, the size and the period — and nothing about what was bought, from whom, or for how much.

{"app":"x402receipts","batch":"86a240c0-64d9-49f1-aea3-e4d32faf620b","count":2,"from":"2026-09-24T10:04:11.000Z","root":"150ad3ba12362b65432fe14c62d58ef27f3b3f1c67a6b69f691e168e87993b17","to":"2026-09-24T23:12:40.000Z","url":"https://app.x402receipts.com/batch/86a240c0-64d9-49f1-aea3-e4d32faf620b","v":1,"workspace":"27f6d763-804b-47cc-b429-f8502d3995ea"}

The ledger MUST be public, append-only, and MUST timestamp entries independently of the issuer. The reference implementation uses the Hedera Consensus Service, where a write costs USD 0.0008 at a price fixed in dollars; any ledger with equivalent properties conforms. An issuer SHOULD anchor within 24 hours of a receipt being accepted and MUST publish the ledger coordinates (network, topic or equivalent) so that anchors can be read without the issuer's cooperation.

8. The proof

A proof bundle (proof.schema.json) carries the receipt core, its fingerprint, the path to the root and the ledger coordinates. A path entry is { "hash", "position" }, where position says whether the sibling goes on the left or the right when the pair is hashed.

An issuer MUST make a proof available for every anchored receipt, to anyone holding the receipt identifier, without authentication. Receipt identifiers are unguessable; the link is the access.

9. Verification

Given a proof bundle, a verifier MUST:

  1. rebuild the core from the bundle, canonicalise it (§5) and compute its sha256; it MUST equal the stated fingerprint;
  2. fold the fingerprint up the path — for each entry, acc = sha256(sibling ‖ acc) when the sibling is on the left, sha256(acc ‖ sibling) when on the right — and the result MUST equal the stated root;
  3. read the anchor record from the ledger directly, at the stated coordinates, and check that its root equals the root, and that its consensus timestamp is not later than the moment the verifier first saw the record.

Step 3 MUST NOT be performed through the issuer. A verification that reads the ledger through the issuer's API proves nothing that the issuer could not fabricate.

All three checks passing establish that this receipt existed, in exactly this form, at the anchor's consensus time. They establish nothing about whether the goods were worth the money, and nothing about receipts that were never submitted — which is what §10 is for.

10. Completeness

Integrity says the records are unaltered. Completeness says there are no missing ones. An ARR-1 issuer claiming completeness MUST, for each wallet and period:

An issuer SHOULD read from at least two independent sources (for example an indexer and a node), because a single indexer can silently skip a block. The period statement SHOULD carry, per wallet: the number of payments seen on-chain, the number matched, the unmatched list with their settlement references, and the sources and heights used.

10.1 The period statement

An issuer claiming Level 3 SHOULD publish the claim as a document. A period statement (statement.schema.json) covers one account and one period and carries: the period and whether it is final (the period had ended when it was produced); totals spent; how many receipts, delivered, anchored and supplier-signed; per wallet, how many payments were seen on-chain, how many matched, and the unmatched ones with their settlement references; every batch of the period with its root and ledger coordinates; and the data sources consulted.

The statement is canonicalised and hashed as in §5, and the hash is anchored as a record of type statement:

{"app":"x402receipts","final":false,"period":"2026-09","receipts":59,"statement":"35a53c63e4cbb447256f7961479b273744d29260d7ae93fea6f39532b4496256","type":"statement","unmatched":1,"url":"https://app.x402receipts.com/statement/9254677d-3973-4d60-b510-475c3a4cc0b9/2026-09","v":1,"workspace":"9254677d-3973-4d60-b510-475c3a4cc0b9"}

A final statement MUST NOT be replaced: a correction is a new statement for a later period, not a rewrite of a closed one. An interim statement (produced before the period ended) MAY be superseded. Verification is §9 applied to the document: canonicalise, hash, compare with the anchored fingerprint, read that fingerprint from the ledger directly. A live example: a September statement and its anchor.

The distinction between funding and expense belongs here. A transfer into an agent's wallet is funding; it is not a purchase and MUST NOT be recorded as one. The expenses are the outgoing payments to suppliers.

11. Supplier-signed receipts

Everything above is evidence produced on the buyer's side. The strongest form of evidence comes from the counterparty. Where a supplier implements the x402 offer-receipt extension, its signed receipt travels in the PAYMENT-RESPONSE header; an ARR-1 issuer SHOULD capture it, verify the signature, record the recovered signer, and carry both alongside the record. A receipt whose signature does not verify MUST be stored without a signer rather than silently dropped or silently trusted.

A supplier signature is what turns "our system says we bought this" into "the supplier says it sold it to us". Suppliers that sign are doing their customers' finance teams a favour at a cost of roughly ten lines of code.

12. Conformance

An implementation MUST state the level it claims and the ledger it anchors to. The reference implementation operates at Level 3.

13. Reference implementation

x402receipts implements ARR-1 at Level 3 and runs the registry. Source: github.com/x402receipts/x402receipts (MIT).

Anchors are written to Hedera mainnet, topic 0.0.10889260, readable by anyone through any Hedera mirror node.

14. Status, licence and versioning

Version 1.0, published 28 September 2026. This is a draft: the schemas and the algorithms in §§5–9 are stable and the reference implementation follows them, but the text may still be clarified.

The specification and its schemas are released into the public domain under CC0 1.0. Implement it, fork it, embed it in another standard; no permission and no attribution required.

A change that alters a fingerprint, a root or an anchor record for the same inputs requires a new version number, carried in the v field. Comments and corrections: hello@x402receipts.com or an issue on the repository.