Skip to main content

Receipts

Use a receipt to prove which governed result, gate run, eval, or monitoring event the platform recorded. Verification uses a public endpoint and does not send your API key.

Status: Beta Companion docs: Public verification API · Testing and CI · Observability Source of truth: Public verification API and the SDK ReceiptHandle.

Know the five receipt families

PrefixFamilyCreated for
dlir_GovernGovernance decisions
gr_GateGate runs and deployment checks
eh_EvalEval harness runs
evow_WinnerThe selected eval model or configuration
ema_MonitorContinuous-assurance monitoring events

The prefix tells you which workflow minted the receipt. It does not replace verification.

Read a governance receipt

from trinitite import Trinitite

tr = Trinitite(env="prod")

resp = tr.client("openai", credential="cred_openai_prod").chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Summarize order #4821."}],
)
result = tr.result(resp)

if result.receipt is not None:
print(result.receipt["id"])
print(result.receipt.get("verify_url"))

The result receipt block is dict-like. Its stable fields are id and verify_url.

Verify without authentication

if result.receipt is None:
raise RuntimeError("This result has no receipt")

verification = result.receipt.verify()
if not verification.ok:
raise RuntimeError(verification.body)

assert verification.body["verified"] is True
print(verification.body["receipt_id"])

result.receipt.verify() calls GET /v1/public/receipts/{id}/verify with no bearer token.

Handle a missing receipt

Receipt minting can produce no id for a result. Check the handle before verification.

receipt = result.receipt
if receipt is None or not receipt.get("id"):
record_unverified_result(result.id)
else:
verified = receipt.verify().body.get("verified", False)

Calling verify() without an id raises ValueError. A receipt handle created without a client raises RuntimeError because it cannot make the verification request.

Read gate receipts

Gate runs use typed GateReceiptHandle objects.

gate = tr.gate.get("gate_refund_release")
for receipt in gate.runs(limit=5):
print(receipt.gate_run_id)
print(receipt.passed)
print(receipt.failures)

if receipt.run_id:
scenario_results = receipt.replay()
print(scenario_results.body)

A gate receipt id uses gr_. The linked run_id points to per-scenario results. receipt.replay() raises ValueError if no linked run exists yet.

Keep receipt ids with application records

audit_record = {
"order_id": "4821",
"decision_id": result.id,
"receipt_id": (
result.receipt.get("id")
if result.receipt is not None
else None
),
}

Store the opaque id and verification URL. Fetch current verification status when you need to validate the artifact.

Next steps