Notifications
Telegram and in-app notifications, and which events go where.
List notifications #
/v1/notifications app sessionThe app inbox: every notification of the last 30 days, newest first, whatever other channels it also went to.
More about this
Failures say what happened (what_happened), what was done (what_we_did) and what to do (what_you_should_do). Live ones arrive on /v1/stream with the notifications topic. Page with limit and before.
Parameters
- limit query · integer
Page size, 1-100 (default 50).
- before query · string
next_cursorof the previous page.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | invalid_query | The query string does not fit the route's parameters. |
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 422 | invalid_request | The request is well-formed but not valid; |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl "https://cirrus.pocketful.in/v1/notifications" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.get(
"https://cirrus.pocketful.in/v1/notifications",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications', {
method: 'GET',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"notifications": [
{
"id": "ntf_18378111f24fba4c62605dd2",
"event": "trigger_fired",
"severity": "info",
"title": "Stop-loss hit on RELIANCE-EQ",
"what_happened": "RELIANCE-EQ traded at ₹2,474.50.",
"what_we_did": "We're placing the exit order.",
"what_you_should_do": null,
"account": "P1",
"strategy": "nifty-momentum",
"trigger_id": "01JA0000000000000000000001",
"origin": {
"kind": "trigger_update",
"id": "01JA0000000000000000000001:3"
},
"at": "2026-10-16T10:45:30+05:30"
}
],
"next_cursor": null
},
"error": null
}List notification event types #
/v1/notifications/events app sessionEvery event type a user can route, in display order, with its group, default and whether the app always shows it (mandatory).
More about this
Types with available: false can be routed but are not sent yet.
Errors
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl "https://cirrus.pocketful.in/v1/notifications/events" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.get(
"https://cirrus.pocketful.in/v1/notifications/events",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/events', {
method: 'GET',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": [
{
"event": "trigger_fired",
"label": "Trigger fired",
"description": "A stop-loss, target, alert or ladder rung was hit.",
"group": "triggers",
"default_on": true,
"mandatory": false,
"account_level": false,
"available": true
},
{
"event": "trigger_refused",
"label": "Trigger refused or errored",
"description": "A change to a trigger was refused, or the trigger stopped with an error.",
"group": "errors",
"default_on": true,
"mandatory": true,
"account_level": false,
"available": true
}
],
"error": null
}Get notification channels #
/v1/notifications/channels app sessionEach channel's state for the user: Telegram (not_linked, linked or broken with broken_reason, e.g.
More about this
the user blocked the bot), the app, and the user's webhooks. telegram.available: false means the server has no Telegram bot: show telegram.unavailable_reason instead of a connect button (nothing is sent to Telegram; the app and webhooks still work). prompts lists what the app should show, most urgent first: connect_telegram (offer to connect; never while Telegram is unavailable), telegram_broken (updates are not reaching Telegram and go to the app instead), webhook_failing.
Errors
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl "https://cirrus.pocketful.in/v1/notifications/channels" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.get(
"https://cirrus.pocketful.in/v1/notifications/channels",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/channels', {
method: 'GET',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"telegram": {
"available": true,
"unavailable_reason": null,
"state": "linked",
"linked": true,
"healthy": true,
"broken_reason": null,
"broken_at": null,
"linked_at": "2026-10-18T13:27:56.350+05:30",
"last_delivered_at": null,
"telegram_username": "asha_trades",
"bot_username": "desk_bot"
},
"app_push": {
"healthy": true,
"stream_topic": "notifications"
},
"webhook": {
"enabled": false,
"receivers": []
},
"prompts": []
},
"error": null
}Get notification preferences #
/v1/notifications/preferences app sessionPer channel (telegram, app_push, webhook): on or off, every event type on or off (defaults filled in), and the scope (all, or selected strategies and triggers; account events such as an expired login always come through).
More about this
A notice goes to every channel that wants it. Mandatory events always reach the app; while Telegram is broken its notices go to the app instead.
Errors
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl "https://cirrus.pocketful.in/v1/notifications/preferences" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.get(
"https://cirrus.pocketful.in/v1/notifications/preferences",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/preferences', {
method: 'GET',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"telegram": {
"enabled": true,
"events": {
"account_setup": true,
"channel_broken": true,
"daily_summary": true,
"entry_failed": true,
"exit_filled": true,
"exit_placed": true,
"exit_refused": true,
"live_updates": true,
"order_filled": false,
"order_rejected": true,
"order_unconfirmed": true,
"protection_failed": true,
"risk_breached": true,
"session_expired": true,
"strategy_armed": false,
"strategy_entered": true,
"strategy_error": true,
"strategy_exited": true,
"strategy_kill_switch": true,
"strategy_refused": true,
"strategy_safety_pause": true,
"trigger_ended": false,
"trigger_fired": true,
"trigger_refused": true,
"webhook_disabled": true
},
"scope": {
"mode": "all",
"strategies": [],
"triggers": []
}
},
"app_push": {
"enabled": true,
"events": {
"account_setup": true,
"channel_broken": true,
"daily_summary": true,
"entry_failed": true,
"exit_filled": true,
"exit_placed": true,
"exit_refused": true,
"live_updates": true,
"order_filled": false,
"order_rejected": true,
"order_unconfirmed": true,
"protection_failed": true,
"risk_breached": true,
"session_expired": true,
"strategy_armed": false,
"strategy_entered": true,
"strategy_error": true,
"strategy_exited": true,
"strategy_kill_switch": true,
"strategy_refused": true,
"strategy_safety_pause": true,
"trigger_ended": false,
"trigger_fired": true,
"trigger_refused": true,
"webhook_disabled": true
},
"scope": {
"mode": "all",
"strategies": [],
"triggers": []
}
},
"webhook": {
"enabled": false,
"events": {
"account_setup": true,
"channel_broken": true,
"daily_summary": true,
"entry_failed": true,
"exit_filled": true,
"exit_placed": true,
"exit_refused": true,
"live_updates": true,
"order_filled": false,
"order_rejected": true,
"order_unconfirmed": true,
"protection_failed": true,
"risk_breached": true,
"session_expired": true,
"strategy_armed": false,
"strategy_entered": true,
"strategy_error": true,
"strategy_exited": true,
"strategy_kill_switch": true,
"strategy_refused": true,
"strategy_safety_pause": true,
"trigger_ended": false,
"trigger_fired": true,
"trigger_refused": true,
"webhook_disabled": true
},
"scope": {
"mode": "all",
"strategies": [],
"triggers": []
}
}
},
"error": null
}Replace notification preferences #
/v1/notifications/preferences app sessionReplaces the preferences.
More about this
A channel left out goes back to its defaults; an event left out of events follows its default. webhook.webhook_ids picks which of the user's webhooks get the notification event (null: every enabled one).
Body fields
- telegram object | null
One channel's preference as stored and as sent. Unknown fields and event names are kept out of the way (a newer pod may have written them), never refused.
- app_push object | null
One channel's preference as stored and as sent. Unknown fields and event names are kept out of the way (a newer pod may have written them), never refused.
- webhook object | null
One channel's preference as stored and as sent. Unknown fields and event names are kept out of the way (a newer pod may have written them), never refused.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | malformed_json | The body is not JSON, or does not fit the request shape (unknown or missing fields, wrong types). |
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 422 | invalid_request | The request is well-formed but not valid; |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl -X PUT "https://cirrus.pocketful.in/v1/notifications/preferences" \
-H "Authorization: token $CIRRUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"telegram": {
"enabled": true,
"events": {
"order_filled": true,
"trigger_ended": false
},
"scope": {
"mode": "selected",
"strategies": [
"nifty-momentum"
],
"triggers": []
}
},
"app_push": {
"enabled": true,
"events": {},
"scope": {
"mode": "all"
}
},
"webhook": {
"enabled": false
}
}'import os
import requests
response = requests.put(
"https://cirrus.pocketful.in/v1/notifications/preferences",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
json={
"telegram": {
"enabled": True,
"events": {
"order_filled": True,
"trigger_ended": False,
},
"scope": {
"mode": "selected",
"strategies": [
"nifty-momentum",
],
"triggers": [],
},
},
"app_push": {
"enabled": True,
"events": {},
"scope": {
"mode": "all",
},
},
"webhook": {
"enabled": False,
},
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/preferences', {
method: 'PUT',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"telegram": {
"enabled": true,
"events": {
"order_filled": true,
"trigger_ended": false
},
"scope": {
"mode": "selected",
"strategies": [
"nifty-momentum"
],
"triggers": []
}
},
"app_push": {
"enabled": true,
"events": {},
"scope": {
"mode": "all"
}
},
"webhook": {
"enabled": false
}
}),
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"telegram": {
"enabled": true,
"events": {
"account_setup": true,
"channel_broken": true,
"daily_summary": true,
"entry_failed": true,
"exit_filled": true,
"exit_placed": true,
"exit_refused": true,
"live_updates": true,
"order_filled": true,
"order_rejected": true,
"order_unconfirmed": true,
"protection_failed": true,
"risk_breached": true,
"session_expired": true,
"strategy_armed": false,
"strategy_entered": true,
"strategy_error": true,
"strategy_exited": true,
"strategy_kill_switch": true,
"strategy_refused": true,
"strategy_safety_pause": true,
"trigger_ended": false,
"trigger_fired": true,
"trigger_refused": true,
"webhook_disabled": true
},
"scope": {
"mode": "selected",
"strategies": [
"nifty-momentum"
],
"triggers": []
}
},
"app_push": {
"enabled": true,
"events": {
"account_setup": true,
"channel_broken": true,
"daily_summary": true,
"entry_failed": true,
"exit_filled": true,
"exit_placed": true,
"exit_refused": true,
"live_updates": true,
"order_filled": false,
"order_rejected": true,
"order_unconfirmed": true,
"protection_failed": true,
"risk_breached": true,
"session_expired": true,
"strategy_armed": false,
"strategy_entered": true,
"strategy_error": true,
"strategy_exited": true,
"strategy_kill_switch": true,
"strategy_refused": true,
"strategy_safety_pause": true,
"trigger_ended": false,
"trigger_fired": true,
"trigger_refused": true,
"webhook_disabled": true
},
"scope": {
"mode": "all",
"strategies": [],
"triggers": []
}
},
"webhook": {
"enabled": false,
"events": {
"account_setup": true,
"channel_broken": true,
"daily_summary": true,
"entry_failed": true,
"exit_filled": true,
"exit_placed": true,
"exit_refused": true,
"live_updates": true,
"order_filled": false,
"order_rejected": true,
"order_unconfirmed": true,
"protection_failed": true,
"risk_breached": true,
"session_expired": true,
"strategy_armed": false,
"strategy_entered": true,
"strategy_error": true,
"strategy_exited": true,
"strategy_kill_switch": true,
"strategy_refused": true,
"strategy_safety_pause": true,
"trigger_ended": false,
"trigger_fired": true,
"trigger_refused": true,
"webhook_disabled": true
},
"scope": {
"mode": "all",
"strategies": [],
"triggers": []
}
}
},
"error": null
}Start linking Telegram #
/v1/notifications/telegram/link app sessionA one-time deep link to the bot (https://t.me/<bot>?start=<token>), valid for a few minutes.
More about this
Opening it and tapping Start links that Telegram chat to the user and confirms in the chat; a new link replaces nothing until used. Poll GET /v1/notifications/channels to see it linked. Only the account holder, signed in themselves, can link.
Errors
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | own_session_required | Credentials can only be created from the user's own signed-in session. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl -X POST "https://cirrus.pocketful.in/v1/notifications/telegram/link" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.post(
"https://cirrus.pocketful.in/v1/notifications/telegram/link",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/telegram/link', {
method: 'POST',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"url": "https://t.me/desk_bot?start=tl_V8hLhHejvIyDpAQwWDcQNnGeI8IdEVIZ",
"bot_username": "desk_bot",
"expires_at": "2026-10-18T13:37:56.348541+05:30",
"expires_in_seconds": 600
},
"error": null
}Unlink Telegram #
/v1/notifications/telegram/link app sessionStops all Telegram messages to the user (sending /stop to the bot does the same).
More about this
Their notices keep reaching the app.
Errors
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 404 | telegram_not_linked | Telegram is not connected for the caller; start a link first. |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl -X DELETE "https://cirrus.pocketful.in/v1/notifications/telegram/link" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.delete(
"https://cirrus.pocketful.in/v1/notifications/telegram/link",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/telegram/link', {
method: 'DELETE',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"unlinked": true
},
"error": null
}Send a Telegram test message #
/v1/notifications/telegram/test app sessionSends a test message to the linked chat now and says whether Telegram took it.
More about this
When Telegram refuses it for good (the bot is blocked), the link is marked broken, broken_reason says why and message what to do.
Errors
| HTTP | Code | When |
|---|---|---|
| 401 | unauthorized | No credential, or the credential is invalid, expired or revoked. |
| 403 | forbidden | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |
| 404 | telegram_not_linked | Telegram is not connected for the caller; start a link first. |
| 429 | rate_limited | Too many requests for this credential (or too many failed attempts); retry after the |
| 503 | notifications_disabled | Notifications are not enabled on this server. |
| 503 | service_unavailable | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |
All fields (request and response schema)
Loading fields…
curl -X POST "https://cirrus.pocketful.in/v1/notifications/telegram/test" \
-H "Authorization: token $CIRRUS_API_KEY"import os
import requests
response = requests.post(
"https://cirrus.pocketful.in/v1/notifications/telegram/test",
headers={
"Authorization": f"token {os.environ['CIRRUS_API_KEY']}",
},
timeout=10,
)
print(response.status_code, response.json())const response = await fetch('https://cirrus.pocketful.in/v1/notifications/telegram/test', {
method: 'POST',
headers: {
Authorization: `token ${process.env.CIRRUS_API_KEY}`,
},
});
const body = await response.json();
console.log(response.status, body);{
"status": "success",
"data": {
"delivered": true,
"message": "Sent. Check your Telegram chat with the bot.",
"broken_reason": null
},
"error": null
}