Skip to main content

Retention & Deletion

Retention is the mechanism that lets you keep records exactly as long as your obligations require: no shorter, and no longer. This guide explains how retention policies are defined, how they attach to documents, how expired records move through review-gated disposition to destruction, and how deletion behaves when legal holds apply. Workspace admins manage policies and approve dispositions; viewers have read-only access.

A retention policy is a named, workspace-scoped rule that answers two questions: how long is a record kept, and what happens when that time is up. Each policy has a unique name, an optional description, either a fixed duration in days or an event trigger the clock starts from, a grace period in extra days after expiry before the record enters disposition, and a disposition action that decides what happens at expiry: review_then_destroy or retain_indefinitely.

A duration-based policy counts a fixed number of days from ingest. An event-based policy starts the clock from a trigger event: ingest_date (when the document entered Talonic) or document_date (a date carried by the document itself, for example an invoice date). Talonic's compliance triage can propose event dates it finds in document content. Proposed dates are suggestions only: a document whose trigger date is not confirmed never gets an expiry date computed from a guess, so an unconfirmed proposal never triggers disposition.

Create a policy and assign it to a document type
# Create a 10-year policy with a 30-day grace period (admin only)
curl -X POST "$API_URL/records/retention-policies" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invoices 10y",
    "description": "Tax-relevant invoices, 10 years from document date",
    "duration_days": 3650,
    "event_trigger": "document_date",
    "grace_period_days": 30,
    "disposition_action": "review_then_destroy"
  }'

# Assign it to every document classified as an invoice
curl -X POST "$API_URL/records/retention-assignments" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "policy_id": "<policy-id>",
    "scope_type": "document_type",
    "scope_id": "invoice"
  }'

Assignments and resolution: most specific wins

A policy takes effect when it is assigned to a scope. Three scopes exist: source connection (every document ingested through that connection), document type (every document classified as that type), and document (one specific document). When more than one assignment could apply, the most specific one wins: document beats document type, and document type beats source connection. Example: your Gmail connection carries a 6-year policy and the document type "invoice" carries a 10-year policy. An invoice from that Gmail connection gets 10 years. One specific invoice with a direct "retain indefinitely" assignment is retained indefinitely.

Retention state per document

ParameterTypeDescription
activestateWithin its retention period. Normal access; no disposition pending.
pending_dispositionstatePast expiry plus grace period. Waiting in the disposition review queue. The document remains fully accessible.
disposedstateDestruction approved and executed. Content is gone; the tombstone row and full audit history remain.

The retention engine runs on a daily schedule. It resolves the effective policy for each document, computes and stores retain_until, and moves documents past retain_until plus the grace period into pending_disposition when their policy says review_then_destroy. Each engine run is summarized in the audit trail (retention.set and disposition.pending events), and each document's resolved policy, expiry date, and state are visible on the document itself and in document list filters.

How disposition works

Disposition is the controlled end of a record's life. Talonic never silently destroys an expired record. The path is: the document passes retain_until plus grace and enters the review queue. Nothing is destroyed at this point. An admin reviews the queue and approves destruction with a typed confirmation ("confirm": "DESTROY"), which is recorded with the approver's identity. Immediately before destruction, the system re-checks for active legal holds; if any hold covers the document, destruction fails closed and the document stays in the queue. Destruction then removes the stored content and extracted occurrences, keeps the document row as a tombstone, and issues a disposition certificate.

Review the queue and approve a disposition
# List documents pending disposition
curl "$API_URL/records/dispositions?state=pending_disposition" \
  -H "Authorization: Bearer $TOKEN"

# Approve destruction of one document (admin only, typed confirmation)
curl -X POST "$API_URL/records/dispositions/$DOCUMENT_ID/approve" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"confirm": "DESTROY"}'
Response
{
  "disposed": true,
  "certificate_id": "c2f0a7e4-6d1b-4c58-9a3e-8b7f6d5c4e3a"
}

Every executed disposition produces a certificate recording the document (by tombstone reference), the filename, the SHA-256 hash of the destroyed content, the retention policy that applied, who approved the destruction and when, when destruction was executed, and confirmation that the legal hold check passed. Certificates are listed at GET /records/disposition-certificates and outlive the records they describe. The destruction itself is also written to the hash-chained audit trail as a document.disposed event, so the fact and circumstances of destruction enjoy the same tamper evidence as every other event.

Soft delete vs. destruction

Two different things

ParameterTypeDescription
Soft deletearchive modeTriggered by ordinary delete actions when archive mode is on. The document is marked deleted and hidden from listings, but content remains in storage and nothing about its history is lost. Audit event: document.deleted.
Destructiondisposition onlyTriggered only by an approved disposition. Content is permanently deleted; the row remains as a tombstone with the content hash and audit linkage. Audit event: document.disposed, plus a certificate.

Every deletion path checks for active legal holds before proceeding and refuses if one applies: user-initiated document deletion, disposition-driven destruction, administrative cleanup, and full workspace deletion. Fail-closed means the check must positively succeed for deletion to proceed. A hold always beats a retention expiry: a document that is both expired and held stays exactly where it is until the hold is released. After destruction, the tombstone preserves the document's identity, its content hash, and its complete audit history, so you can always answer what the record was, when it existed, who touched it, and who approved its destruction.

Roadmap, not yet available: storage-level WORM locks tied to retain_until and lifecycle tiering to archival storage classes (both are designed as infrastructure templates and are not deployed; today retention is enforced at the application layer). Fully automatic event-based retention from extracted dates is intentionally not offered: extracted dates remain proposals requiring human confirmation.

Frequently asked questions

What happens when a retention policy expires for a document?+
Nothing is destroyed automatically. When a document passes its retain_until date plus the policy grace period, the retention engine moves it to pending_disposition and it appears in the disposition review queue. The document remains fully accessible until an admin explicitly approves destruction with a typed confirmation, and a hold check runs immediately before destruction.
Which policy applies when several assignments could match a document?+
The most specific assignment wins: a per-document assignment beats a document-type assignment, which beats a source-connection assignment. Each document shows its resolved policy, retain_until date, and retention state, so you can verify the effective policy before relying on it.
Can I delete a retention policy that is in use?+
Deleting a policy that still has assignments returns a conflict error unless you pass force=true. Removing a policy does not destroy any documents; documents whose policy is removed simply stop having a computed expiry from that policy.
What is in a disposition certificate?+
The document reference, the filename, the SHA-256 hash of the destroyed content, the retention policy that applied, the approver identity and approval time, the execution time, and confirmation that the legal hold check passed. Certificates are retained permanently and remain queryable after the record itself is destroyed.