Skip to content

Reference

Events and webhooks

The events the CMS sends when content changes, what each one carries, how it is delivered, and which reach webhooks.

Reference9 min read

When something changes in a space, such as a page going live or a menu being edited, the CMS records an event. Events let websites and other systems react to changes without asking the CMS over and over.

Where events go

Every event goes to two places.

Orbit Exchange
What it gets
Every event, in full
Format
The event envelope below
Webhooks
What it gets
Only events that have a webhook name, and only those the webhook listens for
Format
A short signed message with the webhook name and a smaller set of data

Orbit Exchange is the hub that connects Orbit products. It receives each event with everything the CMS knows about it.

Webhooks are addresses you register in Configuration › Webhooks. They are meant for websites that need to refresh a cache. See Refresh the website when content changes to set one up.

The envelope

Every event sent to Orbit Exchange has the same outer shape. Only data differs between events.

id
Type
string (UUID)
What it holds
A unique ID for this event. Use it to spot duplicates.
type
Type
string
What it holds
The event name, such as cms.page.published.
version
Type
integer
What it holds
The version of this event's data shape. It goes up only if the shape changes in a way that could break a receiver.
time
Type
string (ISO 8601, UTC)
What it holds
When the change happened.
source
Type
string
What it holds
Always cms for these events.
sequence
Type
integer
What it holds
A number that goes up with every event the CMS sends.
tenant.organisationId
Type
string
What it holds
The organisation the change happened in.
tenant.spaceId
Type
string or null
What it holds
The space.
tenant.environmentKey
Type
string or null
What it holds
The environment key, such as production.
tenant.regionKey
Type
string or null
What it holds
The region key, such as de.
tenant.localeCode
Type
string or null
What it holds
The language code, such as de-DE.
subject.resourceType
Type
string
What it holds
What changed: cms.page, cms.release, cms.redirect or cms.navigation.
subject.id
Type
string
What it holds
The ID of the thing that changed.
actor.type
Type
string
What it holds
Who did it: user, apiKey, agent, system or service.
actor.id
Type
string or null
What it holds
Their ID. It is null for system, for example a scheduled release.
data
Type
object
What it holds
The details of the change. See the event families below.

A full example, for a page going live:

JSON
{  "id": "3f2b6c1e-8d4a-4f7b-9a51-2c0e7d9b1a44",  "type": "cms.page.published",  "version": 1,  "time": "2026-10-17T09:30:00.000Z",  "source": "cms",  "sequence": 48213,  "tenant": {    "organisationId": "6650f1c2a9e4b3d2c1f0e9a8",    "spaceId": "6650f1c2a9e4b3d2c1f0e9b1",    "environmentKey": "production",    "regionKey": "germany",    "localeCode": "de-DE"  },  "subject": { "resourceType": "cms.page", "id": "6650f1c2a9e4b3d2c1f0ea07" },  "actor": { "type": "user", "id": "6650f1c2a9e4b3d2c1f0e011" },  "data": {    "contentId": "6650f1c2a9e4b3d2c1f0ea07",    "contentType": "page",    "name": "Hiking boots",    "url": "/products/hiking-boots",    "locale": "de-DE",    "region": "germany",    "environment": "production",    "version": 7,    "revisionId": "6650f1c2a9e4b3d2c1f0eb42",    "publishedAt": "2026-10-17T09:30:00.000Z",    "redirectFrom": null  }}

Delivery guarantees

Orbit Exchange: at least once. Each event is kept until Orbit Exchange accepts it. If Orbit Exchange cannot be reached, the CMS tries again after 30 seconds, then waits twice as long each time, up to an hour between tries, for 12 tries in all (about five hours). Because a try can succeed even when the answer is lost, the same event can arrive more than once.

Webhooks: once, when the change happens. A webhook message is sent while the change is being saved. If your endpoint fails or does not answer within 10 seconds, the failure is shown in the webhook's Deliveries, but the message is not sent again. See Retries and failures in the webhooks guide.

Order. Events are sent in the order the changes happen, but a retried event can arrive after newer ones. Sort by sequence when order matters. The number is shared across the whole platform, so gaps between your events are normal. Only the order means anything.

Make receivers idempotent. Handling the same event twice should do no harm.

  • In Orbit Exchange events, keep the id of events you have handled and skip any you have seen.
  • Webhook messages carry no event ID. Refreshing a cache twice is harmless, so most receivers need no extra work. If yours does more, combine event, contentId and version.
  • Treat an event as a sign that something changed, not as the final state. If two changes arrive out of order, fetch the current content from the delivery API instead of trusting the older message.

Event families

Pages and entries

These events are about one item of content in one region and language. "Pages" here also covers entries without an address, such as global content. Those have url set to null.

Every page event carries these fields in data:

contentId
Type
string
What it holds
The item's ID.
contentType
Type
string
What it holds
The content type key, such as page.
name
Type
string
What it holds
The item's name in the CMS.
url
Type
string or null
What it holds
The page address, such as /products/hiking-boots. null for entries without an address.
locale
Type
string or null
What it holds
The language code.
region
Type
string or null
What it holds
The region key.
environment
Type
string or null
What it holds
The environment key.

Each event then adds its own fields.

cms.page.published
Triggered when
A page is published, or its changes are, by hand, on a schedule or in a release.
Extra fields
version, revisionId, publishedAt, and redirectFrom, the old address if the address changed and a redirect was added.
Webhook
content.published
cms.page.unpublished
Triggered when
A page is taken offline.
Extra fields
revisionId
Webhook
content.unpublished
cms.page.rolledBack
Triggered when
A page goes back to an earlier version.
Extra fields
toVersion, revisionId, and republished, which is true if the page was live and the older version went live too.
Webhook
content.published
cms.page.promoted
Triggered when
A page is copied into another environment.
Extra fields
sourceContentId, fromEnvironment, toEnvironment, and created, which is true if the page was new there.
Webhook
content.published, to webhooks on the environment it was copied into
cms.page.trashed
Triggered when
A page is moved to the bin.
Extra fields
None
Webhook
content.deleted
cms.page.restored
Triggered when
A page comes back from the bin.
Extra fields
None
Webhook
None
cms.page.purged
Triggered when
A page in the bin is erased for good.
Extra fields
None
Webhook
None

An unpublished event, as data:

JSON
{  "contentId": "6650f1c2a9e4b3d2c1f0ea07",  "contentType": "page",  "name": "Hiking boots",  "url": "/products/hiking-boots",  "locale": "de-DE",  "region": "germany",  "environment": "production",  "revisionId": "6650f1c2a9e4b3d2c1f0eb57"}

Releases

cms.release.published is sent once a release has run, by hand or on its schedule. Each page in the release also sends its own cms.page.published or cms.page.unpublished event first.

releaseId
Type
string
What it holds
The release's ID.
name
Type
string
What it holds
The release name.
published
Type
array of strings
What it holds
IDs of the items that went live.
unpublished
Type
array of strings
What it holds
IDs of the items taken offline.
failed
Type
array of objects
What it holds
Items that could not be published, each with contentId and reason.
scheduled
Type
boolean
What it holds
true if the release ran on its schedule.
JSON
{  "releaseId": "6650f1c2a9e4b3d2c1f0ec10",  "name": "Autumn offers",  "published": ["6650f1c2a9e4b3d2c1f0ea07", "6650f1c2a9e4b3d2c1f0ea19"],  "unpublished": [],  "failed": [],  "scheduled": true}

Webhook name: release.published.

cms.navigation.changed is sent when a menu is created, changed or deleted.

JSON
{ "navigationId": "6650f1c2a9e4b3d2c1f0ed21", "key": "main", "action": "updated" }

action is created, updated or deleted. Webhook name: navigation.changed.

Redirects

cms.redirect.changed is sent when a redirect is created, changed or removed, including redirects the CMS adds itself when a page address changes.

JSON
{  "redirectId": "6650f1c2a9e4b3d2c1f0ee33",  "action": "created",  "source": "/products/hiking-boot",  "destination": { "type": "content", "url": null, "contentId": "6650f1c2a9e4b3d2c1f0ea07" },  "statusCode": 301,  "origin": null}

destination.type is url for a fixed address, or content for a page in the CMS. Redirect events go to Orbit Exchange only. They do not reach webhooks.

Media and other changes

Uploading or changing media, and editing settings, schemas or other screens, does not send an event. Only the changes listed above do.

Webhook messages

A webhook gets a smaller message than Orbit Exchange. The body is JSON with three fields:

event
Type
string
What it holds
The webhook name, such as content.published, or webhook.test for a test.
sentAt
Type
string (ISO 8601, UTC)
What it holds
When the message was sent.
data
Type
object
What it holds
The fields below.
content.published, content.unpublished, content.deleted
data fields
contentId, url, name, locale, region, and version when the page was published
release.published
data fields
releaseId, name, published
navigation.changed
data fields
navigationId, key
webhook.test
data fields
webhook, the webhook's name
JSON
{  "event": "content.published",  "sentAt": "2026-10-17T09:30:00.412Z",  "data": {    "contentId": "6650f1c2a9e4b3d2c1f0ea07",    "url": "/products/hiking-boots",    "name": "Hiking boots",    "locale": "de-DE",    "region": "germany",    "version": 7  }}

The headers and how to check the signature are in Refresh the website when content changes.

What the SDK refreshes

The SDK's createRevalidateHandler turns each webhook message into the cache tags to refresh. It only works if the client is set up with cache: { tags: true }. See The SDK.

content.published, content.unpublished, content.deleted for a page with an address
Tags refreshed
The page, cms:page:{region}:{url}, plus lists (cms:list), the sitemap (cms:sitemap) and everything read with references (cms:references). Without a region, everything (cms).
The same events for an entry without an address
Tags refreshed
Global content (cms:global), lists (cms:list), popups (cms:popups), banners (cms:banners) and everything read with references (cms:references)
navigation.changed
Tags refreshed
That menu, cms:nav:{key}
release.published
Tags refreshed
Lists, the sitemap and everything read with references. The pages themselves are refreshed by their own events.
webhook.test
Tags refreshed
Nothing
Anything else
Tags refreshed
Everything (cms)

For example, publishing /products/hiking-boots in region germany refreshes cms:page:germany:/products/hiking-boots, cms:list, cms:sitemap and cms:references.

Not using the SDK? Connect a website without Next.js shows how to refresh your own cache.

Every event

The table below is built from the live list of events, so it is always current.

cms.page.publishedversion 1
When
A page or entry went live, or its changes did.
Webhook event
content.published
cms.page.unpublishedversion 1
When
A page or entry was taken offline.
Webhook event
content.unpublished
cms.page.rolledBackversion 1
When
A page went back to an earlier version.
Webhook event
content.published
cms.page.promotedversion 1
When
A page was copied live into another environment.
Webhook event
content.published
cms.page.trashedversion 1
When
A page or entry was moved to the bin.
Webhook event
content.deleted
cms.page.restoredversion 1
When
A page or entry came back from the bin.
Webhook event
Orbit Exchange only
cms.page.purgedversion 1
When
A trashed page was erased for good.
Webhook event
Orbit Exchange only
cms.release.publishedversion 1
When
A release went live with all its pages.
Webhook event
release.published
cms.redirect.changedversion 1
When
A redirect was created, changed or removed.
Webhook event
Orbit Exchange only
cms.navigation.changedversion 1
When
A menu changed.
Webhook event
navigation.changed

Was this page helpful?

Read next