# List Notifications

> Lists the signed-in person's in-app notifications, newest first, across the workspaces this connection can reach.

- **URL**: https://orshot.com/docs/api-reference/approvals-notifications-list

---

The Approvals API is available on Enterprise plans, or through first-party apps (the Orshot app and the Orshot MCP server). This endpoint needs [`read` access](/docs/api-reference/approvals-overview#access-levels) and acts for one person: send their OAuth token, or an API key with their user id in `X-Orshot-User-Id`.
See [Enterprise pricing](https://orshot.com/pricing) to get access.

Lists the signed-in person's in-app notifications, newest first, across the workspaces this connection can reach. A notification disappears when the person leaves its workspace or, as a reviewer limited to some flows, loses access to its flow or template, and comes back if access returns. unreadCount counts the same ones.

Results come in pages: pass `nextCursor` back as `cursor` until it is `null`.

## Endpoint

```markdown tab="Endpoint"
https://api.orshot.com/v1/notifications
```

## Query Parameters

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `unread` | Boolean | No | Only unread. Default `false`. |
| `cursor` | String | No | Cursor from the previous page's nextCursor. A cursor the API didn't write starts again from the first page. Up to 200 characters. |
| `limit` | Integer | No | Results per page (1 to 100). Default `50`. |

## Headers

| Header | Required | Description |
| ------ | -------- | ----------- |
| `Authorization` | Yes | `Bearer <API key or OAuth token>` |
| `X-Orshot-User-Id` | With an API key | The user id of the owner, admin or member this call is for. OAuth tokens don't send it. See Acting for a Team Member below. |
| `X-Session-Id` | No | Groups the calls of one agent or MCP session in the activity history. |

## Acting for a Team Member

This acts for one person. With an API key, send `X-Orshot-User-Id` with the user id of an owner, admin or member of the workspace: the answer is theirs, as their own OAuth token would get it, within the key's workspace. Without the header, API keys get `403 permission_denied`, code `approval.person_required`. See [acting for a team member](https://orshot.com/docs/api-reference/approvals-overview#acting-for-a-team-member).

## Request

**Request**
```js
await fetch("https://api.orshot.com/v1/notifications?limit=2", {
  headers: { Authorization: "Bearer <ORSHOT_OAUTH_TOKEN>" },
});
```

**Response**
```json
{
  "notifications": [
    {
      "id": 29,
      "event": {
        "id": 34,
        "kind": "comment.created",
        "label": "Jordan Lee commented on 'Spring sale banner'",
        "actor": {
          "id": "b5d2e8f1-7a3c-4b69-9e0d-3c8a1f6b2e45",
          "name": "Jordan Lee",
          "email": "jordan@acme.com",
          "role": "member"
        },
        "via": "api",
        "source": "api",
        "client": null,
        "subject": {
          "type": "template",
          "id": 101
        },
        "flowId": null,
        "itemId": null,
        "payload": {
          "template": {
            "id": 101,
            "name": "Spring sale banner"
          },
          "commentId": 4,
          "parentId": null,
          "excerpt": "@Priya Shah can you check the claim in the headline?",
          "mentioned": [
            "9a4c7e2b-1d6f-4e3a-8b5c-2f7d0e9a4c61"
          ]
        },
        "createdAt": "2026-09-28T09:30:00.000Z"
      },
      "readAt": null,
      "archivedAt": null,
      "createdAt": "2026-09-28T09:30:00.000Z"
    },
    {
      "id": 21,
      "event": {
        "id": 27,
        "kind": "approval.item.moved",
        "label": "Jordan Lee moved 'Instagram story' from 'Draft' to 'Brand review'",
        "actor": {
          "id": "b5d2e8f1-7a3c-4b69-9e0d-3c8a1f6b2e45",
          "name": "Jordan Lee",
          "email": "jordan@acme.com",
          "role": "member"
        },
        "via": "api",
        "source": "api",
        "client": null,
        "subject": {
          "type": "template",
          "id": 103
        },
        "flowId": 1,
        "itemId": 3,
        "payload": {
          "template": {
            "id": 103,
            "name": "Instagram story"
          },
          "flow": {
            "id": 1,
            "slug": "brand-and-legal",
            "name": "Brand and legal"
          },
          "from": {
            "id": 1,
            "slug": "draft",
            "name": "Draft",
            "category": "open"
          },
          "to": {
            "id": 2,
            "slug": "brand-review",
            "name": "Brand review",
            "category": "review"
          },
          "reason": "moved",
          "revision": 2,
          "round": 1,
          "commentId": null,
          "bulkId": 26
        },
        "createdAt": "2026-09-28T09:30:00.000Z"
      },
      "readAt": null,
      "archivedAt": null,
      "createdAt": "2026-09-28T09:30:00.000Z"
    }
  ],
  "unreadCount": 6,
  "nextCursor": "eyJpZCI6MjF9"
}
```

## Response Fields

Responds `200` with:

| Field | Type | Description |
| ----- | ---- | ----------- |
| `notifications` | Array | List of Notification, fields below. |
| `notifications[].id` | Integer | Numeric id. |
| `notifications[].event` | Object | One ActivityEvent. |
| `notifications[].readAt` | String | ISO 8601 timestamp. Can be `null`. |
| `notifications[].archivedAt` | String | ISO 8601 timestamp. Can be `null`. |
| `notifications[].createdAt` | String | ISO 8601 timestamp. |
| `unreadCount` | Integer | Unread notifications in total. |
| `nextCursor` | String | Can be `null`. Pass it back as `cursor` for the next page; `null` on the last page. |

## Error Responses

Every error has the same body: `error`, `code`, `message` and `helpUrl`, plus the fields that apply (`required`, `role`, `context`, `blockers`, `violations`, `issues`, `current`). Branch on `error`; `code` is more specific. See the [error reference](https://orshot.com/docs/error-reference).

| Status Code | Error | Description |
| ----------- | ----- | ----------- |
| 401 | `oauth_token_invalid` | The OAuth token is invalid, expired or revoked. |
| 403 | `api_key_missing` | No `Authorization: Bearer` header. |
| 403 | `permission_denied` | You don't have access to do this. Ask an owner or admin. `code` names the capability, for example `approval.item.decide_denied`; `required` and `role` say what was missing. With `code: insufficient_scope`: the OAuth token lacks `workspace:approvals:read`. API keys without `X-Orshot-User-Id` get `approval.person_required`: this acts for one person. With `code: approval.member_header_not_member`: `X-Orshot-User-Id` names someone who isn't an owner, admin or member of the workspace now. With `code: approval.member_header_not_allowed`: an OAuth token sent `X-Orshot-User-Id`. |
| 403 | `plan_required` | The workspace's plan doesn't include Approvals, or doesn't include this part of it. |
| 403 | `enterprise_api_required` | Approvals through third-party apps need an Enterprise plan. Contact hi@orshot.com to turn it on. |
| 404 | `not_found` | This doesn't exist or isn't available to you. Reviewers get this, never 403, for flows and templates outside their access. |
| 422 | `validation_failed` | Some fields aren't valid: the fields listed in issues. `issues` lists each field with a path and a reason. |
| 422 | `validation_failed` | With `code: approval.member_header_invalid`: `X-Orshot-User-Id` isn't a user id. |
| 429 | `rate_limit_exceeded` | More than 120 approvals requests in a minute from one person or key. Wait for Retry-After. |
| 503 | `approvals_unavailable` | Approvals aren't available right now. Try again in a moment. Also returned while approvals are not switched on for the API. |