HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityAcademySubmit a ticketLog In
Dev Guide

Subscribe to events with webhooks

Use the Optimizely CMS (SaaS) REST API to subscribe to content lifecycle events and receive the event data at your own endpoint.

A webhook sends event data from CMS (SaaS) to a system of your choice when something happens to the content. Subscribe to the events your integration cares about. CMS (SaaS) then sends an HTTP POST request to your endpoint each time one of those events occurs, so your integration reacts to the event instead of polling CMS (SaaS) for changes.

Webhooks are useful when a change to content should trigger work somewhere else. Examples include sending content to Optimizely Opal, pushing a published page to a translation service, and rebuilding a downstream cache when content is deleted.

Manage webhooks with the REST API, as described in this article, or from the CMS (SaaS) UI.

Prerequisites

  • You need an access token to call the Webhooks endpoints.
  • You need an endpoint that accepts HTTP POST requests and confirms the verification message that CMS (SaaS) sends to it. See Verify your endpoint.

Endpoints

🚧

Experimental

The Webhooks endpoints are experimental and subject to change.

The Webhooks endpoints let you list the available event types and manage your subscriptions.

EndpointMethodDescription
/v1/experimental/webhookdefinitionsGETLists the event types you can subscribe to.
/v1/experimental/webhooksGETLists webhook subscriptions.
/v1/experimental/webhooksPOSTCreates a webhook subscription.
/v1/experimental/webhooks/{key}GETGets a webhook subscription by its key.
/v1/experimental/webhooks/{key}PATCHUpdates a webhook subscription.
/v1/experimental/webhooks/{key}DELETEDeletes a webhook subscription.

Create a webhook subscription

Send a POST request with the subscription in the request body. The following example subscribes to two content events and filters them to a single content item.

POST https://api.cms.optimizely.com/v1/experimental/webhooks
Content-Type: application/json
Authorization: Bearer ACCESS_TOKEN
{
  "key": "content-change-notifications",
  "displayName": "Content change notifications",
  "description": "Notifies the integration service when content is created or deleted.",
  "endpoint": "https://example.com/hooks/cms",
  "eventTypes": [
    "content:preview1:created",
    "content:preview1:deleted"
  ],
  "dataFilters": [
    {
      "field": "key",
      "operator": "StringIn",
      "values": ["6946107a8ad6414f8f1786364dab1ec2"]
    }
  ],
  "bearerToken": "YOUR_SHARED_SECRET"
}

CMS (SaaS) returns the stored subscription:

{
  "key": "content-change-notifications",
  "displayName": "Content change notifications",
  "description": "Notifies the integration service when content is created or deleted.",
  "endpoint": "https://example.com/hooks/cms",
  "eventTypes": [
    "content:preview1:created",
    "content:preview1:deleted"
  ],
  "dataFilters": [
    {
      "field": "key",
      "operator": "StringIn",
      "values": ["6946107a8ad6414f8f1786364dab1ec2"]
    }
  ],
  "bearerToken": "YOUR_SHARED_SECRET",
  "isVerified": false,
  "isDisabled": false,
  "created": "2026-08-26T10:30:00+00:00",
  "createdBy": "USER_NAME",
  "lastModified": "2026-08-26T10:30:00+00:00",
  "lastModifiedBy": "USER_NAME"
}

Each subscription covers events from one category and one version of that category. Do not mix event types from different categories in the same subscription.

Subscription fields

A subscription has the following fields.

FieldDescription
keyThe unique identifier of the subscription. Three to 64 characters, and it can contain letters, numbers, and dashes. This is not the same as the content key in the event payloads.
displayNameRequired. The name that identifies the subscription in the UI. Up to 255 characters.
descriptionDescribes what the subscription is for. Up to 512 characters.
endpointRequired. The URL that receives the HTTP POST requests.
eventTypesThe event types the subscription receives. See Event types.
dataFiltersNarrows which events the subscription receives. See Data filters.
bearerTokenA secret you choose. CMS (SaaS) sends it in the Authorization header of every request, so your endpoint can confirm the request came from CMS (SaaS). This is not the access token you use to call the Webhooks endpoints.
isVerifiedRead-only. Whether the endpoint has confirmed the verification message.
isDisabledWhether the subscription is turned off. When true, CMS (SaaS) does not send events to the endpoint.
created, createdBy, lastModified, lastModifiedByRead-only audit fields.

Update a webhook subscription

Send a PATCH request to change a subscription. The following example turns a subscription off without deleting it.

PATCH https://api.cms.optimizely.com/v1/experimental/webhooks/content-change-notifications
Content-Type: application/merge-patch+json
Authorization: Bearer ACCESS_TOKEN
{
  "isDisabled": true
}

Delete a webhook subscription

Send a DELETE request to remove a subscription. CMS (SaaS) stops sending events to its endpoint.

DELETE https://api.cms.optimizely.com/v1/experimental/webhooks/content-change-notifications
Authorization: Bearer ACCESS_TOKEN

Event types

An event type has the format {resource}:{version}:{action}, such as contentVersion:preview1:published. The resource is the category of entity the event applies to.

Call GET /v1/experimental/webhookdefinitions to list the event types your instance supports, along with their display names and descriptions.

The Filterable fields column lists the fields you can use in data filters for that event type.

Content

Events for a content item. The payload identifies the content item by its key.

Event typeFires whenPayload fieldsFilterable fields
content:preview1:createdContent is created.keykey
content:preview1:updatedContent moves to a different parent, excluding a move to the wastebasket.keykey
content:preview1:deletedContent is deleted, either moved to the wastebasket or deleted permanently.key, isPermanentkey, isPermanent

The content payload has the following schema and sample.

{
  "type": "object",
  "properties": {
    "key": { "type": "string" },
    "isPermanent": { "type": "boolean" }
  },
  "required": ["key"]
}
{
  "key": "6946107a8ad6414f8f1786364dab1ec2",
  "isPermanent": false
}

The isPermanent field only appears on content:preview1:deleted. It is true when the content is deleted permanently, and false when the content moves to the wastebasket.

Deleting a content item together with its children sends one content:preview1:deleted event, not one event for each child.

Content version

Events for a specific version of a content item. The payload identifies the version by the content key and the version.

Event typeFires whenPayload fieldsFilterable fields
contentVersion:preview1:publishedContent is published.key, versionkey, version
contentVersion:preview1:scheduledContent is scheduled for publishing at a future date.key, versionkey, version
contentVersion:preview1:localeDeletedA language branch of content is deleted.key, versionkey, version

The content version payload has the following schema and sample.

{
  "type": "object",
  "properties": {
    "key": { "type": "string" },
    "version": { "type": "string" }
  },
  "required": ["key", "version"]
}
{
  "key": "6946107a8ad6414f8f1786364dab1ec2",
  "version": "456"
}

Display template

Events for a display template. The payload is the display template resource.

Event typeFires whenFilterable fields
displayTemplate:v1:createdA display template is created.id, key, name, nodeType, baseType, contentTypeID, isDefault
displayTemplate:v1:updatedAn existing display template is updated.id, key, name, nodeType, baseType, contentTypeID, isDefault
displayTemplate:v1:deletedAn existing display template is deleted.id, key, name, nodeType, baseType, contentTypeID, isDefault

Webhook

Events for the webhook subscriptions themselves, so you can track configuration changes. The payload is the subscription resource described in Subscription fields.

Event typeFires whenFilterable fields
webhookSubscription:v1:createdA webhook subscription is created.key, displayName, description, endpoint, isVerified, isDisabled
webhookSubscription:v1:updatedAn existing webhook subscription is updated.key, displayName, description, endpoint, isVerified, isDisabled
webhookSubscription:v1:deletedAn existing webhook subscription is deleted.key, displayName, description, endpoint, isVerified, isDisabled

Data filters

A data filter narrows which events reach your endpoint by matching a field in the event payload. A subscription only receives an event when the event matches the filters.

Each filter has the following fields.

FieldDescription
fieldThe payload field to match, such as key. Use the Filterable fields listed for the event type in Event types. The field name cannot contain spaces, start or end with a period, or contain consecutive periods.
operatorThe comparison to apply. See Filter operators.
valuesThe values to compare the field against. Range operators take each range as two numbers separated by a comma, such as "1,10".

The following limits apply to filters:

  • A maximum of 20 values across the filters on a subscription.
  • A maximum of 475 characters for each value.

Filter operators

The following operators are available.

OperatorMatches when the fieldValues
StringInEquals one of the values.One or more strings
StringNotInEquals none of the values.One or more strings
StringContainsContains one of the values.One or more strings
StringNotContainsContains none of the values.One or more strings
StringBeginsWithBegins with one of the values.One or more strings
StringNotBeginsWithBegins with none of the values.One or more strings
StringEndsWithEnds with one of the values.One or more strings
StringNotEndsWithEnds with none of the values.One or more strings
NumberInEquals one of the numbers.One or more numbers
NumberNotInEquals none of the numbers.One or more numbers
NumberInRangeFalls within one of the ranges.One or more ranges
NumberNotInRangeFalls outside every range.One or more ranges
NumberLessThanIs less than the number.One number
NumberLessThanOrEqualsIs less than or equal to the number.One number
NumberGreaterThanIs greater than the number.One number
NumberGreaterThanOrEqualsIs greater than or equal to the number.One number
BoolEqualsEquals the boolean value.true or false
IsNullOrUndefinedHas no value.None
IsNotNullHas a value.None

Callback delivery

CMS (SaaS) delivers each event to your endpoint as a CloudEvent, which is a standard envelope format for event data. The type field holds the event type. The subject field holds the path of the affected entity, in the form /{resource}/{version}/{key}. For contentVersion events, the subject ends with the version identifier when the event has one. The entity itself is in the data field.

The following example shows the body of a delivered event.

{
  "type": "contentVersion:preview1:published",
  "subject": "/contentVersion/preview1/6946107a8ad6414f8f1786364dab1ec2/456",
  "data": {
    "key": "6946107a8ad6414f8f1786364dab1ec2",
    "version": "456"
  }
}

CMS (SaaS) sends an event only when the subscription is verified, is not disabled, and matches both the event type and any data filters.

Optimizely provisions and manages the delivery infrastructure. This includes the retries for failed deliveries and the dead-letter queue for events that cannot be delivered. These settings are not configurable. Because a failed delivery is retried, your endpoint can receive the same event more than once. Handle events idempotently, so that processing the same event twice has the same result as processing it one time.

Authenticate the requests

When the subscription sets bearerToken, CMS (SaaS) sends that value in the Authorization header of every request:

Authorization: Bearer YOUR_SHARED_SECRET

Confirm the token before you act on the request. This token is the static secret stored on the subscription, not the access token you use to call the Webhooks endpoints.

Verify your endpoint

CMS (SaaS) confirms that you control an endpoint before it sends events to it. When you create a subscription, isVerified is false and CMS (SaaS) sends a verification message to the endpoint. When your endpoint confirms the message, isVerified becomes true and CMS (SaaS) starts delivering events.

Verification is tied to the endpoint URL, so changing the URL of an existing subscription starts the verification again.


Did this page help you?