Skip to content
Cirrus home
Sign in

Reference

Notifications

Telegram and in-app notifications, and which events go where.

Read the guide first

List notifications #

GET /v1/notifications app session

The 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_cursor of the previous page.

Errors

HTTPCodeWhen
400invalid_query

The query string does not fit the route's parameters.

401unauthorized

No credential, or the credential is invalid, expired or revoked.

403forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

422invalid_request

The request is well-formed but not valid; field names the input.

429rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503notifications_disabled

Notifications are not enabled on this server.

503service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://cirrus.pocketful.in/v1/notifications" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "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 #

GET /v1/notifications/events app session

Every 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

HTTPCodeWhen
401unauthorized

No credential, or the credential is invalid, expired or revoked.

403forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

429rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503notifications_disabled

Notifications are not enabled on this server.

503service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://cirrus.pocketful.in/v1/notifications/events" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200 · lists shortened
{
  "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 #

GET /v1/notifications/channels app session

Each 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

HTTPCodeWhen
401unauthorized

No credential, or the credential is invalid, expired or revoked.

403forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

429rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503notifications_disabled

Notifications are not enabled on this server.

503service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://cirrus.pocketful.in/v1/notifications/channels" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "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 #

GET /v1/notifications/preferences app session

Per 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

HTTPCodeWhen
401unauthorized

No credential, or the credential is invalid, expired or revoked.

403forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

429rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503notifications_disabled

Notifications are not enabled on this server.

503service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

GET
curl "https://cirrus.pocketful.in/v1/notifications/preferences" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "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 #

PUT /v1/notifications/preferences app session

Replaces 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

HTTPCodeWhen
400malformed_json

The body is not JSON, or does not fit the request shape (unknown or missing fields, wrong types).

401unauthorized

No credential, or the credential is invalid, expired or revoked.

403forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

422invalid_request

The request is well-formed but not valid; field names the input.

429rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503notifications_disabled

Notifications are not enabled on this server.

503service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

PUT
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
    }
  }'
Response · 200
{
  "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
}

Send a Telegram test message #

POST /v1/notifications/telegram/test app session

Sends 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

HTTPCodeWhen
401unauthorized

No credential, or the credential is invalid, expired or revoked.

403forbidden

The credential may not use this route (missing scope, app-session-only route, IP not allowed).

404telegram_not_linked

Telegram is not connected for the caller; start a link first.

429rate_limited

Too many requests for this credential (or too many failed attempts); retry after the Retry-After header (seconds; error.retry_after_ms has the exact wait).

503notifications_disabled

Notifications are not enabled on this server.

503service_unavailable

A dependency is temporarily unavailable, or the feature is off on this server; retry later.

All fields (request and response schema)

Loading fields…

POST
curl -X POST "https://cirrus.pocketful.in/v1/notifications/telegram/test" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "delivered": true,
    "message": "Sent. Check your Telegram chat with the bot.",
    "broken_reason": null
  },
  "error": null
}