Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.visiqlabs.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Every RECALL suppression decision produces a cryptographic receipt. Receipts provide tamper-evident proof that a specific decision (allow, deny, redact, escalate) was made for a specific agent, resource, and operation at a specific time. They are the compliance backbone of RECALL. Receipts are generated server-side during the POST /recall/evaluate flow. After the suppression engine produces a decision, the decision payload is hashed with SHA-256 and signed with Ed25519. The receipt is stored alongside the decision and linked to the audit log entry.

Why Receipts Matter

Traditional audit logs can be modified or deleted. RECALL receipts solve this by making every decision independently verifiable:
  • Compliance audits: Prove to auditors that your AI agents were governed according to policy at a specific point in time.
  • Incident investigation: If a data leak occurs, receipts prove whether the leaked content was allowed or denied by RECALL at the time of retrieval.
  • Tamper detection: If a receipt’s signature does not verify against the payload hash and public key, the record has been modified.
  • Non-repudiation: The cryptographic chain (payload hash, signature, public key) creates a verifiable trail that cannot be forged.

Receipt Structure

A receipt contains the following fields:
FieldTypeDescription
idstring (UUID)Unique receipt identifier
decision_idstring (UUID)ID of the linked suppression decision
signaturestringEd25519 signature of the payload hash (base64-encoded)
public_keystringEd25519 public key used to produce the signature (base64-encoded)
payload_hashstringSHA-256 hash of the canonical decision payload (hex-encoded)
merkle_rootstringMerkle tree root for batch verification (optional, future)
merkle_proofstring[]Merkle proof path for this receipt (optional, future)
created_atstringISO 8601 timestamp of receipt creation
The linked decision object is included in the receipt response:
FieldTypeDescription
recall_decisions.idstring (UUID)Decision identifier
recall_decisions.agent_idstringAgent that made the retrieval request
recall_decisions.operationstringretrieve, tool_call, or prompt_render
recall_decisions.resource_typestringdocument, tool_result, or prompt
recall_decisions.resource_metadataobjectMetadata about the resource (classification, etc.)
recall_decisions.decisionstringallow, deny, redact, or escalate
recall_decisions.reason_codestringMachine-readable reason code
recall_decisions.reasonstringHuman-readable reason
recall_decisions.rule_idstring (UUID)ID of the rule that produced the decision
recall_decisions.created_atstringISO 8601 timestamp of the decision

How Signing Works

1

Decision is recorded

After the RECALL engine evaluates a request, the decision is inserted into the recall_decisions table with all relevant fields (agent_id, operation, resource_type, decision, reason_code, rule_id, etc.).
2

Payload is canonicalized and hashed

A canonical representation of the decision payload is constructed from the decision_id, vendor_id, agent_id, operation, resource_type, decision, reason_code, rule_id, and created_at. This payload is hashed with SHA-256 to produce the payload_hash.
3

Hash is signed with Ed25519

The payload hash is signed using the server’s Ed25519 private key. The resulting signature and the corresponding public key are stored in the receipt. The private key never leaves the server.
4

Receipt is stored and linked

The receipt (signature, public_key, payload_hash) is inserted into the recall_receipts table and linked back to the decision via receipt_id.

Verifying a Receipt

To verify a receipt, reconstruct the canonical payload from the decision fields, hash it with SHA-256, and verify the Ed25519 signature against the payload hash using the receipt’s public key.
import { createHash, createVerify } from 'crypto';

// Fetch the receipt from the API
const receipt = await fetch('https://api.visiq.ai/recall/receipts/receipt-uuid', {
  headers: { Authorization: 'Bearer <session_token>' },
}).then(r => r.json());

// Reconstruct the canonical payload from the linked decision
const decision = receipt.recall_decisions;
const canonicalPayload = JSON.stringify({
  decision_id: decision.id,
  vendor_id: receipt.vendor_id,
  agent_id: decision.agent_id,
  operation: decision.operation,
  resource_type: decision.resource_type,
  decision: decision.decision,
  reason_code: decision.reason_code,
  rule_id: decision.rule_id,
  created_at: decision.created_at,
});

// Verify the payload hash
const computedHash = createHash('sha256').update(canonicalPayload).digest('hex');
if (computedHash !== receipt.payload_hash) {
  throw new Error('Payload hash mismatch — receipt has been tampered with');
}

// Verify the Ed25519 signature
const publicKeyBuffer = Buffer.from(receipt.public_key, 'base64');
const signatureBuffer = Buffer.from(receipt.signature, 'base64');
const payloadHashBuffer = Buffer.from(receipt.payload_hash, 'hex');

const verify = createVerify('Ed25519');
verify.update(payloadHashBuffer);
const isValid = verify.verify(
  { key: publicKeyBuffer, format: 'der', type: 'spki' },
  signatureBuffer,
);

if (!isValid) {
  throw new Error('Signature verification failed — receipt is invalid');
}

console.log('Receipt verified successfully');

Retrieving Receipts

Receipts are returned as part of the POST /recall/evaluate response (as receipt_id) and can be fetched individually via the REST API:
curl -X GET https://api.visiq.ai/recall/receipts/receipt-uuid \
  -H "Authorization: Bearer <session_token>"
See the API Reference for the complete response schema.

Merkle Tree (Future)

The merkle_root and merkle_proof fields are reserved for future batch verification support. When implemented, multiple receipts within a time window will be organized into a Merkle tree, allowing efficient proof-of-inclusion without verifying every individual receipt. These fields are currently null in all responses.

Best Practices

Store receipt IDs

Store the receipt_id returned by POST /recall/evaluate alongside your application’s retrieval logs. This creates a cross-reference between your application audit trail and RECALL’s cryptographic receipts.

Periodic verification

Run periodic verification jobs that fetch receipts and validate their signatures. This detects any tampering with the audit log between the time of decision and the time of audit.

Key rotation awareness

The Ed25519 public key is included in each receipt. When the signing key is rotated, old receipts remain verifiable because each receipt carries the public key that was used to sign it.

Compliance exports

Use the audit log API to export receipts for compliance reporting. Each receipt is self-contained — the signature, public key, and payload hash are sufficient to verify the decision independently.