View Markdown

Receipts

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, 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:

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 when it does not.