> For the complete documentation index, see [llms.txt](https://developer.celigo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.celigo.com/api/api-reference/monitoring/notifications.md).

# Notifications

Notification subscriptions control which users receive alerts for resource-level events (errors, status changes, completions) on flows, connections, integrations, and syncs. Each subscription routes alerts to the email of the subscribed user.

Subscriptions are account-scoped — an account admin can manage subscriptions on behalf of any user, not just their own.

### Notification schema

## The Notification object

```json
{"openapi":"3.2.0","info":{"title":"Notifications","version":"1.0.0"},"components":{"schemas":{"Notification":{"type":"object","required":["_id","type","lastModified"],"description":"A notification subscription linking a user email to a single resource\n(flow, connection, integration, or sync). When the resource emits an\nalert (error, state change, etc.), the subscribed user is notified.","allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"type":{"type":"string","enum":["flow","connection","integration","sync"],"description":"Which resource class this subscription targets. Implies which of\n`_flowId` / `_connectionId` / `_integrationId` / `_syncId` is populated."},"_flowId":{"type":"string","format":"objectId","description":"Flow id when `type: flow`."},"_connectionId":{"type":"string","format":"objectId","description":"Connection id when `type: connection`."},"_integrationId":{"type":"string","format":"objectId","description":"Integration id when `type: integration`."},"_syncId":{"type":"string","format":"objectId","description":"Sync id when `type: sync`."},"subscribedByUser":{"type":"object","description":"Minimal user descriptor for whoever owns this subscription.","properties":{"name":{"type":"string","description":"Display name of the subscribed user."},"email":{"type":"string","format":"email","description":"Email address the notifications are routed to."}}}}}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}},"required":["_id"]}}}}
```

## List notification subscriptions

> Returns notification subscriptions for flows, connections, integrations,\
> and syncs in the account. Without the \`users=all\` query parameter, the response is\
> scoped to the caller's own subscriptions. With \`users=all\`, every user's\
> subscriptions in the account are returned.\
> \
> Returns an empty response when the caller has no subscriptions in the\
> current scope. With \`users=all\`, an empty array is returned only in\
> accounts with zero subscriptions across all users.

```json
{"openapi":"3.2.0","info":{"title":"Notifications","version":"1.0.0"},"tags":[{"name":"Notifications","description":"Notification subscriptions control which users receive alerts for\nresource-level events (errors, status changes, completions) on flows,\nconnections, integrations, and syncs. Each subscription routes alerts\nto the email of the subscribed user.\n\nSubscriptions are account-scoped — an account admin can manage\nsubscriptions on behalf of any user, not just their own.\n\n## Notification schema\n\n{% openapi-schemas spec=\"notification\" schemas=\"Notification\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Notification":{"type":"object","required":["_id","type","lastModified"],"description":"A notification subscription linking a user email to a single resource\n(flow, connection, integration, or sync). When the resource emits an\nalert (error, state change, etc.), the subscribed user is notified.","allOf":[{"$ref":"#/components/schemas/ResourceResponse"},{"type":"object","properties":{"type":{"type":"string","enum":["flow","connection","integration","sync"],"description":"Which resource class this subscription targets. Implies which of\n`_flowId` / `_connectionId` / `_integrationId` / `_syncId` is populated."},"_flowId":{"type":"string","format":"objectId","description":"Flow id when `type: flow`."},"_connectionId":{"type":"string","format":"objectId","description":"Connection id when `type: connection`."},"_integrationId":{"type":"string","format":"objectId","description":"Integration id when `type: integration`."},"_syncId":{"type":"string","format":"objectId","description":"Sync id when `type: sync`."},"subscribedByUser":{"type":"object","description":"Minimal user descriptor for whoever owns this subscription.","properties":{"name":{"type":"string","description":"Display name of the subscribed user."},"email":{"type":"string","format":"email","description":"Email address the notifications are routed to."}}}}}]},"ResourceResponse":{"type":"object","description":"Response","properties":{"_id":{"type":"string","format":"objectId","readOnly":true,"description":"Unique identifier for the resource. Format is a 24-character hexadecimal string."},"createdAt":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was created. Set automatically and cannot be modified."},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"Timestamp when the resource was last updated. Changes whenever any property is modified."},"deletedAt":{"type":["string","null"],"format":"date-time","readOnly":true,"description":"Timestamp when the resource was soft-deleted. When null or absent, the resource is active."}},"required":["_id"]},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/notifications":{"get":{"operationId":"listNotifications","tags":["Notifications"],"summary":"List notification subscriptions","description":"Returns notification subscriptions for flows, connections, integrations,\nand syncs in the account. Without the `users=all` query parameter, the response is\nscoped to the caller's own subscriptions. With `users=all`, every user's\nsubscriptions in the account are returned.\n\nReturns an empty response when the caller has no subscriptions in the\ncurrent scope. With `users=all`, an empty array is returned only in\naccounts with zero subscriptions across all users.","parameters":[{"name":"users","in":"query","required":false,"schema":{"type":"string","enum":["all"]},"description":"When set to `all`, returns subscriptions for every user in the\naccount. When omitted, returns only the caller's own subscriptions."}],"responses":{"200":{"description":"Array of notification subscriptions.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Notification"}}}}},"204":{"description":"Caller has no subscriptions in the current scope (default scope when\n`users=all` is omitted). Not the same as 200 with `[]`."},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```

## Subscribe / unsubscribe users to resource notifications

> Upserts a batch of notification subscriptions. Each item targets exactly one\
> resource (\`\_flowId\`, \`\_connectionId\`, or \`\_integrationId\`) plus a\
> \`subscribedByUserEmail\`. \`subscribed: true\` creates (or keeps) the\
> subscription; \`subscribed: false\` removes it.\
> \
> Returns a parallel array of per-item results — one entry per request item,\
> in the same order. Each result carries \`statusCode\` (\*\*201\*\* when a subscription\
> was created, \*\*200\*\* when updated or removed, 422 when a referenced resource\
> doesn't exist) plus an \`errors\[]\` array on failures. An empty request body\
> returns an empty array.\
> \
> The body is a bare array (maximum 500 items). Each item must carry\
> exactly one of \`\_flowId\` / \`\_connectionId\` / \`\_integrationId\` /\
> \`\_syncId\`. The response is a per-item status array; referencing a\
> non-existent resource fails that item with \`statusCode: 422\` but\
> does not fail the whole request.

```json
{"openapi":"3.2.0","info":{"title":"Notifications","version":"1.0.0"},"tags":[{"name":"Notifications","description":"Notification subscriptions control which users receive alerts for\nresource-level events (errors, status changes, completions) on flows,\nconnections, integrations, and syncs. Each subscription routes alerts\nto the email of the subscribed user.\n\nSubscriptions are account-scoped — an account admin can manage\nsubscriptions on behalf of any user, not just their own.\n\n## Notification schema\n\n{% openapi-schemas spec=\"notification\" schemas=\"Notification\" grouped=\"true\" %}"}],"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"},{"url":"https://api.au.integrator.io","description":"Production (AU region)"},{"url":"https://api.ca.integrator.io","description":"Production (CA region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"NotificationsUpsertRequest":{"type":"array","maxItems":500,"description":"Bare array (no wrapping envelope) of upsert items. Each item targets a\nsingle resource and flips subscription state on or off for one user.","items":{"type":"object","description":"A single subscribe / unsubscribe directive. Set exactly one of\n`_flowId`, `_connectionId`, `_integrationId`, or `_syncId`.","if":{"required":["_flowId"]},"then":{"not":{"anyOf":[{"required":["_connectionId"]},{"required":["_integrationId"]},{"required":["_syncId"]}]}},"else":{"if":{"required":["_connectionId"]},"then":{"not":{"anyOf":[{"required":["_integrationId"]},{"required":["_syncId"]}]}},"else":{"if":{"required":["_integrationId"]},"then":{"not":{"required":["_syncId"]}},"else":{"required":["_syncId"]}}},"properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow id to subscribe / unsubscribe. Set exactly one of `_flowId` / `_connectionId` / `_integrationId` / `_syncId`."},"_connectionId":{"type":"string","format":"objectId","description":"Connection id to subscribe / unsubscribe."},"_integrationId":{"type":"string","format":"objectId","description":"Integration id to subscribe / unsubscribe."},"_syncId":{"type":"string","format":"objectId","description":"Sync id to subscribe / unsubscribe."},"subscribed":{"type":"boolean","description":"`true` creates the subscription (or no-ops if it already exists);\n`false` removes it."},"subscribedByUserEmail":{"type":"string","format":"email","description":"Email of the user whose subscription is being modified. Must match a\nuser in the account: one unknown email fails the entire request with\n**403** `invalid_access`, not just its own item."}},"required":["subscribed","subscribedByUserEmail"]}},"Error":{"type":"object","description":"Standard error response envelope returned by integrator.io APIs.","properties":{"errors":{"type":"array","description":"List of errors that occurred while processing the request.","items":{"type":"object","properties":{"code":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"Machine-readable error code. Usually a string like\n`invalid_ref`, `missing_required_field`, or `unauthorized`;\nmay be an **integer** when the error mirrors an upstream HTTP\nstatus (e.g. `500`) — most commonly returned by connection-ping\nand adaptor-proxy responses."},"message":{"type":"string","description":"Human-readable description of the error."},"field":{"type":"string","description":"Optional pointer to the document field that caused the error.\nUsed by structural validation errors (`missing_required_field`,\n`invalid_ref`) to indicate which field is at fault\n(e.g. `_id`, `type`, `http.baseURI`)."},"source":{"type":"string","description":"Optional origin layer for the error — e.g. `application` when\nthe error came from the remote system the adaptor called,\n`connector` when the adaptor itself rejected the request."}},"required":["message"]}}},"required":["errors"]}},"responses":{"400-bad-request":{"description":"Bad request. The server could not understand the request because of malformed syntax or invalid parameters.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401-unauthorized":{"description":"Unauthorized. The request lacks a valid bearer token, or the provided token\nfailed to authenticate.\n\nNote: the 401 response is produced by the auth middleware **before** the\nrequest reaches the endpoint handler, so it does **not** follow the\nstandard `{errors: [...]}` envelope. Instead the body is a bare\n`{message: string}` object with no `code`, no `errors` array. Callers\nhandling 401s should key off the HTTP status and the `message` string,\nnot try to destructure an `errors[]`.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Human-readable description of the auth failure. Known values:\n- `\"Unauthorized\"` — no `Authorization` header on the request.\n- `\"Bearer Authentication Failed\"` — header present but token\n  is invalid, revoked, or expired."}},"required":["message"]}}}}}},"paths":{"/v1/notifications":{"put":{"operationId":"upsertNotifications","tags":["Notifications"],"summary":"Subscribe / unsubscribe users to resource notifications","description":"Upserts a batch of notification subscriptions. Each item targets exactly one\nresource (`_flowId`, `_connectionId`, or `_integrationId`) plus a\n`subscribedByUserEmail`. `subscribed: true` creates (or keeps) the\nsubscription; `subscribed: false` removes it.\n\nReturns a parallel array of per-item results — one entry per request item,\nin the same order. Each result carries `statusCode` (**201** when a subscription\nwas created, **200** when updated or removed, 422 when a referenced resource\ndoesn't exist) plus an `errors[]` array on failures. An empty request body\nreturns an empty array.\n\nThe body is a bare array (maximum 500 items). Each item must carry\nexactly one of `_flowId` / `_connectionId` / `_integrationId` /\n`_syncId`. The response is a per-item status array; referencing a\nnon-existent resource fails that item with `statusCode: 422` but\ndoes not fail the whole request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationsUpsertRequest"}}}},"responses":{"200":{"description":"Per-item result array (parallel to the request). Each entry is\n`{statusCode, errors?}` — `statusCode` 201 for a created subscription\nand 200 for one that already existed or was removed, or a 4xx status\nwith an `errors[]` array on per-item failures. Overall HTTP is\nstill 200 even when individual items fail.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","description":"Per-item upsert result.","properties":{"statusCode":{"type":"integer","description":"Per-item outcome: 201 when the subscription was created;\n200 when it already existed (subscribing again keeps the one\nrecord) or was removed; 422 when the referenced resource\ndoesn't exist (details in `errors[]`)."},"errors":{"type":"array","description":"Per-item error details — present on 4xx per-item failures, never on a 201 or 200.","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"},"403":{"description":"A `subscribedByUserEmail` value matches no user in the account, so the whole\nrequest is rejected with `invalid_access`, including items that name valid\nusers. The message mentions monitor access even when the caller has full access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}
```
