# Receipts

> Every answer carries a receipt that Kabu signs, a JWS over what was asked, what was decided, by whom and how. Verify it with the published keys.

When an ask settles, its `resolution.receipt` is a compact JWS that Kabu signs (ES256): proof of what was asked, what
was decided, by whom, how, and when. Keep it with whatever the answer allowed, a deploy log or an audit trail, and
anyone can check later that the decision is Kabu's record and was not edited.

## What it says

The receipt's payload is its claims:

| Claim | What it is |
|---|---|
| `msg` | The ask's message id |
| `aud` | The org it belongs to: check it is yours |
| `req_digest` | A SHA-256 of what was shown: the title, body, blocks, links, attachments, action and ask, as canonical JSON (RFC 8785) |
| `decision` | `approve`, `reject`, `edit`, `respond` or `ignore` |
| `value_digest`, `effective_action_digest` | Digests of the answer's value, and of the action as finally approved (with any edits) |
| `sub` | Who answered: the recipient (`rcp_…`), or `system` for an expiry default |
| `assurance`, `via`, `source` | How sure Kabu is it was them, where they answered, and whether a person or the system decided |
| `resolved_at`, `iat`, `jti` | When it settled, when it was signed, and the receipt's own id |

Values are signed as digests, never as text, so a receipt stays verifiable after the message's content is erased. A
receipt proves what Kabu delivered and what it received back, not what a screen showed or what the agent did next.

## Verify it

Offline, with any JWS library: fetch the public keys from
[`https://usekabu.com/.well-known/jwks.json`](/.well-known/jwks.json), pick the key whose `kid` matches the receipt's
header, check the signature with ES256 (no other algorithm), then check `aud` is your org and `msg` the ask you hold.
Keys rotate yearly and stay published for the audit period, so old receipts keep verifying.

Online, without a JWS library:

```sh
curl https://usekabu.com/api/v2/receipts/verify \
  -H "Authorization: Bearer $KABU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"receipt": "eyJhbGciOiJFUzI1NiIs…"}'
```

It returns the claims when the receipt is valid and belongs to your org and mode, and `422`
[`invalid_receipt`](/docs/errors/invalid_receipt) when it does not.
