Skip to content
Felspar
Esc
↑↓navigate↵open⌘Jpreview
On this page

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:

  1. status is reproduced;
  2. decided.jobId is the job you expect;
  3. decided.entityId is the entity you’re about to act on;
  4. decided.outcome is an outcome that allows the action;
  5. if you hold a release, decided.releaseId is it;
  6. if decided.escalation is present, the action is the hand-off your code maps to that id, not the action itself;
  7. the decision’s evidence is still fresh (result.explanation.evidenceFreshUntil is 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.

Was this page helpful?