A receipt is a signed record of how one protected action ended. K-Block stores each receipt as an evidence bundle (a .kbundle file) and keeps a summary record of it for listing and searching.
This page describes the fields you see: in the Cloud API, on the dashboard's Receipts pages, in the answer an agent gets, and inside the bundle. It describes the current Protocol v0.1 format and does not change it. For what these fields prove, see What a receipt proves; to check a bundle yourself, see Verify a receipt.
Where receipts come from
A receipt exists only for actions that reached certain final states:
| Action status | Receipt | Last signed step (head) | outcome |
|---|---|---|---|
succeeded | Yes | RESULT | succeeded |
failed | Yes, in almost every case | RESULT | failed |
rejected | Yes | REJECTION | final |
cancelled | Yes | CANCELLATION | final |
authorized (decision only) | Yes: an authorization receipt | PROPOSAL, or APPROVAL when a person approved | pending or granted |
denied, expired | No | — | — |
Every receipt is signed by K-Block's Gateway identity, the identity whose KID is the Gateway KID. See Action statuses for the details.
Summary fields
The receipt list (GET /api/v1/orgs/<org-id>/receipts) and the receipt detail (GET /api/v1/orgs/<org-id>/receipts/<receipt-id>, under receipt) share these fields. Management keys need the receipts:read scope.
| Field | Meaning |
|---|---|
id | The receipt's ID in the Cloud API (a UUID). Use it in API paths. |
kind | What the receipt covers: execution (the Gateway executed the call), authorization (decision only: it proves the authorization, not an execution) or closure (rejected or cancelled). |
protected_action_id | The action the receipt is about. |
receipt_object_id | The ID of the signed receipt object (starts with ko_). The bundle download is named after it. |
thread_id | The ID of the thread's first object, the TASK, which identifies the action's evidence thread. |
head_object_id | The last signed step the receipt covers (the RESULT, REJECTION or CANCELLATION; the PROPOSAL or APPROVAL of an authorization receipt). |
workflow | The workflow the thread follows: kblock/task-approval@0.1. |
outcome | succeeded or failed for a RESULT head; final for a rejection or cancellation; pending (PROPOSAL) or granted (APPROVAL) for an authorization receipt. |
issuer_kid | The KID of the identity that signed the receipt: the Gateway identity. |
bundle_sha256 | The SHA-256 of the stored bundle file. |
bundle_size | The bundle's size in bytes. |
verified_at_issuance | Whether the bundle verified when it was issued; null once the hosted evidence was deleted. |
created_at | When K-Block recorded the receipt. |
evidence | status: hosted, or deleted once the bundle was deleted after the retention period, with deleted_at. |
The list adds, per receipt:
action: the action'sid, currentstatus,execution(gateway, orcallerfor decision only),agent(id,name),toolandactionname, ornull;policy: the policy decision behind the action (see below), ornullwhen no policy version decided it.
The list accepts an outcome filter (?outcome=succeeded). Rejection and cancellation receipts are stored with outcome final, so ?outcome=rejected matches nothing: filter by final instead.
Receipt detail fields
Once a receipt's hosted copy was deleted after the retention period, the detail, the bundle download and the decision check answer 410 with the code EVIDENCE_EXPIRED and, in details, the receipt's receipt_id, receipt_object_id, protected_action_id, outcome, bundle_sha256, bundle_size, issued_at and evidence_deleted_at. The receipt is not invalid: verify a copy you downloaded before then.
The receipt detail re-reads the stored bundle on every request and checks it against bundle_sha256. The verification report is computed from those bytes; the Cloud API reuses a report it already computed for the same bytes while the trusted attesters and the signers' stored identity documents are unchanged. Besides receipt it returns:
| Field | Meaning |
|---|---|
action | The protected action the receipt is about, in the same form as the actions API, or null. |
workflow | id and digest of the workflow definition the thread was verified against. |
outcome | The outcome derived by this verification. |
issuer_kid, issued_at | Who signed the receipt and the time written into it. |
summary | The summary the verifier derived from the signed steps (see Summary keys). |
result | status and digest of the RESULT, or null values when there is no RESULT. |
chain | The verified path, first step to last: each step's id, type and actor. |
participants | The signers, resolved to this organization's members, services and upstream servers. |
delegations | The delegations in the bundle, with their permissions, expiry (and whether it has passed now) and any revocation in the bundle. |
attestations | Attestations by upstream servers about steps of the path, and whether each was trusted. |
trusted_attesters | The server KIDs of this organization's MCP servers, trusted as attesters for this check. |
verification | The verifier's report: valid, the individual checks, errors, warnings, notes, plus equivocated_identities and verified_at. |
verification_at_issuance | The report stored when the receipt was issued. |
policy | The policy decision behind the action (below). |
verification.valid is true only when every check passed and no signer's identity has equivocated.
The policy decision
policy describes the policy version that decided the action, as recorded on the action:
| Field | Meaning |
|---|---|
policy_id, version_id, version | The policy, the version's ID and its number. |
digest | The digest of the policy document, which is also signed into the TASK. |
rule_id | The rule that decided, or null when the default decided. |
policy_effect | What the policy itself decided: allow, require_approval or deny. |
enforcement | enforce, or observe when the decision was made under an observe window. |
GET /api/v1/orgs/<org-id>/receipts/<receipt-id>/decision-check re-evaluates the stored policy document with the digest signed into the TASK and reports whether it still gives the signed decision. See Versions.
In the dashboard
The Receipts page lists receipts with the columns Receipt, Outcome, Agent and Issued, plus Issuer when the listed receipts have more than one issuer. For a rejection or cancellation receipt, the Outcome column shows the action's status (Rejected or Cancelled) instead of final.
A receipt's page shows:
- the Receipt card: Action, Outcome (for
final, also the action's status), Result when it differs from the outcome, Issuer, Issued at and Workflow; - Identifiers: Receipt object, Thread (task), Head object, Result digest, Workflow digest, Bundle SHA-256 and Bundle size;
- Signed steps: the thread in order and who signed each step;
- Participants: each signer, which steps they signed, and their KID;
- the buttons Verify in this browser and Download .kbundle.
The page header shows the action's status for a final outcome, and so does the Receipt card on the action page.
What the agent gets
When a call completes, the Gateway adds receipt identifiers to the tool result under _meta.kblock:
| Field | Meaning |
|---|---|
protected_action_id | The action's ID. |
receipt_id | The receipt's Cloud API ID (absent if the Gateway could not read the receipt back while answering; the call did run). |
receipt_object_id | The signed receipt object's ID. |
result_object_id | The signed RESULT's ID. |
policy | Only for a call decided under an observe window: enforcement (observe), relaxed, and, when disclosed, policy_effect, rule_id and observe_ends_at. |
Refusals of actions that ended with a receipt (rejected, cancelled, failed) carry the receipt IDs in _meta.kblock too. The TypeScript client and the Python client expose them on their results.
Summary keys
The summary is derived from the signed steps, never copied from the issuer. Its keys depend on which steps are on the path:
| Step | Keys |
|---|---|
| TASK (first step) | requested_by, request, requested_on_behalf_of |
| PROPOSAL | proposed_by, proposal, proposed_on_behalf_of |
| APPROVAL | approved_by, approval, approved_on_behalf_of |
| REJECTION | rejected_by, rejection, rejected_on_behalf_of |
| CANCELLATION | cancelled_by, cancellation, cancelled_on_behalf_of |
| EXECUTION | executed_by, execution, executed_on_behalf_of |
| RESULT | executed_by, result, executed_on_behalf_of, result_status, result_digest |
The …_by key holds the signer's KID, the second key the step's object ID, and …_on_behalf_of the KID the step acted for, when it did. steps lists every step in order with its type, id, actor and, when present, on_behalf_of and delegations. result_digest is a digest of the RESULT's payload, not of the upstream system's state.
A cancellation receipt covers the path TASK → CANCELLATION only: a proposal or approval that existed beside it is not on the path and not in its summary.
Bundle structure
A .kbundle file is JSON with this shape:
{
"kblock_bundle": "0.1",
"receipt": { /* the signed RECEIPT object */ },
"objects": [ /* every signed object the receipt covers */ ],
"identities": [ /* identity documents of every signer, including the issuer */ ]
// "disclosures": [ … ] only when an encrypted payload is revealed
}| Member | Contents |
|---|---|
kblock_bundle | The bundle format version, "0.1". |
receipt | The RECEIPT object (schema kblock/receipt@0.1), signed by the issuer. Its payload holds workflow, root, head, objects (the covered object IDs), identities (the identity-document version relied on for each signer), outcome and summary. |
objects | The covered objects: the path from the TASK to the head, the delegations the steps relied on and their revocations, and attestations about path objects. |
identities | The identity documents needed to check every signature without contacting K-Block. |
disclosures | Optional revealed payloads of encrypted objects. |
The Cloud API serves the bundle at GET /api/v1/orgs/<org-id>/receipts/<receipt-id>/bundle, with content type application/vnd.kblock.bundle+json, the file name receipt-<receipt_object_id>.kbundle, and the header x-kblock-bundle-sha256. It serves the bytes only after checking them against the recorded hash.
What these fields do not tell you
- A receipt is about the steps on its path. A cancellation receipt says nothing about an approval that existed beside it.
- For an ordinary upstream server, the RESULT is the Gateway's own statement of what the upstream returned. Only an attestation from a K-Block-aware upstream adds the upstream's signature.
- An interrupted execution has
outcomefailedalthough its real outcome is unknown; check the action'serror_code(INTERRUPTED). - The tool's binding pin (credential version, input schema, amount mapping) is checked by the Gateway against the tool's authorized binding stored in K-Block, and is not part of the signed evidence.
- Times such as
issued_atare written by the signer; the receipt does not prove them independently.