Skip to main content
Every model-inference request through the gateway produces a receipt: a canonical record of what happened — who called, which model, what it cost, and which policy checks ran — cryptographically signed and chained to the receipt before it. The result is an audit trail where tampering with any single record is detectable. Observability tools can tell you what they observed. Because Wardin sits in the request path and signs what it enforced, a receipt is evidence, not telemetry.

What a receipt contains

How the chain works

  1. The receipt’s fields are serialized in a fixed canonical order.
  2. this_hash = sha256(canonical_receipt || prev_hash) — each receipt’s hash incorporates the previous receipt’s hash.
  3. this_hash is signed with the gateway’s ED25519 key.
Changing any field of any historical receipt changes its hash, which breaks every subsequent link in the chain. Verification re-derives the hashes from stored fields and checks the signature — nothing is taken on trust.
Chaining and signing happen in an asynchronous writer, off the response path. Receipts add zero latency to your LLM requests, and the chain only advances after the receipt is durably stored.

Where to see receipts

  • INGRESS — click any request in the live stream to open its receipt drawer (with RECEIPT | TRACE tabs).
  • EVIDENCE — chain statistics and a sample verified receipt.

Query and export

GET /v1/receipts takes optional, AND-combined filters — from/to (RFC3339), actor, provider, model, check (a check name present on the receipt), and upstreamStatus — composed with cursor pagination:
For a bulk pull, GET /v1/receipts/export returns the matched set as a file:
Export is bounded per call by limit (max 50,000); the X-Wardin-Truncated response header is true when more rows matched — narrow the filters or page GET /v1/receipts. Unlike any log tool’s export, the JSONL rows carry the ED25519 signature + hash-chain fields per row.
For full offline chain verification, use the Evidence Bundle instead — it carries a contiguous signed segment plus the signing-key registry and trust anchor that verification requires. A filtered receipt export has seq gaps (its prev_hash links point at excluded rows) and omits the public keys, so it’s for querying/analysis, not standalone chain verification.
These endpoints query what’s currently retained — the 7–30 day hot analytics window. They are not a durable audit trail until the WORM cold tier ships (see below); the same API will front the cold tier when it does. For control-scoped queries (“all receipts proving eu_ai_act:art_12”), use Framework CoverageGET /v1/compliance/coverage/{framework}/controls/{controlId}/receipts.
Full endpoint references: GET /v1/receipts, GET /v1/receipts/export.

Verifying programmatically

verified: true means the stored hash equals sha256(canonical || prev_hash) and the ED25519 signature over that hash is valid. Receipts are tenant-scoped — you can only read your own. Full endpoint references (continued): GET /v1/receipts/{id}, GET /v1/receipts/_/verify-chain.

Export an Evidence Bundle (verify offline, no account)

The verification above trusts us to run the check. For an auditor who shouldn’t have to, export a self-contained Evidence Bundle and verify it entirely offline — no Wardin account, no network:
The bundle is a single JSON file containing:
  • a contiguous signed receipt segment for the window (bounded so the chain has no gaps),
  • the signing-key registry for every key the receipts reference — so verification survives key rotation without contacting Wardin,
  • the compliance packs in force (framework + version + content hash), and
  • a trust anchor for the first link.
wardin-verify recomputes each sha256(canonical || prev_hash), checks the ED25519 signature against the bundled public key for its key_id, and reports any tampered field, broken link, missing key, or seq gap — exiting non-zero if anything fails. It shares the exact canonical-serialization code the gateway signs with. See Offline Verification for the tool’s status, the full bundle-format spec, and the verification algorithm (so you — or an auditor — can reimplement the check in any language). See the full endpoint reference: GET /v1/compliance/evidence-bundle — the range parameter and the bundle schema.
A clean result proves integrity — the chain is internally consistent, untampered, and each receipt is signed by the key the bundle declares for it. It does not by itself prove authenticity: the bundle carries its own key registry, so a forged bundle could be internally consistent under a fresh keypair. To close that gap, pin the signing-key fingerprints wardin-verify prints against Wardin’s published key registry — eyeball them, or pass --keys=<fingerprint>,… to make verification fail unless they match.
A bundle covers the receipts currently in the hot analytics window (typically the last 7–30 days) — it’s an offline-verifiable snapshot of the recent chain, not a long-term archive. Durable WORM retention that lets a bundle span years is in active development (see below).

Verify your first receipt

Commissioning — the guided first-run flow — already shows you your first receipt once your first governed request completes; this is how to confirm it yourself, and how to check any receipt afterward:
  1. Open INGRESS and click the row for your first request (or any request) — the receipt drawer opens with RECEIPT | TRACE tabs.
  2. The RECEIPT tab shows a VERIFIED ✓ or UNVERIFIED ✕ badge. VERIFIED means Wardin recomputed sha256(canonical || prev_hash) from the stored fields and confirmed the ED25519 signature over it matches — nothing is taken on trust.
  3. To verify programmatically instead, fetch the same receipt by ID (see above) and check its verified field, or run verify-chain over a range that includes it.
The cryptographic verification behind the VERIFIED badge happens on every fetch, independent of who’s watching.

Why this matters for compliance

Frameworks like the EU AI Act and NIST AI RMF ask for evidence that governance controls actually ran — not a dashboard screenshot. A hash-chained, signed record of every enforcement decision (including blocks: over-budget 429s, allowlist 403s, guardrail rejections) is exactly that artifact. Today you can verify any receipt — or a contiguous range of the chain — through the API above: recompute the hash and check the ED25519 signature, nothing taken on trust. Receipts are retained in the hot analytics window (configurable, typically the last 7–30 days).
Framework-mapped evidence packs — control-ID citations per check, with a coverage map and per-control receipt drill-down — ship today as draft mappings; see Framework Coverage. The one-click auditor Evidence Bundle export and the offline verifier (spec published; reference CLI, public release in preparation — check the chain without a Wardin account) are available now, over the recent window (above). Long-term WORM retention — so a bundle can span years, not just the hot window — is still in development. Until it ships, treat receipts and bundles as verifiable runtime evidence over the recent 7–30 day window, not a long-term archive.