List Notifications
Lists the signed-in person's in-app notifications, newest first, across the workspaces this connection can reach.
Updated
/v1/notificationscurl -X GET "https://api.orshot.com/v1/notifications?unread=<UNREAD>&cursor=<CURSOR>&limit=10" \
-H "Authorization: Bearer <ORSHOT_API_KEY>"const res = await fetch("https://api.orshot.com/v1/notifications?unread=<UNREAD>&cursor=<CURSOR>&limit=10", {
method: "GET",
headers: {
Authorization: "Bearer <ORSHOT_API_KEY>",
},
});
const data = await res.json();import requests
response = requests.get(
"https://api.orshot.com/v1/notifications?unread=<UNREAD>&cursor=<CURSOR>&limit=10",
headers={"Authorization": "Bearer <ORSHOT_API_KEY>"},
)
data = response.json()$ch = curl_init("https://api.orshot.com/v1/notifications?unread=<UNREAD>&cursor=<CURSOR>&limit=10");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <ORSHOT_API_KEY>",
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);require "net/http"
require "json"
uri = URI("https://api.orshot.com/v1/notifications?unread=<UNREAD>&cursor=<CURSOR>&limit=10")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer <ORSHOT_API_KEY>"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)Enterprise Only
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 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 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#
https://api.orshot.com/v1/notificationsQuery 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.
Request#
await fetch("https://api.orshot.com/v1/notifications?limit=2", {
headers: { Authorization: "Bearer <ORSHOT_OAUTH_TOKEN>" },
});{
"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.
| 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. |
Ready to automate?
Start rendering images, PDFs and videos from your templates in under 2 minutes. Free plan, no credit card.
Get your API key- Image, PDF and video generation via API
- Visual editor with AI and smart layouts
- Zapier, Make, MCP and 50+ integrations
- White-label embed for your own app
- 100 free credits a month, no credit card required