Verify receipts
Confirm a Felspar decision with one REST call before your code acts on it.
Verify a decision’s receipt whenever your code is about to act on it: send an email, update a record, approve a request. Verification asks Felspar to replay the decision from what it recorded and confirm it matches. It calls no model.
The call
curl -s "https://api.felspar.ai/v0/executions/$EXECUTION_OBJECT_ID/verify" \
-H "Authorization: Bearer $FELSPAR_AGENT_KEY" \
-H "Content-Type: application/json" \
-d @verify.json
Where verify.json holds the receipt exactly as the decision returned it:
{
"receipt": { "...": "result.receipt" },
"expectedReceiptDigest": "the value of result.receipt.receiptDigest",
"deliveredCapsule": { "...": "result.context, if your code used it" }
}
EXECUTION_OBJECT_ID is result.executionObjectId from the decision.
The answer
{
"authority": "unapproved",
"status": "reproduced",
"mismatches": [],
"decided": {
"jobId": "review-nda",
"entityId": "CTR-2026-0117",
"releaseId": "release-...",
"outcome": "review",
"subject": { "type": "contract", "related": [{ "relationship": "counterparty", "subject": "company", "id": "northwind.com", "questions": ["law"] }] },
"escalation": { "id": "legal-review", "trigger": "outcome" }
}
}
Act only when all of these hold:
statusisreproduced;decided.jobIdis the job you expect;decided.entityIdis the entity you’re about to act on;decided.outcomeis an outcome that allows the action;- if you hold a release,
decided.releaseIdis it; - if
decided.escalationis present, the action is the hand-off your code maps to thatid, not the action itself; - the decision’s evidence is still fresh (
result.explanation.evidenceFreshUntilis in the future).
decided.subject and decided.escalation appear when the release declares a subject or escalations; Felspar re-derives both from the release and the replayed outcome. Use the values in decided, which come from Felspar’s replay, never values the agent passed along. If status is mismatch, mismatches names what differs. Don’t act.
In TypeScript
The SDK’s verifier does the same call and returns decided only when the receipt was reproduced:
import { felsparVerifier } from "@felspar/sdk/draft/action-gate";
const verify = felsparVerifier({ origin: "https://api.felspar.ai", agentKey: process.env.FELSPAR_AGENT_KEY });
const decided = await verify(decision); // null unless reproduced
For a whole tool-call gate, see The pre-action gate.
Who can verify what
- An agent key verifies receipts of decisions that agent made, and no others.
- A signed-in member, approver or owner can verify any decision in the workspace.
Verification isn’t counted toward decision rate limits.
When verification fails
| Response | Meaning |
|---|---|
reproduced |
Act if the checks above pass. |
mismatch |
The receipt doesn’t match what Felspar recorded. Don’t act. |
403 forbidden |
This caller can’t verify this decision, or it no longer exists. Decisions are kept for 30 days. |
| Network error or timeout | You don’t know. Don’t act; retry the verification. |