Receipts API
A receipt is the immutable record of one action: the event that triggered it, the plan it belonged to, the trust verdict, the idempotency key, and the outcome. Receipts are append-only. There is no update and no delete, and refusals are receipted the same as successes. This page documents listing, retrieving, and exporting receipts. The concept is covered in Receipts & audit.
Shared conventions, including authentication, pagination, and the error envelope, are defined in the API overview. Error codes are catalogued in Errors.
The receipt object
Unique identifier, prefixed rc_.
Always receipt.
Tenancy on the row, the same as every envelope. reseller_id is null for Fibric-direct tenants.
The operator whose plan produced the action.
The operator's name at the time of the action, denormalized so the receipt stays readable even if the operator is later removed.
What was invoked, as proposed in the plan's PlannedAction.
The entity the action touched, for example order:SO-10884.
The dedup key that guarantees this side effect can never apply twice.
The trust evaluation as it was enforced: decision (ALLOW, ALERT, BLOCK, or DEDUP), tier, and rule, or null when the block came from the default-closed fallthrough.
applied, refused, deduplicated, or failed. A refused receipt records a policy block; a failed receipt records a connector error after an allow.
Who approved the plan, when it ran through the human escalation path. null for auto-disposed plans.
The API request that caused the disposition, correlating the receipt with our logs and yours.
RFC 3339 timestamp of the disposition.
{
"id": "rc_5b21",
"object": "receipt",
"reseller_id": null,
"tenant_id": "t_8f2ac901",
"operator_id": "op_8f2a1c",
"operator": "order-risk",
"event_id": "ev_3a91c7",
"plan_id": "pl_7c1a",
"action_id": "act_91d0",
"connector": "cn_7d2f4a",
"tool": "order.hold",
"entity_key": "order:SO-10884",
"idempotency_key": "order-risk:SO-10884:hold",
"verdict": { "decision": "ALLOW", "tier": 1, "rule": "tool:order.hold max_value:500" },
"outcome": "applied",
"approver": "ops@acme.com",
"request_id": "req_9b3e21f0",
"at": "2026-07-02T15:04:41Z"
}
List receipts
receipts:readReturns receipts for the tenant, newest first, cursor-paginated. Filters combine with AND, so one query answers questions like "everything the order-risk operator was refused on this order last week".
Only receipts produced by this operator; accepts an id (op_8f2a1c) or a name (order-risk).
Only receipts touching this entity_key.
Filter by decision: ALLOW, ALERT, BLOCK, or DEDUP.
Filter by outcome: applied, refused, deduplicated, or failed. outcome=applied selects exactly the billable actions counted against the action allowance.
Only receipts written by this API request. Use the request_id from an error body or X-Request-Id header to trace one call end to end.
Only receipts at or after this RFC 3339 timestamp.
Only receipts strictly before this RFC 3339 timestamp. Combine with since for a closed window.
Page size, 1–100. Defaults to 20.
Pagination cursor from a previous response's next_cursor.
curl "https://api.fibric.io/v1/receipts?operator=order-risk&verdict=BLOCK&since=2026-06-25T00:00:00Z&until=2026-07-02T00:00:00Z" \
-H "Authorization: Bearer $FIBRIC_KEY"
{
"object": "list",
"data": [
{
"id": "rc_5a90",
"object": "receipt",
"operator": "order-risk",
"tool": "order.hold",
"entity_key": "order:SO-10871",
"verdict": { "decision": "BLOCK", "tier": 1, "rule": null },
"outcome": "refused",
"at": "2026-06-28T11:19:03Z"
}
],
"has_more": false,
"next_cursor": null
}
Error cases:
| Status | Code | When |
|---|---|---|
400 | invalid_parameter | verdict is not one of the four decisions, or a timestamp is not RFC 3339. |
400 | invalid_cursor | The cursor is malformed or was issued for a different query. |
Retrieve a receipt
receipts:readReturns the full receipt, the complete answer to "why did this happen": the triggering event, the plan, the verdict with the rule that produced it, the idempotency key, and the outcome.
The receipt id, for example rc_5b21.
curl https://api.fibric.io/v1/receipts/rc_5b21 \
-H "Authorization: Bearer $FIBRIC_KEY"
Returns the receipt object. A cross-tenant id reads as 404 not_found.
Export receipts
receipts:readStarts an asynchronous export job over a filtered slice of the ledger, for an auditor, a data warehouse, or your own retention copy. The job runs in the background; poll the export until it completes, then download from the signed URL. This mirrors fibric receipt export in the CLI.
csv or jsonl. JSONL rows are complete receipt objects; CSV flattens verdict into verdict_decision, verdict_tier, and verdict_rule columns.
The same filters as list receipts: operator, entity, verdict, since, until. Omit for the full ledger.
curl -X POST https://api.fibric.io/v1/receipts/export \
-H "Authorization: Bearer $FIBRIC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: export-june-audit" \
-d '{
"format": "jsonl",
"filters": {
"since": "2026-06-01T00:00:00Z",
"until": "2026-07-01T00:00:00Z"
}
}'
{
"id": "exp_2f81",
"object": "export",
"status": "pending",
"format": "jsonl",
"filters": { "since": "2026-06-01T00:00:00Z", "until": "2026-07-01T00:00:00Z" },
"created_at": "2026-07-02T16:00:00Z"
}
Error cases:
| Status | Code | When |
|---|---|---|
400 | missing_parameter | format is absent. |
400 | invalid_parameter | format is not csv or jsonl, or a filter failed validation. |
409 | idempotency_conflict | The Idempotency-Key was reused with a different body. |
429 | quota_exceeded | Too many concurrent export jobs. See Rate limits & quotas. |
Retrieve an export
receipts:readReturns the export job. Poll until status is complete, then download from url. The URL is signed and expires; re-fetch the export to mint a fresh one. Jobs progress pending → running → complete, or failed with an error.
The export job id, for example exp_2f81.
curl https://api.fibric.io/v1/exports/exp_2f81 \
-H "Authorization: Bearer $FIBRIC_KEY"
{
"id": "exp_2f81",
"object": "export",
"status": "complete",
"format": "jsonl",
"receipt_count": 4182,
"url": "https://exports.fibric.io/t_8f2ac901/exp_2f81.jsonl?sig=…",
"url_expires_at": "2026-07-02T17:03:12Z",
"created_at": "2026-07-02T16:00:00Z",
"completed_at": "2026-07-02T16:03:12Z"
}
Error cases:
| Status | Code | When |
|---|---|---|
404 | not_found | No export with this id exists for the tenant. Completed exports are kept for 30 days, then removed. |
Exporting never removes anything from the ledger. Receipts remain queryable in place regardless of how many exports reference them. Because a receipt exists for every action, including every refusal and every dedup, the export is the complete answer to "what did the AI do last month", not a sample of it.