Outbound webhook contract
Outbound webhooks notify an external system about content changes. They are not plugin commands or a place to run CMS business rules. Configure subscribers in Settings → Integrations → Outbound webhooks with the appropriate site permission. A notification failure does not undo publication, and delivery is best-effort with bounded retries, not a guarantee that every subscriber eventually receives an event.
While Save subscribers runs, editing is locked. If someone else saved first, your edits stay in the form; Reload and discard edits replaces them with the latest list. A failed subscriber or delivery-history read offers Try again. Retrying history keeps subscriber edits.
Events and envelope
Section titled “Events and envelope”Successful content, workflow, release, media and model mutations enqueue these events: content.created, content.updated, content.trashed, content.restored, content.deleted, content.published, content.unpublished, workflow.transitioned, release.applied, media.created, media.updated, media.deleted, model.applied. Refused writes, rolled-back transactions and idempotent replays create no new event. A coordinated release emits events only after its complete tenant commit.
The JSON body has id, event, site_id, occurred_at (ISO-8601) and data. Data identifies the affected item, model, media or release and includes the applicable committed version, revision and locale. Publication events identify the primary instance_id, model and publication state. Payloads omit private field snapshots and credentials. Read the appropriate API for current data; an unpublished or deleted item may no longer appear in public responses.
A successful mutation queues delivery as pending; it does not wait for a subscriber’s network response. The existing scheduled delivery worker makes the first attempt and any retries. All deliveries of one event retain its stable ID and original body, including manual replay.
HTTP and signature
Section titled “HTTP and signature”The sender makes a POST with Content-Type: application/json. X-Deewan-Event names the event. X-Deewan-Delivery is the subscriber configuration ID, not the event ID. X-Deewan-Signature is sha256= followed by the lowercase hexadecimal HMAC-SHA256 of the exact UTF-8 body bytes using the configured subscriber secret.
Verify the raw bytes before parsing, compare the signature safely, check the intended site and supported event. Then deduplicate the body’s stable id within your subscriber/site scope. Re-serializing JSON before verification changes the signed bytes. occurred_at is signed. Apply a replay policy that permits the legitimate retry window. There is no independent timestamp signature header.
The same event ID is used for delivery to multiple subscribers and for retries. Retries and replays retain the original body and are signed with the subscriber’s current secret, so secret changes need coordinated receiver updates. Each delivery records the subscriber id and URL it went to. A retry or replay is sent only while the subscriber with that id still has that URL. It is refused when the URL changed, the subscriber was removed, or the delivery predates destination recording. A new subscriber gets a random id and cannot take an id that already has delivery history. Never deduplicate solely on X-Deewan-Delivery, which is reused for unrelated events.
Acknowledgment and retry
Section titled “Acknowledgment and retry”Any 2xx acknowledges delivery. The default request deadline is 5 seconds. Unreachable requests, HTTP 408, 429 and 5xx are retryable. Other HTTP refusals are terminal. Up to five total attempts use exponential backoff from one minute, capped at one hour, with 50–100% jitter. A valid Retry-After in seconds or date form can increase the wait, capped at one hour. Exhaustion stops automatic retries.
The scheduled delivery worker claims records that are due and rechecks the current subscriber. Removed or disabled subscriptions do not receive retries. Do not assume ordering or exactly-once requests: a lost acknowledgment or lease recovery can repeat a notification whose effect already happened. A receiver should durably record its accepted event and apply its effect atomically before acknowledging it. Use existing delivery details in Settings to review failures or manually resend a notification. Do not interpret a failed response as proof that no effect occurred.
Receiver acceptance checks
Section titled “Receiver acceptance checks”Verify rejection of an invalid signature, altered bytes, wrong site and unsupported event. Confirm duplicate event IDs do not repeat effects, different IDs on the same subscriber do run, and a lost acknowledgment can be retried safely. A search receiver must follow the complete-generation withdrawal contract, rather than continually adding or updating items without removing withdrawn content.
Authorities: backend/src/lib/outbound-webhook.ts, backend/src/lib/outbound-retry.ts and backend/src/lib/lifecycle/publication-effects.ts. These outbound retry rules are separate from the plugin protocol.
Next step
Section titled “Next step”Manage content from scripts and AI agents with the CMS management API.
Unreleased / pre-MVP; no stable version
Source revision: fe23db481c422b40e317b92fc98116b4c0c26a87 (modified checkout)
Build date (UTC): 2026-10-18T09:22:34.630Z
Upgrade target: unavailable: modified checkout. Release notes