Skip to main content

Subscriptions

A subscription asks Andromeda to tell you when entities change. You name what to watch and where to send the message, and every matching write sends one notification. This guide creates a subscription, watches a notification arrive, shapes what the notification holds, and manages the subscription through its life. The exact rules behind every step are on Subscriptions and notifications.

Where notifications go​

Notifications need somewhere to go. The endpoint in these examples is http://127.0.0.1:8085/notify, and the Quickstart has a one-line receiver that prints every notification and answers 204. Run it in a second terminal before you create the subscription.

Creating a subscription​

Send the subscription to POST /ngsi-ld/v1/subscriptions. Name what to watch in entities or watchedAttributes, name the endpoint in notification, and narrow it with a query if you only care about some of the changes.

POST /ngsi-ld/v1/subscriptions
Content-Type: application/json

{
"id": "urn:ngsi-ld:Subscription:fast-vehicles",
"type": "Subscription",
"entities": [
{
"type": "Vehicle"
}
],
"watchedAttributes": [
"speed"
],
"q": "speed>90",
"notification": {
"endpoint": {
"uri": "http://127.0.0.1:8085/notify",
"accept": "application/json"
}
}
}
HTTP/1.1 201 Created
Location: /ngsi-ld/v1/subscriptions/urn:ngsi-ld:Subscription:fast-vehicles

Leave the id out and Andromeda mints one, naming it in the Location header. The @context you create the subscription under expands its attribute and type names, and it becomes the subscription's jsonldContext unless you set one yourself.

Andromeda checks the whole subscription when you write it, filters included. A malformed q is refused with 400 now, not when the first change arrives.

Seeing a notification arrive​

Push a vehicle over the limit.

PATCH /ngsi-ld/v1/entities/urn:ngsi-ld:Vehicle:A4567/attrs
Content-Type: application/json

{
"speed": {
"type": "Property",
"value": 95
}
}

The write answers 204, and the receiver prints the notification.

{
"id": "urn:ngsi-ld:Notification:5d3e1c0a-6f2b-4a8e-9c47-1b2d3e4f5a6b",
"type": "Notification",
"subscriptionId": "urn:ngsi-ld:Subscription:fast-vehicles",
"notifiedAt": "2026-10-24T09:15:02.481Z",
"data": [
{
"id": "urn:ngsi-ld:Vehicle:A4567",
"type": "Vehicle",
"speed": {
"type": "Property",
"value": 95
}
}
]
}

data holds the whole entity as it stands after the write, not only the attributes that changed. The notification was sent because a subscription listens for created and updated attributes by default, and speed was just updated. A write that changed five attributes would still have sent one notification.

Two defaults trip people up. A subscription hears about creations and updates, but not deletions. Deleting an attribute or an entity only notifies a subscription that asks for the attributeDeleted, entityUpdated or entityDeleted trigger. And watchedAttributes decides what can trigger a notification, not what the notification holds. Both are covered under What triggers a notification.

Shaping the notification​

Everything inside notification besides endpoint shapes what the notification holds.

{
"notification": {
"endpoint": {
"uri": "http://127.0.0.1:8085/notify"
},
"attributes": [
"speed"
],
"format": "keyValues",
"showChanges": true,
"sysAttrs": true
}
}
  • attributes narrows data to the members you name. pick and omit do the same job from the other direction, and both can follow relationships into linked entities.
  • format picks the representation, normalized by default, or concise, or keyValues (whose synonym is simplified).
  • showChanges adds what each changed attribute held before the write, in a member such as previousValue. It needs normalized or concise; the key-value formats have nowhere to put a previous value.
  • sysAttrs adds createdAt and modifiedAt.

A deletion is notified like any other change, with the NGSI-LD Null in place of the value the attribute held. A deleted entity is notified with its id, its type and deletedAt, and none of its attributes.

What a notification holds has the full picture, including datasetId narrowing, the lang filter and ngsildConformance for clients that speak older versions of NGSI-LD.

Pacing the notifications​

throttling is the shortest time, in seconds, between two notifications of one subscription. A change inside the window gets no notification, and nothing is queued for later.

{
"throttling": 30
}

timeInterval makes the subscription periodic instead. Every timeInterval seconds it sends the current state of every entity it matches, whether anything changed or not.

{
"timeInterval": 60,
"entities": [
{
"type": "Vehicle"
}
]
}

A periodic subscription isn't notified of changes at all, and the two members can't sit side by side. A periodic one needs entities, and it takes neither watchedAttributes nor throttling. The schedule starts when the subscription is created; the first notification goes out one interval later.

Throttling, cooldown and periodic notifications has the rest, including how a failed delivery sets its own cooldown.

Reading subscriptions back​

GET /ngsi-ld/v1/subscriptions lists them, in identifier order and in pages.

GET /ngsi-ld/v1/subscriptions?limit=5

A limit above 1,000 is refused with 403 TooManyResults. Pagination explains how to walk the rest of the list.

After its first notification, a subscription reports how delivery is going:

{
"id": "urn:ngsi-ld:Subscription:fast-vehicles",
"notification": {
"status": "ok"
},
"timesSent": 3,
"timesFailed": 0,
"lastNotification": "2026-10-24T09:15:02.481Z",
"lastSuccess": "2026-10-24T09:15:02.481Z"
}

timesSent and timesFailed count notifications sent and failures, lastNotification, lastSuccess and lastFailure time the latest of each, and notification.status is ok or failed. A subscription that has notified nothing reports none of these, not even a zero, and values you send for them are ignored.

Changing and deleting​

PATCH /ngsi-ld/v1/subscriptions/{id} changes only the members you send. This fragment pauses the subscription and narrows its query in one write.

PATCH /ngsi-ld/v1/subscriptions/urn:ngsi-ld:Subscription:fast-vehicles
Content-Type: application/json

{
"isActive": false,
"q": "speed>110"
}

The answer is 204. To remove a member, write it as the NGSI-LD Null, urn:ngsi-ld:null. The rules that tie members together, such as timeInterval excluding throttling, are checked against the subscription as it stands after the update, so an update that would leave them side by side is refused.

Delete with the identifier from the Location header.

DELETE /ngsi-ld/v1/subscriptions/urn:ngsi-ld:Subscription:fast-vehicles

It answers 204, and stops notifying at once. A subscription deleted and created again under the same id starts with no delivery history.

Other ways to receive​

The endpoint's scheme decides how a notification travels. http and https send one POST per notification, and every 2xx answer counts as a success. mqtt and mqtts publish one message to an MQTT broker and topic, with the headers an HTTP delivery would carry folded into a metadata member beside the body. How failures are retried depends on notifications.delivery.mode, which the operator sets. "live" sends once from memory, and "durable" queues and retries.

Delivery has the HTTP headers, the MQTT envelope and the retry modes.

What gets refused​

The subscription is checked as a whole when you write it. The refusals that come up most are as follows.

  • 400 BadRequestData for neither entities nor watchedAttributes. One of the two is required, unless localOnly is true.
  • 400 BadRequestData for showChanges beside keyValues or simplified. Use normalized or concise.
  • 400 BadRequestData for timeInterval beside throttling or watchedAttributes. An update that would leave them side by side is refused too.
  • 400 BadRequestData for an expiresAt in the past.
  • 504 LdContextNotAvailable for a jsonldContext Andromeda can't fetch. It is fetched when you write the subscription, so a broken URL fails at once.

What gets refused has the list, and Subscriptions in Strictness has every rule.

Where next​

A subscription can also hear about entities a registered context source holds, and about the registrations themselves. Source subscriptions covers the second; the federation guide explains how entities reach this broker from elsewhere in the first place.