# Notifications

## List notification subscriptions

> Returns notification subscriptions for flows, connections, and integrations\
> 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 \*\*204\*\* when the response would be empty (e.g. the caller has no\
> subscriptions on the default scope). The \`users=all\` scope returns 200 with\
> \`\[]\` only in accounts with zero subscriptions across all users — typically\
> the 204 path is the "caller has none" case.\
> \
> AI guidance:\
> \- Always pass \`?users=all\` for admin-style audits — the default scope\
> &#x20; omits subscriptions owned by other users.\
> \- Each item carries exactly one of \`\_flowId\` / \`\_connectionId\` /\
> &#x20; \`\_integrationId\` depending on \`type\`.

```json
{"openapi":"3.1.0","info":{"title":"Notifications","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"parameters":{"Include":{"name":"include","in":"query","required":false,"description":"Comma-separated list of fields to project into each returned record.\nTriggers **summary projection** on supported list endpoints: the server\nreturns a minimal identity set for each record (`_id`, `name`, plus a\nresource-specific always-on set like `adaptorType` on exports/imports,\nor richer defaults on `ashares`, `audit`, `httpconnectors`, `transfers`,\netc.) and adds any listed fields that exist on the record. Listed fields\nthe record doesn't carry are silently dropped.\n\nDot notation is supported for projecting nested sub-fields — e.g.\n`include=ftp.directoryPath` on `/v1/exports` returns just that nested\nfield inside `ftp` for FTP-type exports (and omits `ftp` entirely for\nnon-FTP exports).\n\nRules:\n- Value regex is `{a-z A-Z . _}` (letters, dots, underscores) plus the\n  comma separator; digits are also accepted in practice. Any other\n  character returns **400 `invalid_query_params`**.\n- Empty value (`include=`) or bare `include` is ignored — the full\n  default record is returned.\n- `include` and `exclude` are **mutually exclusive**. Passing both\n  returns **400 `invalid_query_params`**: *\"Please provide either\n  include or exclude param in the request query and not both.\"*\n- Array-bracket syntax (`include[]=...`) is not supported and can return\n  a 500.\n- Only list endpoints honor projection — on GET-by-id the parameter is\n  silently ignored.\n- A small set of list endpoints explicitly reject both `include` and\n  `exclude` with **400 `invalid_query_params`** and a message of the form\n  *\"Include or exclude query params are not applicable for `<resource>`\n  resource.\"* Known rejections: `/v1/ediprofiles`, `/v1/environments`,\n  `/v1/iClients`, `/v1/lookupcaches`, `/v1/tags`.","schema":{"type":"string"}},"Exclude":{"name":"exclude","in":"query","required":false,"description":"Comma-separated list of fields to remove from the default response on\nsupported list endpoints. Unlike `include`, `exclude` does NOT trigger\nsummary projection — callers get the standard full-record shape with the\nnamed fields stripped out.\n\nRules:\n- Value regex is `{a-z A-Z . _}` (letters, dots, underscores) plus the\n  comma separator; digits are also accepted in practice. Any other\n  character returns **400 `invalid_query_params`**.\n- Empty value (`exclude=`) is ignored.\n- Certain protected identity fields **cannot be stripped** — e.g.\n  `exclude=name` on `/v1/exports` is silently ignored and `name` remains\n  in the response. Protected sets vary per resource.\n- `include` and `exclude` are **mutually exclusive**. Passing both\n  returns **400 `invalid_query_params`**: *\"Please provide either\n  include or exclude param in the request query and not both.\"*\n- Only list endpoints honor stripping — on GET-by-id the parameter is\n  silently ignored.\n- A small set of list endpoints explicitly reject both `include` and\n  `exclude` with **400 `invalid_query_params`** and a message of the form\n  *\"Include or exclude query params are not applicable for `<resource>`\n  resource.\"* Known rejections: `/v1/ediprofiles`, `/v1/environments`,\n  `/v1/iClients`, `/v1/lookupcaches`, `/v1/tags`.","schema":{"type":"string"}}},"schemas":{"Notification":{"type":"object","description":"A notification subscription linking a user email to a single resource\n(flow, connection, or integration). When the resource emits an alert\n(error, state change, etc.), the subscribed user is notified.","properties":{"_id":{"type":"string","format":"objectId","description":"Unique subscription id."},"type":{"type":"string","enum":["flow","connection","integration"],"description":"Which resource class this subscription targets. Implies which of\n`_flowId` / `_connectionId` / `_integrationId` 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`."},"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."}}},"lastModified":{"type":"string","format":"date-time","readOnly":true,"description":"When this subscription was last created or modified."}},"required":["_id","type","subscribedByUser"]}},"responses":{"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, and integrations\nin 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 **204** when the response would be empty (e.g. the caller has no\nsubscriptions on the default scope). The `users=all` scope returns 200 with\n`[]` only in accounts with zero subscriptions across all users — typically\nthe 204 path is the \"caller has none\" case.\n\nAI guidance:\n- Always pass `?users=all` for admin-style audits — the default scope\n  omits subscriptions owned by other users.\n- Each item carries exactly one of `_flowId` / `_connectionId` /\n  `_integrationId` depending on `type`.","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."},{"$ref":"#/components/parameters/Include"},{"$ref":"#/components/parameters/Exclude"}],"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 `[]`."},"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\` (200 on success,\
> 422 when a referenced resource doesn't exist) plus an \`errors\[]\` array on\
> failures. An empty request body returns an empty array.\
> \
> AI guidance:\
> \- The body is a \*\*bare array\*\*, not an envelope. The Celigo CLI batches at\
> &#x20; \~50 items per call to avoid request-size limits on large bulk operations.\
> \- Each item must carry exactly one of \`\_flowId\` / \`\_connectionId\` /\
> &#x20; \`\_integrationId\`. Passing more than one silently prefers the first\
> &#x20; populated field in the order the server inspects it.\
> \- The response is a per-item status array, NOT the upserted Notification\
> &#x20; objects. To read the post-upsert state, call \`GET /v1/notifications\`\
> &#x20; afterward.\
> \- Referencing a non-existent resource id fails per-item with \`statusCode:\
> &#x20; 422\` + \`errors: \[{field, code:"invalid\_ref", message}]\` but does NOT fail\
> &#x20; the whole request — other items in the batch still succeed.

```json
{"openapi":"3.1.0","info":{"title":"Notifications","version":"1.0.0"},"servers":[{"url":"https://api.integrator.io","description":"Production (US / default region)"},{"url":"https://api.eu.integrator.io","description":"Production (EU region)"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"NotificationsUpsertRequest":{"type":"array","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.","properties":{"_flowId":{"type":"string","format":"objectId","description":"Flow id to subscribe / unsubscribe. Set exactly one of `_flowId` / `_connectionId` / `_integrationId`."},"_connectionId":{"type":"string","format":"objectId","description":"Connection id to subscribe / unsubscribe."},"_integrationId":{"type":"string","format":"objectId","description":"Integration 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 — unknown emails are silently ignored (no-op)."}},"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` (200 on success,\n422 when a referenced resource doesn't exist) plus an `errors[]` array on\nfailures. An empty request body returns an empty array.\n\nAI guidance:\n- The body is a **bare array**, not an envelope. The Celigo CLI batches at\n  ~50 items per call to avoid request-size limits on large bulk operations.\n- Each item must carry exactly one of `_flowId` / `_connectionId` /\n  `_integrationId`. Passing more than one silently prefers the first\n  populated field in the order the server inspects it.\n- The response is a per-item status array, NOT the upserted Notification\n  objects. To read the post-upsert state, call `GET /v1/notifications`\n  afterward.\n- Referencing a non-existent resource id fails per-item with `statusCode:\n  422` + `errors: [{field, code:\"invalid_ref\", message}]` but does NOT fail\n  the whole request — other items in the batch still succeed.","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: 200` on success, or a non-200\nstatus with 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: 200 when the subscription was created,\nupdated, or left unchanged; 422 when the referenced\nresource doesn't exist (details in `errors[]`)."},"errors":{"type":"array","description":"Per-item error details — present on non-200 results.","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}},"required":["statusCode"]}}}}},"400":{"$ref":"#/components/responses/400-bad-request"},"401":{"$ref":"#/components/responses/401-unauthorized"}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.celigo.com/api/api-reference/notifications.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
