A receipt/1 receipt records one on-chain transfer — tx hash, chain, amount,
sender, recipient, block, time — and signs it with Ed25519. This page checks the signature and the
canonical bytes. It does not ask the chain anything: the block is public, so the transfer is
re-checkable by anyone from the tx hash.
| Verdict | Meaning |
|---|---|
ok | The signature verifies against the public key in the receipt, and the signed fields are unchanged. |
tampered | The signature does not verify: at least one signed field was changed after signing. |
wrong_key | The receipt is internally consistent but signed by a key you did not name. Compare the fingerprint. |
unsigned | There is no signature at all. Nothing was attested. |
malformed | Not a receipt/1 object, or a field has the wrong type. Nothing was checked. |
The signed bytes are the canonical JSON (RFC 8785) of the receipt without
signature and public_key. Verify with the module itself — no network, no server:
python3 -m attest.payment_receipt verify receipt.json --key <issuer-public-key-b64>
| Proves | Does not prove |
|---|---|
| A transfer of that amount, asset and recipient existed in that block. | That goods or services were delivered. |
| The issuer signed those exact facts at issuance. | That the issuer is solvent, honest or still in business. |
| Any change to the facts breaks the signature. | That the transfer was for the stated subject: the subject is the requester's declaration, signed as a declaration. |
| The receipt records the facts the issuer read from the chain at issuance. | That the payer owned the funds lawfully. |
A receipt costs $0.50. Issue one: POST /api/receipt/issue with
{"tx_hash": "0x…", "chain": "base", "subject": "what was paid for"}.