Liccium Developer Portal
Registry Operations

Redaction and Full Deletion of Declarations

A declaration is signed, timestamped and content-addressed by its CID, so it cannot be edited in place. The registry offers two operations for withdrawing one instead. They differ in three effects: discoverability through ISCC search, direct access to the metadata through the CID, and what remains in the provenance chain.

RedactionFull deletion
ISCC searchno resultno result
CID existsyesyes, a deletion marker is retained
CID returns the declaration metadatayes, marked redactedno, 410 Gone with the marker
Declaration remains in active storageyesno
Position in the provenance chainkept, flaggedkept, shown as deleted through the marker
Batch operationyes, up to 500 CIDs per requestno, one CID per request
Reversibleyesno
Who may request itthe declarer of the declarationadministrators, and declarers for whom deletion has been enabled

Both operations address a declaration by its CID (the declaration id, lowercase base32, returned as cidV1 by the Declaration API). An ISCC is never accepted: several declarations can share an ISCC, and the operation must target one specific declaration.

The operations are served by the registry gateway at https://api.liccium.app. The full request and response reference is in the Redaction API tab.

Authentication

Every route needs a consumer API key (Authorization: Bearer <key>). What a key may do is bound to it by Liccium when the key is issued:

Key capabilityGrants
bound to a declarer idredact and un-redact the declarations made by that declarer, read its own batch jobs and CID states
bound to a declarer id, deletion enabledadditionally: full deletion of its own declarations, one CID per request
administratoreverything, for any declarer: redaction, deletion (also of a whole chain), the redaction index and statistics

The binding is enforced by the gateway. Headers sent by the client that claim a declarer or a role are ignored, and a request for another declarer's declaration is rejected with 403. Contact Liccium to have redaction or deletion enabled for your key.

Redaction

Redaction suppresses a declaration from ISCC-based search without removing it. The declaration and its CID continue to exist.

  • Discoverability: the declaration is excluded from ISCC similarity search. If it belongs to the provenance chain of a visible declaration, the Search API still returns it inside that chain, flagged metaInternal.redacted: true, so a verifying party sees the full history. It never appears as a result of its own.
  • Direct access: the metadata routes (/v1/cid/{cid}, /v1/dec-id/{decId}, /v1/metadata-pub/{identifier}) keep returning the declaration. The response header x-declaration-status: redacted tells a verifying party that it is redacted; the signed document itself is unchanged.
  • Provenance: the declaration keeps its CID and its place in the chain. A later declaration may still supersede it without making it discoverable again.
  • Federated registry: the CID keeps its place in the synchronised registry document, but its value is replaced by a marker that carries no content code, so registry nodes stop returning it from similarity search after their next sync. The origin retains the original value so an un-redaction can republish it.
  • Statistics: excluded while redacted, included again after un-redaction.

Redact one declaration

TerminalCode
curl -X POST https://api.liccium.app/v1/redact \ -H "Authorization: Bearer $CONSUMER_KEY" \ -H "content-type: application/json" \ -d '{"cid": "bbqjcb...", "isRedacted": true, "reason": "declarer request"}'
JSONCode
{ "cid": "bbqjcb...", "ok": true, "changed": true, "isRedacted": true, "everRedacted": true, "version": 1, "page": 1, "declarerId": "did:key:z...", "effects": { "iroh": "queued", "stats": "removed" } }

"isRedacted": false un-redacts the declaration. The call is idempotent: repeating it answers "changed": false.

Errors: 400 (invalid body, an ISCC instead of a CID, more than 500 CIDs), 403 (the key is not bound to the declarer of this declaration), 404 (unknown CID), 410 (the declaration was deleted; deletion is terminal).

Redact up to 500 declarations in one request

TerminalCode
curl -X POST https://api.liccium.app/v1/redact \ -H "Authorization: Bearer $CONSUMER_KEY" \ -H "content-type: application/json" \ -d '{"cids": ["bbqjca...", "bbqjcb..."], "isRedacted": true}'

The batch is accepted with 202 and processed asynchronously:

JSONCode
{ "jobId": "7f3c...", "status": "queued", "type": "redact", "total": 2, "duplicatesDropped": 0, "statusPath": "/v1/redact/jobs/7f3c..." }

Poll GET /v1/redact/jobs/{jobId}. The job status moves from queued through running to done (or failed), with processed, succeeded, unchanged and failed counters and a per-CID results list. Each entry carries ok and changed, and on failure a status (not_found, forbidden, deleted) with an error message. Every CID is checked against the caller's declarer individually, so one rejected CID never blocks the others. A declarer key only sees its own jobs.

Full deletion

Full deletion removes the declaration and its metadata from active storage and from every participating registry. Unlike redaction it is not reversible, and there is no batch form.

  • Discoverability: removed from ISCC search.

  • Direct access: resolving the CID no longer returns the metadata. The metadata routes answer 410 Gone with a minimal deletion marker and the header x-declaration-status: deleted. A verifying party can therefore tell a CID that never existed (404) from one whose declaration was deleted (410):

    JSONCode
    { "cid": "bbqjcb...", "iscc": "ISCC:KEC...", "status": "deleted", "deletedAt": "2026-09-24T10:00:00.000Z", "authorizedBy": { "role": "declarer", "declarerId": "did:key:z..." }, "supersedes": "bbqjca..." }

    The marker contains no original metadata and no personal information: only the CID, the ISCC, the status, the time of deletion, who authorised it (the declarer with its did, or an administrator) and the chain links.

  • Provenance: the cryptographic references to the CID stay valid, the referenced data is gone. Chains containing the CID are still returned by the Search API, with the deleted position represented by its marker only (metaInternal.deleted: true), for example Declaration A → [Declaration B, deleted] → Declaration C. A deleted declaration cannot be superseded.

  • Federated registry: the CID keeps its place with a permanent deletion marker. The declaration value is released and garbage-collected on the origin node, and registry nodes that re-sync see the marker. Copies exported or archived outside the participating infrastructure cannot be recalled.

  • Recovery snapshot: before removal, the declaration is copied into a protected snapshot store retained for 90 days, solely for disaster recovery and the correction of technical errors. Snapshots are not part of the registry, not searchable, not resolvable and not accessible to any API consumer. After 90 days they expire, and the deletion becomes final everywhere.

  • Statistics: removed.

TerminalCode
curl -X POST https://api.liccium.app/v1/delete \ -H "Authorization: Bearer $ADMIN_OR_ENABLED_KEY" \ -H "content-type: application/json" \ -d '{"cid": "bbqjcb...", "reason": "GDPR request #12"}'
JSONCode
{ "cid": "bbqjcb...", "ok": true, "changed": true, "marker": { "cid": "bbqjcb...", "iscc": "ISCC:KEC...", "status": "deleted", "deletedAt": "2026-09-24T10:00:00.000Z", "authorizedBy": { "role": "admin" } }, "effects": { "snapshot": "written", "marker": "written", "index": "deleted", "stats": "removed", "iroh": "queued", "s3Versions": 1 } }

Deleting an already deleted CID answers 200 with "changed": false and the existing marker. Errors: 400 (invalid body, an ISCC, or a cids batch), 403 (deletion is not enabled for this key, the declaration belongs to another declarer, or recursive without the administrator role), 404 (unknown CID).

Deleting a whole provenance chain

Deleting one declaration never deletes its predecessors or successors. Administrators can request that explicitly with "recursive": true: every declaration on the CID's supersedes chain is deleted, each with its own marker, and the response lists the chain and the per-CID results (207 when some members failed).

How verifying parties see it

Consumers of the Metadata and Search APIs do not need any new permission. They receive three signals:

SignalWhereMeaning
x-declaration-status: active, redacted or deletedresponse header of the metadata routesstate of the declaration behind the CID
410 Gone with a deletion marker bodymetadata routesthe declaration existed and was fully deleted
metaInternal.redacted and metaInternal.deletedSearch API results inside a provenance chainthe chain member is redacted (metadata present) or deleted (marker only, exposed as deletionMarker)

A 404 keeps its meaning: the CID is unknown to the registry.

Checking the state of a CID

GET /v1/redaction/status/{cid} returns the status (active, redacted, deleted or unknown), the redaction-index entry and, for deleted CIDs, the public marker. With ?verify=1 the response also contains a store-by-store consistency report. Declarer keys can only query their own declarations.

Technical routes for administrators

  • GET /v1/redacted?page=N returns the paged index of every declaration that was ever redacted or deleted. Entries are never removed: un-redaction flips redacted to false, deletion sets deleted: true. Pages hold 500 entries; while fewer than 1000 entries exist, all pages and a flat list are returned as well.
  • GET /v1/redaction/stats?days=30 returns totals (indexed, currently redacted, un-redacted, deleted), counts per declarer, operations per day, recent audit events, batch jobs and deletion markers.

Status codes at a glance

CodeMeaning
200done, or already in the requested state ("changed": false)
202batch accepted, poll the job
207recursive deletion with partial failures
400invalid body, an ISCC instead of a CID, batch too large, or a batch delete
401missing or invalid API key
403the key is not allowed to perform this operation on this declaration
404unknown CID or job
410the declaration was fully deleted (the metadata routes return the marker)

See also

Last modified on