Admin API

The Admin API manages collection configuration, webhook rules, and the dead-letter queue. It requires a token with the admin scope.

Authorization: Bearer <api-key>  # must have admin scope

Collection configuration

Get collection config

GET /api/v1/collections/{collection}/config

Returns the collection’s current configuration.

Response:

{
  "collection": "crm.deals",
  "reliability_mode": "durable",
  "auto_create": true,
  "snapshot_every": 100,
  "first_event_op": "create",
  "plugins": ["hash_chain"],
  "hash_chain": {
    "enabled": true
  }
}

Update collection config

PUT /api/v1/collections/{collection}/config

Updates the collection configuration. Fields not specified are left unchanged.

{
  "reliability_mode": "strict",
  "snapshot_every": 50,
  "plugins": ["hash_chain"]
}
Field Type Description
reliability_mode string Default mode for writes: strict, durable, fast
snapshot_every integer Snapshot interval in events (default 100)
first_event_op string Op assigned to the first event: create (default) or update
plugins string[] List of plugins to enable (e.g., ["hash_chain"])

Rules

Rules define conditions under which webhooks are fired. Each rule has a filter expression that is evaluated against every incoming event.

List rules

GET /api/v1/collections/{collection}/rules

Create a rule

POST /api/v1/collections/{collection}/rules
{
  "name": "notify-on-stage-change",
  "filter": "changes[?path=='stage']",
  "webhook": {
    "url": "https://example.com/hooks/letopis",
    "secret": "my-signing-secret",
    "timeout_ms": 5000,
    "max_retries": 5
  },
  "enabled": true
}
Field Type Description
name string Human-readable rule name
filter string JMESPath expression; rule fires when the expression is truthy
webhook.url string Target URL
webhook.secret string Name of a signing secret from webhooks.secrets config
webhook.timeout_ms integer Per-attempt timeout in milliseconds (default 5000)
webhook.max_retries integer Maximum delivery attempts (default 5)
enabled boolean Whether the rule is active

Update a rule

PATCH /api/v1/collections/{collection}/rules/{ruleId}

Delete a rule

DELETE /api/v1/collections/{collection}/rules/{ruleId}

Webhooks

Webhooks are fired by rules. The payload is a JSON object containing the event and the collection/entity context.

Webhook payload

{
  "event_type": "letopis.event.stored",
  "collection": "crm.deals",
  "entity_id": "deal-1",
  "version": 4,
  "op": "update",
  "author_id": "user-42",
  "source": "crm-backend",
  "ts_stored": "2026-06-02T09:00:01Z",
  "changes": [
    {"path": "stage", "op": "change", "old": "prospect", "new": "qualified"}
  ]
}

Signature

Every webhook delivery includes an X-Letopis-Signature header:

X-Letopis-Signature: sha256=<hmac_hex>

The HMAC is computed over the raw request body using the secret named in the rule’s webhook.secret. Validate it on your receiving side to verify authenticity.


Dead-letter queue

Failed webhook deliveries are moved to the DLQ after all retries are exhausted.

List DLQ entries

GET /api/v1/dlq

Query parameters: collection (filter by collection), rule_id, limit (default 100), cursor.

Replay a DLQ entry

POST /api/v1/dlq/{entryId}/replay

Re-attempts delivery of a failed webhook. The entry is removed from the DLQ and re-enqueued as if it were a new delivery.

Delete a DLQ entry

DELETE /api/v1/dlq/{entryId}

Permanently removes the DLQ entry without replaying.


Purge an entity (GDPR)

DELETE /api/v1/collections/{collection}/entities/{entityId}

Physically removes all events, snapshots, and current-state documents for the entity. A tombstone is written to ev__system for audit purposes.

Caution: This is irreversible. If hash-chain integrity was enabled, the chain is destroyed for this entity; other entities are unaffected.


System info

GET /version

Returns build information:

{
  "version": "v1.2.3",
  "commit":  "abc1234",
  "date":    "2026-06-01T00:00:00Z"
}