Skip to content

v2.3.0: signed receipts

Choose a tag to compare

@paidwithtab paidwithtab released this 23 Oct 06:08
· 43 commits to 9df41c22590b58eb9e2dd9f4f3db1e8fce12ea78 since this release

Receipts now prove what was bought, not just that money moved.

Signed receipts (spec draft 0.5)

  • Every gateway has an Ed25519 receipt key, published as receipt_key in /.well-known/tab.
  • Each receipt is signed over the mandate id, the challenge id, the exact request the agent signed (query and body hash) and its signature, the response status and body hash, the seller, and the payment ref (the transaction hash on Robinhood Chain).
  • The gateway reads the upstream body before capture, so the response is fixed before any money moves.

Checking them

  • client.verify(url, res, body, init) returns { ok: true } only when the published key signed the receipt, it names your mandate, commits to your request and hashes to the bytes you read.
  • tab fetch, the MCP tab_fetch tool and the catalog try-it check every paid call and report receipt_verified.
  • Companies verify receipts before booking them, the dashboard marks each one signed or NOT VERIFIED, and GET /api/companies/<id>/receipts/<id> returns one exactly as signed.

What it does not prove: the gateway signs what it relayed, not what the upstream API produced. That needs upstream signed responses, now listed in the spec as future work.

Older receipts stay valid but never count as verified. 245 automated checks (adversarial 37, company 92) plus 21 browser checks.