Documentation

Webhook Events

Every event Meldoc sends shares the same envelope — only the event name and data field differ.

Payload envelope

{
  "delivery_id": "f1b4e12c-8acb-41c1-8e1a-1dfe8e7e2e11",
  "event": "doc.published",
  "workspace_id": "8e53...",
  "project_id": "4a2c...",
  "project_alias": "api",
  "data": {},
  "triggered_at": "2026-04-18T10:00:00Z"
}

project_id and project_alias are omitted for workspace-scope events. Glossary events are always workspace-scope; member events are workspace-scope only when the change isn’t tied to a specific project (see Member events below).

Filtering events

When creating a webhook you can subscribe to:

  • All events — receive every event type.
  • Category wildcard — for example doc.* matches all document events.
  • Exact type — for example doc.published only.

Document events

Event Fires when Key data fields
docs.changed Any document is created, updated, or deleted { created: [], updated: [], deleted: [] } — arrays of { id, alias, title, updated_at }
doc.published Document transitions from draft to published { doc }
doc.unpublished Document transitions from published to draft { doc }
doc.moved Document’s parent changes { doc, from_parent_alias, to_parent_alias }
doc.project_changed Document (and its subtree) moves to another project in the same workspace { doc, from_project_id, from_project_alias, to_project_id, to_project_alias, from_parent_alias, to_parent_alias, subtree_count }
doc.exposure_changed Document exposure level changes { doc, from, to }
doc.archived Document enters the archive (see Archiving Documents) { doc, replaced_by, cascaded } — fires once per affected document; cascaded is true for descendants archived with a subtree
doc.unarchived Document is restored from the archive { doc, cascaded } — never cascaded; restoring affects one document

Note: docs.changed is debounced — rapid edits are batched into a single delivery roughly every 10 seconds. Lifecycle events (doc.published, doc.unpublished, doc.moved, doc.project_changed, doc.exposure_changed, doc.archived, doc.unarchived) fire immediately and are additive to docs.changed. Subscribe to only the lifecycle events if you don’t need to track every edit. doc.project_changed fires in the context of the destination project, so the envelope’s project_id and project_alias reflect the target.

Deleting a document reports its whole subtree in docs.changed — every descendant appears in the deleted array, not just the document that was acted on.

Project events

Event Fires when Key data fields
project.created New project created { project }
project.updated Name, alias, or settings changed { project, changed_fields: [...] }
project.deleted Project deleted { project }

Member events

Member events fire for both workspace-level and project-level changes. When project_id is absent from the envelope, the change is workspace-level.

Event Fires when Key data fields
member.added User added to workspace or project { member }
member.removed User removed { member }
member.role_changed Role updated { member, from_role, to_role }

Glossary events

All glossary events are workspace-scope — project_id is always omitted from the envelope.

Event Fires when Key data fields
glossary.term_added Term created { term }
glossary.term_updated Definition, aliases, or settings changed { term }
glossary.term_deleted Term removed { term } (snapshot at delete time)
glossary.imported Bulk import completed { created, updated, total }

Note: Bulk import fires a single glossary.imported event rather than one per term. Fetch the current term list from the Glossary page if you need the full updated state.

What’s next?

Verifying Webhook Signatures — Verify that events come from Meldoc.

Delivery and Retries — Retry behavior and the delivery log.