Skip to content
Cirrus home
Sign in

Reference

Orders

Place, modify and cancel orders in one or many accounts, and estimate margin first.

Read the guide first

Place orders #

POST /v1/orders scope orders

Places each order in every account it names (sized per account; split above the exchange freeze quantity).

More about this

Once placement starts the answer is 200 with one result per slice, even when some accounts refuse: check each status. Request-level problems (bad JSON, validation, unknown instrument or account list, missing Idempotency-Key) are 4xx and place nothing.

Repeat a request with the same Idempotency-Key to get the first answer back (Idempotent-Replayed: true) instead of placing again.

Parameters

  • Idempotency-Key header · string required

    A new UUID per order request (1-128 printable characters).

Body fields

  • orders object[] required
  • use_multiplier boolean

    Scale quantity by each account's Multiplier.

Errors

HTTPCodeWhen
400malformed_json

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

400idempotency_key_required

The Idempotency-Key header is missing (use a new UUID per order request).

400invalid_idempotency_key

The Idempotency-Key header is not 1-128 printable characters.

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).

409request_in_progress

A request with this Idempotency-Key is still being processed.

422invalid_request

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

422idempotency_key_reused

This Idempotency-Key was already used with a different request.

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).

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/orders" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "orders": [
      {
        "instrument_token": "CT:TEST:RELIANCE",
        "side": "BUY",
        "order_type": "LIMIT",
        "product": "DELIVERY",
        "quantity": 1,
        "price": 2500,
        "accounts": [
          "P1"
        ]
      }
    ]
  }'
Response · 200
{
  "status": "success",
  "data": {
    "results": [
      {
        "order_index": 0,
        "account": "P1",
        "quantity": 1,
        "status": "accepted",
        "order_id": "PAPER-1",
        "message": null,
        "order_type": "LIMIT",
        "price": 2500,
        "instrument_token": "CT:TEST:RELIANCE",
        "order_tag": "01M3PGPRZFZXEQM0KEC0DB653H"
      }
    ],
    "accepted": 1,
    "rejected": 0,
    "unknown": 0
  },
  "error": null
}

One order #

GET /v1/orders/{order_id} scope read

One order from today's order book, in the same shape as a GET /v1/portfolio/orders row (OrderData, with instrument details and live prices when known).

More about this

order_id is the broker's order id (as PATCH / DELETE on this path take it) or the order's order_tag (known before the broker acknowledges), or the client_tag it was placed with. Searches every linked account, or only account.

An id that names more than one order (a client_tag given to several orders or accounts, or the same broker order id in two accounts) is answered with 409 ambiguous_order listing the accounts; send account to pick one.

A cover / bracket entry placed through POST /v1/orders may be accepted with a null order_id (the broker's reply did not name the entry); look it up by its order_tag here once the order book has it.

Parameters

  • order_id path · string required

    Broker order id, order_tag or client_tag (1-64 letters, digits, -, _, . or :).

  • account query · string

    Only this account's book; every linked account when absent.

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).

404order_not_found

No order with this id (broker order id or order_tag) in the caller's order book today.

404account_not_found

No linked broker account with this id for the caller.

409ambiguous_order

The id names orders in more than one account (or several orders); message lists the accounts. Add account= to choose one.

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).

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/orders/<order_id>" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "broker_tag": null,
    "order_id": "250929000101",
    "parent_tag": null,
    "username": "user-01M3PGPRXSNM34C3C6AM1B721X",
    "account": "P1",
    "broker": "paper",
    "tradingsymbol": "RELIANCE-EQ",
    "side": "BUY",
    "order_type": "LIMIT",
    "product": "MIS",
    "quantity": 5,
    "price": 2500,
    "trigger_price": null,
    "state": "OPEN",
    "filled_qty": 0,
    "average_price": null,
    "status_message": null,
    "broker_updated_at": null,
    "created_at": "2026-09-29T12:02:21.780809Z",
    "status_history": [],
    "client_tag": "strat-7:entry",
    "lot_size": 1,
    "exchange": "NSE",
    "instrument_type": "EQUITY",
    "symbol": "RELIANCE",
    "expiry": "",
    "strike": 0,
    "option_type": "",
    "ltp": 2500,
    "prev_close": 2490,
    "instrument_token": "CT:TEST:RELIANCE",
    "order_tag": "01M3PGPRYMRRAPV8MCBEA19MS1"
  },
  "error": null
}

Modify an order #

PATCH /v1/orders/{order_id} scope orders

Changes an open order in one account: send the order as it should be now (same validation and market protection as placement).

More about this

Once the request is valid the answer is 200 with the broker's verdict in status; request-level problems are 4xx and change nothing. quantity must be greater than what has already filled.

Send an Idempotency-Key to make retries safe: a repeat with the same key gets the first answer back (Idempotent-Replayed: true) instead of modifying again.

Parameters

  • order_id path · string required

    Broker order id, order_tag or client_tag, as GET /v1/orders/{order_id} takes it (1-64 letters, digits, -, _, . or :). A tag is sent to the broker as the order's broker id.

  • Idempotency-Key header · string

    Optional: a new UUID per modify request (1-128 printable characters).

Body fields

  • account string required

    Account id the order is in (see /v1/accounts).

  • instrument_token string required

    Instrument id of the order.

  • side string required

    Order side.

    One of: BUY, SELL

  • order_type string required

    MARKET, LIMIT, SL (stop-loss limit) or SL_M (stop-loss market; SL-M and SLM are accepted in requests).

    One of: MARKET, LIMIT, SL, SL_M

  • product string required

    MIS (intraday), CARRYFORWARD (overnight derivatives, NRML), DELIVERY (equity delivery, CNC) or MTF (margin trading facility).

    One of: MIS, CARRYFORWARD, DELIVERY, MTF

  • quantity integer (int64) required

    Units, or lots when qty_is_in_lot. Units round down to whole lots; under one lot is refused.

  • qty_is_in_lot boolean

    quantity counts lots, not units.

  • price number (double)

    Limit price (LIMIT, SL); 0 or absent for market orders.

  • trigger_price number (double) | null

    Trigger price for SL / SL_M.

Errors

HTTPCodeWhen
400malformed_json

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

400invalid_idempotency_key

The Idempotency-Key header is not 1-128 printable characters.

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).

404account_not_found

No linked broker account with this id for the caller.

409order_not_open

The order is already finished (filled, cancelled or rejected), so there is nothing to modify or cancel. Nothing was sent to the broker.

409request_in_progress

A request with this Idempotency-Key is still being processed.

422invalid_request

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

422idempotency_key_reused

This Idempotency-Key was already used with a different request.

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).

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…

PATCH
curl -X PATCH "https://cirrus.pocketful.in/v1/orders/<order_id>" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account": "P1",
    "instrument_token": "CT:TEST:RELIANCE",
    "side": "BUY",
    "order_type": "SL",
    "product": "MIS",
    "quantity": 5,
    "price": 2500,
    "trigger_price": 2499
  }'
Response · 200
{
  "status": "success",
  "data": {
    "account": "P1",
    "order_id": "PAPER-9",
    "status": "accepted",
    "message": null
  },
  "error": null
}

Cancel an order #

DELETE /v1/orders/{order_id} scope orders

Cancels an open order in one account.

More about this

Once the request is valid the answer is 200 with the broker's verdict in status.

A bracket / cover entry is cancelled together with its legs. Once the entry has (partly) filled, its legs are the position's live stop-loss / target, so such a cancel is refused with 409 position_protected unless legs=true is sent; then the legs are cancelled, the answer carries a warning (the position is unprotected) and the activity log records the protection as removed. An entry that has not filled is cancelled as before.

Parameters

  • order_id path · string required

    Broker order id, order_tag or client_tag, as GET /v1/orders/{order_id} takes it (1-64 letters, digits, -, _, . or :). A tag is sent to the broker as the order's broker id.

  • account query · string required

    Account id the order is in.

  • instrument_token query · string required

    Instrument id of the order.

  • quantity query · integer (int64)

    Units still open (some brokers need it to cancel); 0 or absent otherwise.

  • legs query · boolean

    For a bracket / cover entry that has (partly) filled: true also cancels its live stop-loss / target legs, leaving the position unprotected. Without it such a cancel is refused (409 position_protected).

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).

404account_not_found

No linked broker account with this id for the caller.

409position_protected

The order is a (partly) filled bracket / cover entry: cancelling it would cancel the live stop-loss / target legs of its position. Send legs=true to do it anyway.

409order_not_open

The order is already finished (filled, cancelled or rejected), so there is nothing to modify or cancel. Nothing was sent to the broker.

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).

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…

DELETE
curl -X DELETE "https://cirrus.pocketful.in/v1/orders/<order_id>?account=<account>&instrument_token=<instrument_token>" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "account": "P1",
    "order_id": "PAPER-8",
    "status": "accepted",
    "message": null
  },
  "error": null
}

An order's protection #

GET /v1/orders/{order_id}/protection scope read

The stop-loss / target an order placed with protection on POST /v1/orders is protected by: status (none, waiting_for_fill, armed), where it lives (route), the rules asked for and the triggers holding it, each with the path to open it (version v2: /v2/triggers/{trigger_id}, v1: /v1/triggers/{trigger_id}).

More about this

The order is found as GET /v1/orders/{order_id} finds it (broker id, order_tag or client_tag, today's book). Protection records are kept 36 hours after the order; an older or unprotected order answers none.

Parameters

  • order_id path · string required

    Broker order id, order_tag or client_tag.

  • account query · string

    Only this account's book; every linked account when absent.

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).

404order_not_found

No order with this id (broker order id or order_tag) in the caller's order book today.

404account_not_found

No linked broker account with this id for the caller.

409ambiguous_order

The id names orders in more than one account (or several orders); message lists the accounts. Add account= to choose one.

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).

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/orders/<order_id>/protection" \
  -H "Authorization: token $CIRRUS_API_KEY"
Response · 200
{
  "status": "success",
  "data": {
    "account": "P1",
    "status": "armed",
    "route": "trigger",
    "rules": {
      "stop_loss": {
        "type": "points",
        "value": 20
      },
      "target": {
        "type": "points",
        "value": 40
      },
      "trail": null
    },
    "broker_id": null,
    "triggers": [
      {
        "trigger_id": "01JAC9X2K7QF0000000000TRG1",
        "version": "v2",
        "quantity": 5,
        "entry_price": 2499.5
      }
    ],
    "order_tag": "01JAC9X2K7QF0000000000PR01"
  },
  "error": null
}

Calculate order margins #

POST /v1/margins/orders scope read

The margin each order would need in each account, for the same body as POST /v1/orders (sized and priced as it would be placed).

More about this

Nothing is placed and no Idempotency-Key is needed. Accounts without a figure carry a message instead; the other accounts still get theirs.

Broker limits: Pocketful, 5paisa, Motilal Oswal, Tradejini, XTS and ODIN accounts have no margin calculation; their results have no figure and error_code not_supported_by_broker.

Body fields

  • orders object[] required
  • use_multiplier boolean

    Scale quantity by each account's Multiplier.

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).

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/margins/orders" \
  -H "Authorization: token $CIRRUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "orders": [
      {
        "instrument_token": "CT:TEST:RELIANCE",
        "side": "BUY",
        "order_type": "LIMIT",
        "product": "MIS",
        "quantity": 10,
        "price": 2500,
        "accounts": [
          "P2",
          "PF1"
        ]
      }
    ],
    "use_multiplier": true
  }'
Response · 200
{
  "status": "success",
  "data": {
    "results": [
      {
        "order_index": 0,
        "account": "PF1",
        "quantity": 10,
        "total_required": null,
        "message": "Margin calculation is not available for pocketful accounts.",
        "error_code": "not_supported_by_broker",
        "instrument_token": "CT:TEST:RELIANCE"
      },
      {
        "order_index": 0,
        "account": "P2",
        "quantity": 20,
        "total_required": 50000,
        "message": null,
        "error_code": null,
        "instrument_token": "CT:TEST:RELIANCE"
      }
    ],
    "total_required": 50000
  },
  "error": null
}