Skip to main content
The eventing model has two halves with deliberately different guarantees:
  1. The event feed is the source of truth. GET /api/v1/events is a durable, cursor-ordered pull feed of everything that happened in your organization (within your key’s scopes). Events are written in the same database transaction as the mutation that caused them, so the feed never misses a change.
  2. Webhooks are lossy wakeups. A webhook delivery tells you that new events are available — never what happened. The payload is minimal by design; on receiving one (and on your own schedule) you poll the feed from your last cursor. Webhooks can be lost, replayed, or delayed without correctness consequences, and no sensitive data ever transits your endpoint.
This split means a missed webhook is harmless: cursor-resume on the feed always catches you up. We recommend polling GET /events at least every 5 minutes even with webhooks configured.

The event envelope

  • id is the dedup key: the feed is at-least-once, so treat events idempotently.
  • cursor is strictly monotonic per organization. Pass the last cursor you processed as ?after= to resume.
  • actor + metadata.origin support echo suppression: skip events your own integration caused by comparing actor.id to your key id.
  • All payloads and diffs pass sensitive-field redaction before they reach the feed. Events marked ids-only in the catalog carry an empty payload — fetch details via the scoped resource endpoints.

Reading the feed

GET /api/v1/events requires events:read, and results are additionally scope-filtered: a key only sees events for entities whose required read scope it also holds (e.g. case.* events require cases:read; medical events require medical:read). Filters: entity, eventType, caseId, plus standard cursor pagination.
GET /api/v1/document-events is the original documents-only feed and remains available as a deprecated alias for shipped document-sync integrations.

Subscriptions

Webhook subscriptions are managed with the webhooks:manage scope and are scoped to your API key — sibling keys cannot see each other’s subscriptions.
  • POST /api/v1/webhook-subscriptions — { "url": "https://...", "eventTypes": [...] }. eventTypes accepts public event types and entity.* wildcards (e.g. case.*), validated against the public catalog; omitted, you receive the default wakeup.
  • The subscription signing secret is returned once, on create — and again only when you rotate it (PATCH with "rotateSecret": true).
  • The URL must be HTTPS on a host in your key’s webhook allowed hosts allowlist (configured on the key; fail-closed when empty).
Delivery mechanics, signature verification, and retry semantics: Delivery.

Ordering & delivery guarantees

  • Feed cursors are strictly monotonic per organization, and a later cursor never becomes readable before an earlier one.
  • The feed is at-least-once — dedupe on envelope id.
  • Event retention is currently indefinite, but do not build on unbounded replay; a retention window may be introduced with advance notice.