Skip to content
Cirrus home
Sign in

Guide

Getting started

Create an API key, pick its scopes and make your first Cirrus API request in a few minutes.

The Cirrus API lets your code do what you do in the app: place orders with your broker, protect positions, run strategies and get told when something happens. It is plain HTTPS and JSON.

WhatURL
REST APIhttps://cirrus.pocketful.in
Live stream (WebSocket)wss://cirrus.pocketful.in/v1/stream

1. Create an API key #

  1. Sign in and open API access.
  2. Choose Create key, give it a name and tick only the scopes you need.
  3. Optionally limit it to your server’s IP addresses.
  4. Copy the key and secret now: the secret is shown only once.

2. Pick scopes #

ScopeLets the key
readRead accounts, orders, positions, holdings, funds, triggers and the live stream.
ordersPlace, modify and cancel orders, bracket orders and GTTs; convert positions.
triggersCreate, change and cancel alerts, stop-losses, targets and loss limits.
strategies, strategies_live, strategies_signalAutomated strategies: build and backtest, run live, send signals. API keys cannot carry these yet; use the app for now.

Scopes do not include each other: a key with orders but not read cannot read the order book. A missing scope answers 403 forbidden naming the scope.

3. Make your first request #

Put the key in an environment variable, then send it as Authorization: token <key>:<secret> on every request. This asks who the key belongs to:

export CIRRUS_API_KEY='ck_xxxxxxxx:cs_xxxxxxxx'
GET
curl "https://cirrus.pocketful.in/v1/user/profile" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "username": "user-01M3PGPS465224YW0C5Z5DBNFB",
    "auth": {
      "kind": "api_key",
      "key_id": "ck_sVOtcTpQ3Y5d6VIRAE9Q",
      "name": "Reporting",
      "scopes": [
        "read"
      ],
      "ip_allowlist": [
        "203.0.113.7"
      ]
    }
  },
  "error": null
}

Then list your linked broker accounts. You pass an account id like P1 when you place orders.

GET
curl "https://cirrus.pocketful.in/v1/accounts" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "items": [
      {
        "account": "5P1",
        "broker": "5paisa",
        "broker_name": "5paisa",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "login_required",
        "missing": [
          {
            "field": "static_ip",
            "label": "Static IP",
            "required": false
          }
        ],
        "updates": "stream",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": false,
          "cover": false,
          "gtt": false,
          "gtt_two_leg": false
        },
        "warnings": []
      },
      {
        "account": "MO1",
        "broker": "motilaloswal",
        "broker_name": "Motilal Oswal",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "login_required",
        "missing": [
          {
            "field": "static_ip",
            "label": "Static IP",
            "required": false
          }
        ],
        "updates": "stream",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": false,
          "cover": false,
          "gtt": false,
          "gtt_two_leg": false
        },
        "warnings": []
      },
      {
        "account": "P1",
        "broker": "paper",
        "broker_name": "Paper",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "ready",
        "missing": [],
        "updates": "postback",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": true,
          "cover": true,
          "gtt": true,
          "gtt_two_leg": true
        },
        "warnings": []
      },
      {
        "account": "P2",
        "broker": "paper",
        "broker_name": "Paper",
        "tag": null,
        "multiplier": 2,
        "supported": true,
        "status": "ready",
        "missing": [],
        "updates": "postback",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": true,
          "cover": true,
          "gtt": true,
          "gtt_two_leg": true
        },
        "warnings": []
      },
      {
        "account": "PF1",
        "broker": "pocketful",
        "broker_name": "Pocketful",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "login_required",
        "missing": [],
        "updates": "stream",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": true,
          "cover": true,
          "gtt": true,
          "gtt_two_leg": false
        },
        "warnings": []
      },
      {
        "account": "TJ1",
        "broker": "tradejini",
        "broker_name": "Tradejini",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "ready",
        "missing": [
          {
            "field": "static_ip",
            "label": "Static IP",
            "required": false
          }
        ],
        "updates": "stream",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": "2026-10-12T11:31:53Z",
        "seat_assigned": null,
        "last_update_at": "2026-10-12T10:31:53.299825Z",
        "protection": {
          "bracket": true,
          "cover": true,
          "gtt": true,
          "gtt_two_leg": true
        },
        "warnings": []
      },
      {
        "account": "U1",
        "broker": "upstox",
        "broker_name": "Upstox",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "login_required",
        "missing": [],
        "updates": "stream",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": false,
          "cover": false,
          "gtt": false,
          "gtt_two_leg": false
        },
        "warnings": []
      },
      {
        "account": "Z1",
        "broker": "zerodha",
        "broker_name": "Zerodha",
        "tag": null,
        "multiplier": 1,
        "supported": true,
        "status": "setup_incomplete",
        "missing": [
          {
            "field": "api_key",
            "label": "API Key",
            "required": true
          },
          {
            "field": "static_ip",
            "label": "Static IP",
            "required": false
          }
        ],
        "updates": "stream",
        "static_ip": null,
        "last_login_at": null,
        "session_expires_at": null,
        "seat_assigned": null,
        "last_update_at": null,
        "protection": {
          "bracket": false,
          "cover": false,
          "gtt": true,
          "gtt_two_leg": true
        },
        "warnings": []
      }
    ]
  },
  "error": null
}

Every response looks the same #

Success is {"status": "success", "data": …, "error": null}. An error keeps the shape and fills error: branch on error.code, show error.message to people. See Errors.

{
  "status": "error",
  "data": null,
  "error": {
    "code": "invalid_request",
    "message": "price must be > 0 for LIMIT orders",
    "field": "orders[0].price"
  }
}

Next #

In the reference