HCMS Change Notifications
Explains how to get notified about content changes in the Headless CMS via HTTP
Change Notifications
Notifications are a mechanism for integration with external system that needs to be notified about changes with low latency. It is a low-level mechanism. It operates at the level of assets, not entities. The external system is notified about changed assets and can react with its custom logic that maps asset ids to entities, if needed.
Notification itself is done as HTTP POST request to configured URL ("webhook") with array of asset/entity ids in its body. If this request fails, it is repeated until success.
Notification system is available only in delivery infrastructure (satellite) and not in server version.
It is disabled by default and must be explicitly enabled by a special elements in the configuration XML (element <cluster> and its sub-element <notifications>).
Subscription
Notifications are configured as subscription that contains url to be notified, name and optional filter. Any number of subscriptions can be defined, even with the same url.
Subscription is identified by unique identifier called "key". Unlike entity id, subscription key is not limited to number and its value can be any non-empty string. Internally, this key is used to construct censhare:resource-key feature by appending it to configured prefix.
Subscriptions are managed by REST API endpoints at prefix /daemon/notification:
- /daemon/notification (GET)
- Lists all subscriptions as a paginated list (see Rest Endpoints) for response format and supported query arguments). Subscriptions are aways ordered by their names, and it is not possible to change this order.
- /daemon/notification (POST)
- Creates a new subscription, or update existing one. Equivalent of PUT on /daemon/notification/{key}, except that the key must be specified as part of the request body.
- /daemon/notification/{key} (GET, PUT, DELETE)
- GET retrieves the subscription.
- PUT updates the subscription, or creates it if does not yet exist.
- Request body must contain valid JSON with one required property ("url"). The Subscription key is always taken from the URL path; any "key" property in request body is ignored.
- If the new subscription content is not valid PUT returns 400 Bad Request.
- Response always returns new subscription configuration on success.
- If the subscription does not exist, GET returns 404 Not Found.
- /daemon/notification/{key} (DELETE)
- Removes the subscription.
- Response is empty with status 204 on success.
All these endpoints require role schema-rw
Subscription JSON object can contain up to four properties:
- "key": identifier, string, mandatory
- "name": short name/description, string
- Used to sort subscriptions in listing.
- This property is not required when creating or updating; "key" is used as a default value.
- "url": notification endpoint, string, mandatory
- Only HTTP protocol (http and https) is supported.
- URL is parsed and validated when creating or updating the subscription (PUT or POST).
- "filter": filter expression, string, optional
- Query expression in the same syntax as accepted by the /query endpoint.
- When present, notification will be sent only for entities that match this query; other changes will be ignored by this subscription.
- Expression is parsed and validated when creating or changing subscription (PUT or POST) and invalid expressions are refused (400 Bad Request).
- Note that this validation use current schema(s). If the schema referenced by filter expression changes in an incompatible way (for example, property or even whole schema is removed), the filter will stop working and all asset changes will be notified (with warning message in satellite log).
- Note that filter is always applied to current state of the entity - that is, after the change. If the change itself changed filter evaluation result (from matched to ignored), this notification is not sent!
- Note that deleted asset never matches. This means that subscription with filter does not send notifications about deleted assets, ever!
Subscription is automatically activated when created and all following changes are sent to the specified url. Asset of this entity is also used to store data about current state in storage item content; this storage is not accessible by REST API.
Subscription can be updated at any time and new values will be immediately used. Note that new url and filter values affect also retries of previous failed invocations.
Subscription can be deleted. This immediately disables further notifications. Internal state (stored in storage item) is also discarded; new subscription with the same content will start anew.
Notification Request
Notification itself is sent as HTTP POST to configured url. Body of this request is always JSON object (mime type application/json) with two properties:
- ids: array of ids of changed assets
- contains id of each created, updated, or deleted asset
- each id can be present only once, even if there were several changes since last change
- subscription: the subscription JSON
Example:
{"ids":[13856,13851],"subscription":{"name":"test 1","id":14336,"url":"http://localhost:8000/hook/test1","filter":"@image"}}
Notification is not sent immediately after each change - that would generate too much traffic. Changes are instead grouped together to small batches and sent with small delay, up to 300 milliseconds by default (can be changed in configuration).
By default, only one instance (satellite) in Headless CMS cluster sends notifications and maintains internal state. If this instance stops (for any reason), one of the other ones picks up this role and starts sending updates. This usually takes several minutes (at least 3 minutes in default configuration).
No notifications are sent during this transitional period, but no events are lost: any changes are sent as part of the new notification(s).
It is possible that some notifications are duplicated (if the old server managed to send notification, but not save this to persistent state), but no changes are lost.