{
  "openapi": "3.1.0",
  "info": {
    "title": "Cirrus API",
    "description": "Trade across linked broker accounts with one API: place, modify and cancel orders (one order across many accounts), bracket / cover and GTT orders, server-side stop-loss / target triggers, live order book, positions, holdings, trades and funds, a WebSocket stream of changes, an activity log, and signed webhooks.\n\nEvery JSON response has the same envelope: `{\"status\": \"success\", \"data\": ..., \"error\": null}` or `{\"status\": \"error\", \"data\": null, \"error\": {\"code\", \"message\", \"field\"}}` (see `ErrorCode` for every code). All keys are snake_case. A few fields are also sent under a deprecated legacy name with the same value, and requests accept either name: `x-deprecated-aliases` lists them (per schema, and for the whole API under `info`). Use the documented names.\n\nAuthenticate with an API key (`Authorization: token <key_id>:<key_secret>`) or, for partner apps, an OAuth 2.0 access token (authorization code with PKCE). Operations tagged `app_session_only` (`x-app-only: true`) are available only to the signed-in app. Each operation's `x-required-scope` names the scope it needs.",
    "x-deprecated-aliases": {
      "cirrus_token": "instrument_token",
      "cirrus_tag": "order_tag",
      "cirrus_exits": "exits"
    },
    "version": "0.1.0"
  },
  "paths": {
    "/v1/orders": {
      "post": {
        "tags": [
          "orders"
        ],
        "summary": "Place orders",
        "description": "Places each order in every account it names (sized per account; split above the exchange freeze quantity). 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.\n\nRepeat a request with the same `Idempotency-Key` to get the first answer back (`Idempotent-Replayed: true`) instead of placing again.",
        "operationId": "place_orders",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A new UUID per order request (1-128 printable characters).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlaceOrdersRequest"
              },
              "examples": {
                "partial_failure": {
                  "summary": "One order, two accounts: one accepted, one refused",
                  "value": {
                    "orders": [
                      {
                        "instrument_token": "CT:TEST:RELIANCE",
                        "side": "BUY",
                        "order_type": "LIMIT",
                        "product": "DELIVERY",
                        "quantity": 1,
                        "price": 2500,
                        "accounts": [
                          "P1",
                          "Z1"
                        ]
                      }
                    ]
                  }
                },
                "protected": {
                  "summary": "Protected entry: a broker bracket where the broker has one, a server-side trigger elsewhere",
                  "value": {
                    "orders": [
                      {
                        "instrument_token": "CT:TEST:RELIANCE",
                        "side": "BUY",
                        "order_type": "LIMIT",
                        "product": "MIS",
                        "quantity": 5,
                        "price": 2500,
                        "accounts": [
                          "PF1",
                          "P1"
                        ],
                        "protection": {
                          "stop_loss": {
                            "enabled": true,
                            "type": "points",
                            "value": 20
                          },
                          "target": {
                            "enabled": true,
                            "type": "points",
                            "value": 40
                          }
                        }
                      }
                    ]
                  }
                },
                "success": {
                  "summary": "Placed in one account",
                  "value": {
                    "orders": [
                      {
                        "instrument_token": "CT:TEST:RELIANCE",
                        "side": "BUY",
                        "order_type": "LIMIT",
                        "product": "DELIVERY",
                        "quantity": 1,
                        "price": 2500,
                        "accounts": [
                          "P1"
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Placement ran; one result per slice.",
            "headers": {
              "Idempotent-Replayed": {
                "schema": {
                  "type": "string"
                },
                "description": "`true` when this is the stored answer to an earlier request with the same key."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_PlaceOrdersResponse"
                },
                "examples": {
                  "partial_failure": {
                    "summary": "One order, two accounts: one accepted, one refused",
                    "value": {
                      "status": "success",
                      "data": {
                        "results": [
                          {
                            "order_index": 0,
                            "account": "P1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "cirrus_tag": "01M3MQZWZC63GQBA2RNYAXX1M8",
                            "quantity": 1,
                            "status": "accepted",
                            "order_id": "PAPER-1",
                            "message": null,
                            "order_type": "LIMIT",
                            "price": 2500,
                            "instrument_token": "CT:TEST:RELIANCE",
                            "order_tag": "01M3MQZWZC63GQBA2RNYAXX1M8"
                          },
                          {
                            "order_index": 0,
                            "account": "Z1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "cirrus_tag": "01M3MQZWZDP8V1WSK2M7TRSVBE",
                            "quantity": 1,
                            "status": "rejected",
                            "order_id": null,
                            "message": "Broker zerodha is not supported yet.",
                            "order_type": "LIMIT",
                            "price": 2500,
                            "instrument_token": "CT:TEST:RELIANCE",
                            "order_tag": "01M3MQZWZDP8V1WSK2M7TRSVBE"
                          }
                        ],
                        "accepted": 1,
                        "rejected": 1,
                        "unknown": 0
                      },
                      "error": null
                    }
                  },
                  "protected": {
                    "summary": "Protected entry: a broker bracket where the broker has one, a server-side trigger elsewhere",
                    "value": {
                      "status": "success",
                      "data": {
                        "results": [
                          {
                            "order_index": 0,
                            "account": "PF1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "cirrus_tag": "01M3MQZWZ8PW47QZB5A0Y2DWXR",
                            "quantity": 5,
                            "status": "accepted",
                            "order_id": null,
                            "message": "placed as a broker bracket order (basket 777)",
                            "order_type": "LIMIT",
                            "price": 2500,
                            "protection": "bracket",
                            "protection_id": "777",
                            "instrument_token": "CT:TEST:RELIANCE",
                            "order_tag": "01M3MQZWZ8PW47QZB5A0Y2DWXR"
                          },
                          {
                            "order_index": 0,
                            "account": "P1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "cirrus_tag": "01M3MQZWZ84XTJYCDY33KN40EP",
                            "quantity": 5,
                            "status": "accepted",
                            "order_id": "PAPER-1",
                            "message": null,
                            "order_type": "LIMIT",
                            "price": 2500,
                            "protection": "trigger",
                            "instrument_token": "CT:TEST:RELIANCE",
                            "order_tag": "01M3MQZWZ84XTJYCDY33KN40EP"
                          }
                        ],
                        "accepted": 2,
                        "rejected": 0,
                        "unknown": 0
                      },
                      "error": null
                    }
                  },
                  "success": {
                    "summary": "Placed in one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "results": [
                          {
                            "order_index": 0,
                            "account": "P1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "cirrus_tag": "01M3MQZWZ9F0JEZ3JCBMBCHJTP",
                            "quantity": 1,
                            "status": "accepted",
                            "order_id": "PAPER-1",
                            "message": null,
                            "order_type": "LIMIT",
                            "price": 2500,
                            "instrument_token": "CT:TEST:RELIANCE",
                            "order_tag": "01M3MQZWZ9F0JEZ3JCBMBCHJTP"
                          }
                        ],
                        "accepted": 1,
                        "rejected": 0,
                        "unknown": 0
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`, `idempotency_key_required` or `invalid_idempotency_key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`request_in_progress`: an earlier request with this key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field` names the input, e.g. `orders[0].price`) or `idempotency_key_reused`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_quantity": {
                    "summary": "A zero quantity is refused; nothing is placed",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "quantity must be greater than 0",
                        "field": "orders[0].quantity"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: market data or accounts are temporarily unavailable; nothing was placed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/orders/{order_id}": {
      "delete": {
        "tags": [
          "orders"
        ],
        "summary": "Cancel an order",
        "description": "Cancels an open order in one account. Once the request is valid the answer is 200 with the broker's verdict in `status`.",
        "operationId": "cancel_order",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "description": "Broker order id (1-64 letters, digits, `-`, `_` or `.`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account",
            "in": "query",
            "description": "Account id the order is in.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument_token",
            "in": "query",
            "description": "Instrument id of the order.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "x-deprecated-aliases": {
              "cirrus_token": "instrument_token"
            }
          },
          {
            "name": "quantity",
            "in": "query",
            "description": "Units still open (some brokers need it to cancel); 0 or absent\notherwise.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_AmendResult"
                },
                "examples": {
                  "broker_refused": {
                    "summary": "The broker refused: its reason is in `message`",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "P1",
                        "order_id": "PAPER-7",
                        "status": "rejected",
                        "message": "Order already completed"
                      },
                      "error": null
                    }
                  },
                  "success": {
                    "summary": "The broker cancelled the order",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "P1",
                        "order_id": "PAPER-8",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_query`: a parameter is missing or not valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_account": {
                    "summary": "`account` is required",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_query",
                        "message": "invalid query string: missing field `account`",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: bad `order_id` or unknown instrument.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or market data are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      },
      "patch": {
        "tags": [
          "orders"
        ],
        "summary": "Modify an order",
        "description": "Changes an open order in one account: send the order as it should be now (same validation and market protection as placement). Once the request is valid the answer is 200 with the broker's verdict in `status`; request-level problems are 4xx and change nothing.",
        "operationId": "modify_order",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "description": "Broker order id (1-64 letters, digits, `-`, `_` or `.`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyOrderRequest"
              },
              "examples": {
                "success": {
                  "summary": "The broker accepted the change",
                  "value": {
                    "account": "P1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "side": "BUY",
                    "order_type": "SL",
                    "product": "MIS",
                    "quantity": 5,
                    "price": 2500,
                    "trigger_price": 2499
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_AmendResult"
                },
                "examples": {
                  "success": {
                    "summary": "The broker accepted the change",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "P1",
                        "order_id": "PAPER-9",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "No linked account with this id",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "Account not found for this user",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field` names the input, e.g. `price`, `quantity`, `order_id`, `instrument_token`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "price_off_tick": {
                    "summary": "A price off the tick grid is refused; nothing is sent",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "price 2500.03 is not a multiple of tick size 0.05",
                        "field": "price"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or market data are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/margins/orders": {
      "post": {
        "tags": [
          "orders"
        ],
        "summary": "Calculate order margins",
        "description": "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). Nothing is placed and no `Idempotency-Key` is needed. Accounts without a figure carry a `message` instead; the other accounts still get theirs.",
        "operationId": "calculate_order_margins",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlaceOrdersRequest"
              },
              "examples": {
                "success": {
                  "summary": "One account with a figure, one whose broker cannot calculate margins",
                  "value": {
                    "orders": [
                      {
                        "instrument_token": "CT:TEST:RELIANCE",
                        "side": "BUY",
                        "order_type": "LIMIT",
                        "product": "MIS",
                        "quantity": 10,
                        "price": 2500,
                        "accounts": [
                          "P2",
                          "PF1"
                        ]
                      }
                    ],
                    "use_multiplier": true
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "One result per order and account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_OrderMarginResponse"
                },
                "examples": {
                  "success": {
                    "summary": "One account with a figure, one whose broker cannot calculate margins",
                    "value": {
                      "status": "success",
                      "data": {
                        "results": [
                          {
                            "order_index": 0,
                            "account": "PF1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "quantity": 10,
                            "total_required": null,
                            "message": "Margin calculation is not available for pocketful",
                            "instrument_token": "CT:TEST:RELIANCE"
                          },
                          {
                            "order_index": 0,
                            "account": "P2",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "quantity": 20,
                            "total_required": 50000,
                            "message": null,
                            "instrument_token": "CT:TEST:RELIANCE"
                          }
                        ],
                        "total_required": 50000
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`invalid_request` (`field` names the input, e.g. `orders[0].quantity`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "no_accounts": {
                    "summary": "An order needs at least one account",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "at least one account is required",
                        "field": "orders[0].accounts"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: market data or accounts are temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/orders/bracket": {
      "post": {
        "tags": [
          "orders"
        ],
        "summary": "Place a bracket or cover order",
        "description": "Places a broker bracket (`BO`: entry + stop-loss + target) or cover (`CO`: entry + stop-loss) order in one account; the legs show up in the order book as ordinary orders. Once the request is valid the answer is 200 with the broker's verdict in `status`; request-level problems are 4xx and place nothing.\n\nRepeat a request with the same `Idempotency-Key` to get the first answer back (`Idempotent-Replayed: true`) instead of placing again.",
        "operationId": "place_bracket_order",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A new UUID per order request (1-128 printable characters).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BracketRequest"
              },
              "examples": {
                "success": {
                  "summary": "Bracket order accepted",
                  "value": {
                    "account": "PF1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "kind": "BO",
                    "side": "BUY",
                    "order_type": "LIMIT",
                    "product": "MIS",
                    "quantity": 5,
                    "price": 2500,
                    "stop_loss": 2450,
                    "target": 2600
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "headers": {
              "Idempotent-Replayed": {
                "schema": {
                  "type": "string"
                },
                "description": "`true` when this is the stored answer to an earlier request with the same key."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_BracketResult"
                },
                "examples": {
                  "success": {
                    "summary": "Bracket order accepted",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "basket_id": "777",
                        "order_id": null,
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`idempotency_key_required`, `invalid_idempotency_key` or `malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "idempotency_key_required": {
                    "summary": "The Idempotency-Key header is required",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "idempotency_key_required",
                        "message": "Idempotency-Key header is required (use a new UUID per order request)",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "`request_in_progress`: an earlier request with this key is still running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field` names the input, e.g. `stop_loss`, `target`, `price`, `quantity`) or `idempotency_key_reused`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missing_target": {
                    "summary": "A bracket order (BO) needs a target",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "a bracket order (BO) needs a target",
                        "field": "target"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or market data (the LTP a market entry is checked against) are temporarily unavailable; nothing was placed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/orders/bracket/{order_id}": {
      "delete": {
        "tags": [
          "orders"
        ],
        "summary": "Cancel a bracket or cover order",
        "description": "Cancels a bracket / cover order (entry and legs) in one account. Once the request is valid the answer is 200 with the broker's verdict in `status`.\n\nA missing or invalid query parameter is answered with a plain-text 400, not the JSON envelope.",
        "operationId": "cancel_bracket_order",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "description": "Broker order id of the entry (1-64 letters, digits, `-`, `_` or `.`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account",
            "in": "query",
            "description": "Account id the order is in.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "`BO` or `CO`.",
            "required": true,
            "schema": {
              "type": "string",
              "description": "`BO` (bracket: entry + stop-loss + target) or `CO` (cover: entry +\nstop-loss).",
              "enum": [
                "BO",
                "CO"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_BracketResult"
                },
                "examples": {
                  "success": {
                    "summary": "Entry and legs cancelled",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "basket_id": null,
                        "order_id": "250929000001",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Plain text (not the JSON envelope): a query parameter is missing or not valid, e.g. `Failed to deserialize query string: missing field kind`.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "No linked account with this id",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "Account not found for this user",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: bad `order_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      },
      "patch": {
        "tags": [
          "orders"
        ],
        "summary": "Modify a bracket or cover order",
        "description": "Changes the entry price or quantity, or the legs, of a bracket / cover order in one account. Once the request is valid the answer is 200 with the broker's verdict in `status`.",
        "operationId": "modify_bracket_order",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "description": "Broker order id of the entry (1-64 letters, digits, `-`, `_` or `.`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyBracketRequest"
              },
              "examples": {
                "success": {
                  "summary": "Both legs of a bracket order moved",
                  "value": {
                    "account": "PF1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "kind": "BO",
                    "side": "BUY",
                    "entry_price": 2500,
                    "stop_loss": 2460,
                    "target": 2620
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_BracketResult"
                },
                "examples": {
                  "success": {
                    "summary": "Both legs of a bracket order moved",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "basket_id": null,
                        "order_id": "250929000001",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `order_id`, `stop_loss`, `target`, `instrument_token`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "cover_has_no_target": {
                    "summary": "A cover order (CO) has no target",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "a cover order (CO) has no target",
                        "field": "target"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or market data are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/positions/convert": {
      "post": {
        "tags": [
          "orders"
        ],
        "summary": "Convert a position",
        "description": "Moves an open position in one account to another product (e.g. `MIS` to `CARRYFORWARD`). Once the request is valid the answer is 200 with the broker's verdict in `status`.",
        "operationId": "convert_position",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConvertRequest"
              },
              "examples": {
                "not_available": {
                  "summary": "The account's broker cannot convert positions",
                  "value": {
                    "account": "P1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "side": "BUY",
                    "quantity": 5,
                    "from": "MIS",
                    "to": "DELIVERY"
                  }
                },
                "success": {
                  "summary": "Moved from MIS to DELIVERY",
                  "value": {
                    "account": "PF1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "side": "BUY",
                    "quantity": 5,
                    "from": "MIS",
                    "to": "DELIVERY"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_ConvertResult"
                },
                "examples": {
                  "not_available": {
                    "summary": "The account's broker cannot convert positions",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "P1",
                        "status": "rejected",
                        "message": "Position conversion is not available for paper accounts."
                      },
                      "error": null
                    }
                  },
                  "success": {
                    "summary": "Moved from MIS to DELIVERY",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `quantity`, `to`, `instrument_token`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "same_product": {
                    "summary": "`to` must differ from `from`",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "`to` must differ from `from`",
                        "field": "to"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or market data are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/gtt": {
      "get": {
        "tags": [
          "gtt"
        ],
        "summary": "List GTTs",
        "description": "Every GTT at the broker, per account (a live read, including GTTs made outside this API). An account whose list cannot be read carries an `error`; the others are still listed.\n\nAn unknown query parameter is answered with a plain-text 400, not the JSON envelope.",
        "operationId": "list_gtts",
        "parameters": [
          {
            "name": "account",
            "in": "query",
            "description": "Only this account; every account when absent.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One entry per account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_AccountGtts"
                },
                "examples": {
                  "cannot_list": {
                    "summary": "The account's broker cannot list GTTs: `error` says so",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "account": "P1",
                          "broker": "paper",
                          "gtts": [],
                          "error": "Listing GTTs is not available for paper accounts."
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Plain text (not the JSON envelope): the query string is not valid, e.g. an unknown parameter.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`: no linked account with this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "No linked account with this id",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "Account NOPE not found for this user",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts are temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      },
      "post": {
        "tags": [
          "gtt"
        ],
        "summary": "Create a GTT",
        "description": "Creates a GTT at the broker in one account: a stop-loss, a target, or both (whichever fires first cancels the other). Legs are checked against the tick grid and the live price. Once the request is valid the answer is 200 with the broker's verdict in `status`.",
        "operationId": "create_gtt",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GttRequest"
              },
              "examples": {
                "success": {
                  "summary": "Stop-loss and target GTT created at the broker",
                  "value": {
                    "account": "PF1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "side": "SELL",
                    "product": "DELIVERY",
                    "quantity": 5,
                    "stop_loss": {
                      "trigger": 2400
                    },
                    "target": {
                      "trigger": 2600,
                      "price": 2600
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_GttResult"
                },
                "examples": {
                  "success": {
                    "summary": "Stop-loss and target GTT created at the broker",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "trigger_id": "0f6c1a52-4d7e-4b8e-9d51-2c7a9e3b1f20",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `stop_loss`, `target`, `quantity`, `instrument_token`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "legs_on_wrong_side": {
                    "summary": "A SELL's stop-loss must sit below LTP and its target above",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "for a Sell GTT the stop-loss and target must sit on opposite sides of LTP 2500 (stop-loss below, target above)",
                        "field": "stop_loss"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or the live price are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/gtt/{trigger_id}": {
      "delete": {
        "tags": [
          "gtt"
        ],
        "summary": "Delete a GTT",
        "description": "Deletes a GTT at the broker. Once the request is valid the answer is 200 with the broker's verdict in `status`.\n\nA missing or unknown query parameter is answered with a plain-text 400, not the JSON envelope.",
        "operationId": "delete_gtt",
        "parameters": [
          {
            "name": "trigger_id",
            "in": "path",
            "description": "The broker's GTT id (1-64 letters, digits, `-`, `_` or `.`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account",
            "in": "query",
            "description": "Account id the GTT is in.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_GttResult"
                },
                "examples": {
                  "success": {
                    "summary": "Deleted at the broker",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "trigger_id": "0f6c1a52-4d7e-4b8e-9d51-2c7a9e3b1f20",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Plain text (not the JSON envelope): `account` is missing or the query string is not valid.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "No linked account with this id",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "Account not found for this user",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: bad `trigger_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      },
      "patch": {
        "tags": [
          "gtt"
        ],
        "summary": "Modify a GTT",
        "description": "Replaces a GTT's legs and quantity at the broker: send the GTT as it should be now (same body and checks as creating). Once the request is valid the answer is 200 with the broker's verdict in `status`.",
        "operationId": "modify_gtt",
        "parameters": [
          {
            "name": "trigger_id",
            "in": "path",
            "description": "The broker's GTT id (1-64 letters, digits, `-`, `_` or `.`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GttRequest"
              },
              "examples": {
                "success": {
                  "summary": "Both legs moved",
                  "value": {
                    "account": "PF1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "side": "SELL",
                    "product": "DELIVERY",
                    "quantity": 5,
                    "stop_loss": {
                      "trigger": 2420
                    },
                    "target": {
                      "trigger": 2650,
                      "price": 2650
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The broker's answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_GttResult"
                },
                "examples": {
                  "success": {
                    "summary": "Both legs moved",
                    "value": {
                      "status": "success",
                      "data": {
                        "account": "PF1",
                        "trigger_id": "0f6c1a52-4d7e-4b8e-9d51-2c7a9e3b1f20",
                        "status": "accepted",
                        "message": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `trigger_id`, `stop_loss`, `target`, `quantity`, `instrument_token`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_trigger_id": {
                    "summary": "The GTT id has characters an id cannot have",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "trigger_id must be 1-64 letters, digits, '-', '_' or '.'",
                        "field": "trigger_id"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or the live price are temporarily unavailable; nothing was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "orders"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "orders"
      }
    },
    "/v1/triggers": {
      "get": {
        "tags": [
          "triggers"
        ],
        "summary": "List triggers",
        "description": "Every trigger of the caller, with its live levels and status: server-side triggers and the mirrors of broker-held protection (bracket / cover legs, GTTs) armed from placed orders.",
        "operationId": "list_triggers",
        "responses": {
          "200": {
            "description": "The caller's triggers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_TriggerView"
                },
                "examples": {
                  "success": {
                    "summary": "A server-side trigger and a broker-held GTT",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "trigger_id": "efb67bb6-5c8a-44dc-ab8e-dbdec912a0b6",
                          "account": "P1",
                          "cirrus_token": "CT:TEST:RELIANCE",
                          "name": "SL + TGT + TSL",
                          "side": "BUY",
                          "product": "MIS",
                          "quantity": 5,
                          "price": 2500,
                          "order_id": null,
                          "broker_order_id": null,
                          "kind": "platform",
                          "cirrus_exits": true,
                          "rules": {
                            "target": {
                              "enabled": true,
                              "type": "percentage",
                              "value": 2
                            },
                            "stop_loss": {
                              "enabled": true,
                              "type": "points",
                              "value": 25
                            },
                            "trail": {
                              "enabled": true,
                              "type": "points",
                              "value": 5
                            }
                          },
                          "stop_loss_price": 2475,
                          "initial_stop_loss_price": 2475,
                          "target_price": 2550,
                          "live": true,
                          "status": null,
                          "created_at": "2026-09-29 01:01:12",
                          "updated_at": "2026-09-29 01:01:12",
                          "instrument_token": "CT:TEST:RELIANCE",
                          "exits": true
                        },
                        {
                          "trigger_id": "489301aa-4fbb-4cb6-adef-6b7813c6b78f",
                          "account": "PF1",
                          "cirrus_token": "CT:TEST:RELIANCE",
                          "name": "SL + TGT",
                          "side": "BUY",
                          "product": "DELIVERY",
                          "quantity": 5,
                          "price": 2500,
                          "order_id": "250929000002",
                          "broker_order_id": "gtt-held",
                          "kind": "gtt_oco",
                          "cirrus_exits": false,
                          "rules": {
                            "target": {
                              "enabled": true,
                              "type": "points",
                              "value": 100
                            },
                            "stop_loss": {
                              "enabled": true,
                              "type": "points",
                              "value": 25
                            },
                            "trail": {
                              "enabled": false,
                              "type": "percentage",
                              "value": 0
                            }
                          },
                          "stop_loss_price": 2475,
                          "initial_stop_loss_price": 2475,
                          "target_price": 2600,
                          "live": true,
                          "status": null,
                          "created_at": "2026-09-29 01:01:12",
                          "updated_at": "2026-09-29 01:01:12",
                          "instrument_token": "CT:TEST:RELIANCE",
                          "exits": false
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "No credential",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unauthorized",
                        "message": "Missing access token",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: triggers are temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      },
      "post": {
        "tags": [
          "triggers"
        ],
        "summary": "Protect a position",
        "description": "Creates a server-side trigger on an open position: its stop-loss / target (and trailing stop-loss) are watched on every tick and the server exits at market when one is hit. Levels are measured from `price` (LTP when absent); a level already crossed at LTP is refused. Needs a running trigger exit worker: without one nothing is created (503 `trigger_worker_down`).",
        "operationId": "create_trigger",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProtectRequest"
              },
              "examples": {
                "success": {
                  "summary": "Stop-loss 25 points below, target 2% above, trailing by 5 points",
                  "value": {
                    "account": "P1",
                    "instrument_token": "CT:TEST:RELIANCE",
                    "side": "BUY",
                    "product": "MIS",
                    "quantity": 5,
                    "price": 2500,
                    "rules": {
                      "stop_loss": {
                        "enabled": true,
                        "type": "points",
                        "value": 25
                      },
                      "target": {
                        "enabled": true,
                        "type": "percentage",
                        "value": 2
                      },
                      "trail": {
                        "enabled": true,
                        "type": "points",
                        "value": 5
                      }
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_TriggerView"
                },
                "examples": {
                  "success": {
                    "summary": "Stop-loss 25 points below, target 2% above, trailing by 5 points",
                    "value": {
                      "status": "success",
                      "data": {
                        "trigger_id": "aa554bda-c2ad-4981-9f83-c7291c567c40",
                        "account": "P1",
                        "cirrus_token": "CT:TEST:RELIANCE",
                        "name": "SL + TGT + TSL",
                        "side": "BUY",
                        "product": "MIS",
                        "quantity": 5,
                        "price": 2500,
                        "order_id": null,
                        "broker_order_id": null,
                        "kind": "platform",
                        "cirrus_exits": true,
                        "rules": {
                          "target": {
                            "enabled": true,
                            "type": "percentage",
                            "value": 2
                          },
                          "stop_loss": {
                            "enabled": true,
                            "type": "points",
                            "value": 25
                          },
                          "trail": {
                            "enabled": true,
                            "type": "points",
                            "value": 5
                          }
                        },
                        "stop_loss_price": 2475,
                        "initial_stop_loss_price": 2475,
                        "target_price": 2550,
                        "live": true,
                        "status": null,
                        "created_at": "2026-09-29 01:01:12",
                        "updated_at": "2026-09-29 01:01:12",
                        "instrument_token": "CT:TEST:RELIANCE",
                        "exits": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: invalid `rules` (or a level already crossed at LTP), or an unknown instrument.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "already_crossed": {
                    "summary": "A stop-loss already crossed at LTP is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "the stop-loss is already crossed at LTP 2500; it would exit immediately",
                        "field": "rules"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`trigger_worker_down` (nothing was created) or `service_unavailable` (accounts, market data or triggers temporarily unavailable).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "triggers"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "triggers"
      }
    },
    "/v1/triggers/{trigger_id}": {
      "delete": {
        "tags": [
          "triggers"
        ],
        "summary": "Delete a trigger",
        "description": "Removes a trigger. Broker-held protection is cancelled at the broker first (the bracket / cover order or the GTT); the trigger is removed only once the broker agreed.",
        "operationId": "delete_trigger",
        "parameters": [
          {
            "name": "trigger_id",
            "in": "path",
            "description": "The trigger's id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_TriggerDeleted"
                },
                "examples": {
                  "success": {
                    "summary": "Deleted",
                    "value": {
                      "status": "success",
                      "data": {
                        "trigger_id": "33a9061d-deb5-4c85-8969-01d63f07e0bc",
                        "deleted": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`trigger_not_found`, or `account_not_found` (the broker-held protection's account is no longer linked).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No trigger with this id (here: already deleted)",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "trigger_not_found",
                        "message": "Trigger not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`trigger_fired`: it already fired; its exit is being handled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "description": "`broker_refused`: the broker did not cancel its protection; the trigger is kept.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "broker_refused": {
                    "summary": "The broker did not cancel its GTT; the trigger is kept",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "broker_refused",
                        "message": "GTT already triggered",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "`service_unavailable`: triggers or accounts are temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "triggers"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "triggers"
      },
      "patch": {
        "tags": [
          "triggers"
        ],
        "summary": "Change a trigger",
        "description": "Changes the rules, quantity or entry price of a server-side trigger. Levels are recomputed only for the legs whose inputs changed, so trailing progress on an untouched stop-loss is kept. Broker-held protection (`exits: false`) is changed at the broker instead (409 `broker_held`).",
        "operationId": "modify_trigger",
        "parameters": [
          {
            "name": "trigger_id",
            "in": "path",
            "description": "The trigger's id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModifyTriggerRequest"
              },
              "examples": {
                "success": {
                  "summary": "New entry price and quantity; the levels follow the price",
                  "value": {
                    "price": 2510,
                    "quantity": 3
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Changed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_TriggerView"
                },
                "examples": {
                  "success": {
                    "summary": "New entry price and quantity; the levels follow the price",
                    "value": {
                      "status": "success",
                      "data": {
                        "trigger_id": "710f58d1-9253-4194-b225-12f7a23e5862",
                        "account": "P1",
                        "cirrus_token": "CT:TEST:RELIANCE",
                        "name": "SL + TGT + TSL",
                        "side": "BUY",
                        "product": "MIS",
                        "quantity": 3,
                        "price": 2510,
                        "order_id": null,
                        "broker_order_id": null,
                        "kind": "platform",
                        "cirrus_exits": true,
                        "rules": {
                          "target": {
                            "enabled": true,
                            "type": "percentage",
                            "value": 2
                          },
                          "stop_loss": {
                            "enabled": true,
                            "type": "points",
                            "value": 25
                          },
                          "trail": {
                            "enabled": true,
                            "type": "points",
                            "value": 5
                          }
                        },
                        "stop_loss_price": 2485,
                        "initial_stop_loss_price": 2485,
                        "target_price": 2560.2,
                        "live": true,
                        "status": null,
                        "created_at": "2026-09-29 01:01:12",
                        "updated_at": "2026-09-29 01:01:12",
                        "instrument_token": "CT:TEST:RELIANCE",
                        "exits": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`trigger_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No trigger with this id",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "trigger_not_found",
                        "message": "Trigger not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`trigger_fired` (it already fired), `broker_held` (the broker holds the legs) or `trigger_busy` (it kept changing while updating; retry).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "broker_held": {
                    "summary": "Broker-held protection is changed at the broker",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "broker_held",
                        "message": "This protection is held by the broker; change the broker order instead",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: nothing to change, or invalid rules / quantity / price.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: triggers are temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "triggers"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "triggers"
      }
    },
    "/v1/portfolio/{kind}": {
      "get": {
        "tags": [
          "portfolio"
        ],
        "summary": "Order book, positions, holdings, trades or funds",
        "description": "One kind of data for every linked account (or only `account`), from the live per-account snapshots: no broker call on the read path. Each account with data is under `accounts`, each without (broker not supported yet, no active session) under `missing` with the reason. The shape of each `data` depends on `kind`: `orders` (today's order book, newest first): a list of `OrderData`; `positions`: a list of `PositionRow`; `holdings`: a list of `HoldingRow`; `trades` (today's fills): a list of `TradeRow`; `margins`: one `MarginRow` object. Rows carry instrument details and live prices when known.",
        "operationId": "get_portfolio",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "description": "Which data: `orders`, `positions`, `holdings`, `trades` or `margins`.",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/SnapshotKind"
            }
          },
          {
            "name": "account",
            "in": "query",
            "description": "Only this linked account (its id).",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Per-account data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_PortfolioResponse"
                },
                "examples": {
                  "holdings": {
                    "summary": "Holdings of one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "P1",
                            "updated_at": "2026-09-28T19:31:12.035116Z",
                            "data": [
                              {
                                "account": "P1",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "product": "DELIVERY",
                                "quantity": 10,
                                "average_price": 2400,
                                "invested_amount": 24000,
                                "pnl": 1000,
                                "pnl_percent": 4.17,
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE"
                              }
                            ]
                          }
                        ],
                        "missing": []
                      },
                      "error": null
                    }
                  },
                  "margins": {
                    "summary": "Funds of one account (one object)",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "P1",
                            "updated_at": "2026-09-28T19:31:12.041560Z",
                            "data": {
                              "account": "P1",
                              "opening_balance": 100000,
                              "available": 90000.8,
                              "utilised": 9999.2
                            }
                          }
                        ],
                        "missing": []
                      },
                      "error": null
                    }
                  },
                  "orders": {
                    "summary": "Today's order book of one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "P1",
                            "updated_at": "2026-09-28T19:31:12.042868Z",
                            "data": [
                              {
                                "cirrus_tag": "01M3MQZX1AF8Z74E43NAT1YCQ5",
                                "broker_tag": "a1b2c3",
                                "order_id": "240927000012345",
                                "parent_tag": null,
                                "username": "user-01M3MQZX047V42W740CP2QY5QN",
                                "account": "P1",
                                "broker": "paper",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "side": "BUY",
                                "order_type": "LIMIT",
                                "product": "DELIVERY",
                                "quantity": 1,
                                "price": 2500,
                                "trigger_price": null,
                                "state": "OPEN",
                                "filled_qty": 0,
                                "average_price": null,
                                "status_message": null,
                                "broker_updated_at": "2026-09-28T19:31:12.042868Z",
                                "created_at": "2026-09-28T19:31:12.042868Z",
                                "status_history": [
                                  {
                                    "from": "SUBMITTED",
                                    "to": "OPEN",
                                    "at": "2026-09-28T19:31:12.042868Z",
                                    "message": null
                                  }
                                ],
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE",
                                "order_tag": "01M3MQZX1AF8Z74E43NAT1YCQ5"
                              }
                            ]
                          }
                        ],
                        "missing": []
                      },
                      "error": null
                    }
                  },
                  "positions": {
                    "summary": "Open positions of one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "P1",
                            "updated_at": "2026-09-28T19:31:12.034488Z",
                            "data": [
                              {
                                "account": "P1",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "product": "MIS",
                                "net_qty": 4,
                                "buy_qty": 4,
                                "sell_qty": 0,
                                "buy_value": 9999.2,
                                "sell_value": 0,
                                "average_price": 2499.8,
                                "buy_average_price": 2499.8,
                                "sell_average_price": 0,
                                "pnl": 0.8,
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE"
                              }
                            ]
                          }
                        ],
                        "missing": []
                      },
                      "error": null
                    }
                  },
                  "trades": {
                    "summary": "Today's fills of one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "P1",
                            "updated_at": "2026-09-28T19:31:12.038635Z",
                            "data": [
                              {
                                "account": "P1",
                                "order_id": "240927000012345",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "side": "BUY",
                                "quantity": 4,
                                "fill_price": 2499.8,
                                "trade_value": 9999.2,
                                "filled_at": "2026-09-28T19:31:12.034472Z",
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE"
                              }
                            ]
                          }
                        ],
                        "missing": []
                      },
                      "error": null
                    }
                  },
                  "with_missing_accounts": {
                    "summary": "Every account: those without data are listed under missing",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "P1",
                            "updated_at": "2026-09-28T19:31:12.041560Z",
                            "data": {
                              "account": "P1",
                              "opening_balance": 100000,
                              "available": 90000.8,
                              "utilised": 9999.2
                            }
                          }
                        ],
                        "missing": [
                          {
                            "account": "P2",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          },
                          {
                            "account": "Z1",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          },
                          {
                            "account": "PF1",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          },
                          {
                            "account": "U1",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          },
                          {
                            "account": "5P1",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          },
                          {
                            "account": "MO1",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          },
                          {
                            "account": "TJ1",
                            "reason": "No live data yet for this account (broker not supported yet, or no active session)"
                          }
                        ]
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unreadable query string (an unknown parameter): a plain-text answer, not the JSON envelope.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`: `account` is not one of the caller's linked accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "The account is not one of the caller's",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "Account not found for this user",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `kind`): unknown kind (checked only when the caller has at least one account).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_kind": {
                    "summary": "An unknown kind is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "kind must be one of orders, positions, holdings, trades, margins",
                        "field": "kind"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or snapshots are temporarily unavailable; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/portfolio/refresh": {
      "post": {
        "tags": [
          "portfolio"
        ],
        "summary": "Re-read positions, holdings and funds",
        "description": "Asks the live workers of every linked account (or only `account`) to re-read positions, holdings, trades and funds from the broker now. Returns at once (202); the new data reaches `GET /v1/portfolio/{kind}` and the stream within seconds. Recorded in the activity log.",
        "operationId": "refresh_portfolio",
        "parameters": [
          {
            "name": "account",
            "in": "query",
            "description": "Only this linked account (its id).",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Refresh requested.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_PortfolioRefresh"
                },
                "examples": {
                  "success": {
                    "summary": "One account asked to re-read",
                    "value": {
                      "status": "success",
                      "data": {
                        "requested": 1
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unreadable query string (an unknown parameter): a plain-text answer, not the JSON envelope.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`: `account` is not one of the caller's linked accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "The account is not one of the caller's",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "Account not found for this user",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: the refresh could not be requested (or accounts could not be loaded); retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/accounts": {
      "get": {
        "tags": [
          "accounts"
        ],
        "summary": "List linked broker accounts",
        "description": "Every broker account the user linked, sorted by id, with whether it can trade now (`status`), what it lacks (`missing`) and how order updates arrive (`updates`). Never a credential.",
        "operationId": "list_accounts",
        "responses": {
          "200": {
            "description": "The accounts (may be empty).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_AccountList"
                },
                "examples": {
                  "success": {
                    "summary": "Ready, login-required and incomplete accounts",
                    "value": {
                      "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
                          },
                          {
                            "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
                          },
                          {
                            "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
                          },
                          {
                            "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
                          },
                          {
                            "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
                          },
                          {
                            "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-09-28T20:31:11Z",
                            "seat_assigned": null,
                            "last_update_at": "2026-09-28T19:31:11.879659Z"
                          },
                          {
                            "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
                          },
                          {
                            "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
                          }
                        ]
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "No credential",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unauthorized",
                        "message": "Missing access token",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or their status could not be read; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/accounts/{account}": {
      "get": {
        "tags": [
          "accounts"
        ],
        "summary": "One linked broker account",
        "description": "The account as in `GET /v1/accounts`, plus `health`: what its live worker last reported (order-update stream, polling, last book read, last broker error).",
        "operationId": "get_account",
        "parameters": [
          {
            "name": "account",
            "in": "path",
            "description": "Account id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_AccountDetail"
                },
                "examples": {
                  "login_required": {
                    "summary": "No session and no recent health report",
                    "value": {
                      "status": "success",
                      "data": {
                        "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,
                        "health": null
                      },
                      "error": null
                    }
                  },
                  "success": {
                    "summary": "A live account with its health",
                    "value": {
                      "status": "success",
                      "data": {
                        "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-09-28T20:31:11Z",
                        "seat_assigned": null,
                        "last_update_at": "2026-09-28T19:31:11.870303Z",
                        "health": {
                          "stream": "up",
                          "polls": false,
                          "last_book_read_at": "2026-09-28T19:31:11.870303Z",
                          "open_orders": 2,
                          "last_error_kind": null,
                          "last_error_at": null
                        }
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`account_not_found`: not one of the caller's linked accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "account_not_found": {
                    "summary": "Not one of the caller's accounts",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "account_not_found",
                        "message": "No linked broker account with this id",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: accounts or their status could not be read; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/instruments": {
      "get": {
        "tags": [
          "instruments"
        ],
        "summary": "Search instruments",
        "description": "Searches today's instrument list. Give `q` or at least one filter. `q` is matched literally and case-insensitively (no wildcards): exact trading symbol first, then symbol prefix, then a word prefix of the name or underlying; every word of a multi-word `q` must match. Filters are exact (case-insensitive). At most `limit` items (default 20, at most 100).",
        "operationId": "search_instruments",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Search text (at most 64 characters).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exchange",
            "in": "query",
            "description": "Exchange, e.g. `NSE`, `NFO`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument",
            "in": "query",
            "description": "Instrument type, e.g. `EQUITY`, `OPTIDX`, `FUTSTK`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expiry",
            "in": "query",
            "description": "Expiry date `YYYY-MM-DD`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "strike",
            "in": "query",
            "description": "Strike price.",
            "required": false,
            "schema": {
              "type": "number",
              "format": "double"
            }
          },
          {
            "name": "option_type",
            "in": "query",
            "description": "`CE` or `PE`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Most items to return (default 20; above 100 means 100).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matches (may be empty).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_InstrumentSearchResult"
                },
                "examples": {
                  "filters": {
                    "summary": "Filters only: NFO calls at one strike",
                    "value": {
                      "status": "success",
                      "data": {
                        "items": [],
                        "count": 0
                      },
                      "error": null
                    }
                  },
                  "success": {
                    "summary": "Search by symbol or name",
                    "value": {
                      "status": "success",
                      "data": {
                        "items": [
                          {
                            "cirrus_token": "CT:1:2:RELIANCE-EQ",
                            "exchange": "NSE",
                            "instrument": "EQUITY",
                            "exchange_token": "2885",
                            "lot_size": 1,
                            "expiry": null,
                            "strike": null,
                            "option_type": null,
                            "tick_size": 0.1,
                            "underlying_symbol": "RELIANCE",
                            "isin": "INE002A01018",
                            "freeze_qty": 81195,
                            "name": "RELIANCE",
                            "tradingsymbol": "RELIANCE",
                            "sector": "Oil Gas & Consumable Fuels",
                            "indices": [
                              "NIFTY",
                              "NIFTY100",
                              "NIFTYENERGY"
                            ],
                            "instrument_token": "CT:1:2:RELIANCE-EQ"
                          },
                          {
                            "cirrus_token": "CT:2:2:RELIANCE-A",
                            "exchange": "BSE",
                            "instrument": "EQUITY",
                            "exchange_token": "500325",
                            "lot_size": 1,
                            "expiry": null,
                            "strike": null,
                            "option_type": null,
                            "tick_size": 0.05,
                            "underlying_symbol": "RELIANCE",
                            "isin": "INE002A01018",
                            "freeze_qty": null,
                            "name": "RELIANCE",
                            "tradingsymbol": "RELIANCE",
                            "sector": "Oil Gas & Consumable Fuels",
                            "indices": [
                              "NIFTY",
                              "NIFTY100",
                              "NIFTYENERGY"
                            ],
                            "instrument_token": "CT:2:2:RELIANCE-A"
                          }
                        ],
                        "count": 2
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`invalid_request`: neither `q` nor a filter (`field`: `q`), a value too long (filters: 32 characters), `strike` not a number or `limit` not a whole number of at least 1 (`field` names the parameter), or an unreadable query string (`field`: `query`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "no_query": {
                    "summary": "Neither `q` nor a filter",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "Give `q` or at least one filter (exchange, instrument, expiry, strike, option_type)",
                        "field": "q"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`instruments_unavailable`: the instrument list is still loading; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "instruments_unavailable": {
                    "summary": "The instrument list is still loading",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "instruments_unavailable",
                        "message": "The instrument list is loading. Please retry in a minute.",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/instruments.csv": {
      "get": {
        "tags": [
          "instruments"
        ],
        "summary": "Download the instrument list (CSV)",
        "description": "Today's full instrument list as one CSV file (UTF-8, header row), gzip-compressed when the request accepts it (`Accept-Encoding: gzip`). Send the `ETag` back in `If-None-Match` (or `Last-Modified` in `If-Modified-Since`) to get `304 Not Modified` while it is unchanged; validators are the same on every server.\n\nColumns (find them by header name; new columns may be added): the instrument id (under its legacy name; the same value as `instrument_token`), `exchange`, `instrument` (type), `exchange_token`, `lot_size`, `expiry` (`YYYY-MM-DD`), `strike`, `option_type` (`CE` / `PE`), `tick_size`, `underlying_symbol`, `isin`, `freeze_qty`, `name`, `tradingsymbol`, `sector`, `indices` (`|`-separated). Empty cells mean no value; numbers may be written with a decimal point (`1.0`).",
        "operationId": "download_instruments",
        "parameters": [
          {
            "name": "If-None-Match",
            "in": "header",
            "description": "An `ETag` received earlier.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "If-Modified-Since",
            "in": "header",
            "description": "A `Last-Modified` received earlier.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file (`Content-Disposition: attachment; filename=\"instruments.csv\"`).",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`public, max-age=300`."
              },
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Version of the file (differs for the gzip encoding)."
              },
              "Last-Modified": {
                "schema": {
                  "type": "string"
                },
                "description": "When the file was published."
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "description": "Not modified: the copy the client has is current."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`instruments_unavailable`: the instrument list is still loading; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "instruments_unavailable": {
                    "summary": "The instrument list is still loading",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "instruments_unavailable",
                        "message": "The instrument list is loading. Please retry in a minute.",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/instruments/{instrument_token}": {
      "get": {
        "tags": [
          "instruments"
        ],
        "summary": "One instrument",
        "description": "The instrument with this id, from today's instrument list, else from the live instrument master (fields it lacks are null).",
        "operationId": "get_instrument",
        "parameters": [
          {
            "name": "instrument_token",
            "in": "path",
            "description": "Instrument id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The instrument.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_InstrumentRow"
                },
                "examples": {
                  "success": {
                    "summary": "An index option",
                    "value": {
                      "status": "success",
                      "data": {
                        "cirrus_token": "CT:1:6:FINNIFTY27OCT202625000CE",
                        "exchange": "NSE",
                        "instrument": "OPTIDX",
                        "exchange_token": "50319",
                        "lot_size": 60,
                        "expiry": "2026-10-27",
                        "strike": 25000,
                        "option_type": "CE",
                        "tick_size": 0.05,
                        "underlying_symbol": "FINNIFTY",
                        "isin": null,
                        "freeze_qty": 1801,
                        "name": "FINNIFTY",
                        "tradingsymbol": "FINNIFTY27OCT202625000CE",
                        "sector": null,
                        "indices": [],
                        "instrument_token": "CT:1:6:FINNIFTY27OCT202625000CE"
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`instrument_not_found`: unknown or expired instrument id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "instrument_not_found": {
                    "summary": "Unknown or expired instrument",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "instrument_not_found",
                        "message": "No instrument with this instrument_token (expired or invalid)",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: instrument lookup is temporarily unavailable; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/user/profile": {
      "get": {
        "tags": [
          "user"
        ],
        "summary": "Who am I",
        "description": "The user and the credential of this request (session, API key or partner app) with its scopes. Any valid credential may call it, whatever its scopes. Never returns a secret.",
        "operationId": "get_profile",
        "responses": {
          "200": {
            "description": "The caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_UserProfile"
                },
                "examples": {
                  "api_key": {
                    "summary": "Called with an IP-restricted API key",
                    "value": {
                      "status": "success",
                      "data": {
                        "username": "user-01M3MQZX31VE1ERX4EGEWXDXDC",
                        "auth": {
                          "kind": "api_key",
                          "key_id": "ck_tpVIaOozVzi8aEUO9yH6",
                          "name": "Reporting",
                          "scopes": [
                            "read"
                          ],
                          "ip_allowlist": [
                            "203.0.113.7"
                          ]
                        }
                      },
                      "error": null
                    }
                  },
                  "session": {
                    "summary": "Signed in to the app",
                    "value": {
                      "status": "success",
                      "data": {
                        "username": "user-01M3MQZX31VE1ERX4EGEWXDXDC",
                        "auth": {
                          "kind": "session",
                          "impersonated": false,
                          "scopes": [
                            "read",
                            "orders",
                            "triggers"
                          ]
                        }
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "No credential",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unauthorized",
                        "message": "Missing access token",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: the API key's details are temporarily unavailable; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": []
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "any"
      }
    },
    "/v1/stream": {
      "get": {
        "tags": [
          "stream"
        ],
        "summary": "Live updates (WebSocket)",
        "description": "Upgrades to a WebSocket carrying the user's live order and portfolio state and new activity-log records, as JSON text frames. Client messages are `StreamClientMessage`, server messages `StreamServerMessage` (see `x-websocket-messages`).\n\n**Authentication.** Either send the credential on the upgrade request (an `Authorization` header, as on every route), or send as the first message `{\"type\":\"auth\",\"token\":\"...\"}` within 5 s of connecting. Credentials are never read from the URL. The credential needs the `read` scope. A failed check does not answer 401/403: the upgrade succeeds and the socket is closed with code 4001. The credential is re-checked every 10 s; logout or revocation closes the stream (4001).\n\n**Messages.** Every server message has a per-connection `seq` (1, 2, 3, ...). First `hello` (user and accounts), then one `snapshot` per account and data kind, then `snapshot_done`; after that live `order_update`, `portfolio` and `activity` messages. Every event carries full state (the whole order, the whole kind), never a diff, so a missed message is repaired by the next one for the same order or kind. After a gap in `seq`, send `{\"type\":\"resync\"}` to get every snapshot again (then `snapshot_done`). If live updates cannot be set up an `error` message (`unavailable`) is sent and the stream ends: reconnect.\n\n**Heartbeat.** The server pings every 15 s and closes a connection it has heard nothing from for 45 s (code 1000).\n\n**Close codes.** 4001: credential missing, invalid, expired, revoked or without the `read` scope (or the first message was not `auth`); 4002: no `auth` message within 5 s; 1013: the client fell too far behind (reconnect for a fresh snapshot); 1001: server shutting down; 1000: idle.",
        "operationId": "open_stream",
        "responses": {
          "101": {
            "description": "Switching Protocols: the WebSocket is open."
          },
          "400": {
            "description": "Not a valid WebSocket upgrade (missing or wrong `Connection`, `Upgrade`, `Sec-WebSocket-Version` or `Sec-WebSocket-Key` header): plain text.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "426": {
            "description": "Upgrade Required: the connection cannot be upgraded (e.g. an HTTP/1.0 or proxied connection that drops the upgrade); plain text.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-websocket-messages": {
          "client": {
            "$ref": "#/components/schemas/StreamClientMessage"
          },
          "server": {
            "$ref": "#/components/schemas/StreamServerMessage"
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/activity": {
      "get": {
        "tags": [
          "activity"
        ],
        "summary": "List activity",
        "description": "One trading day (IST) of the activity log, newest first, in pages. Filters combine (all must match); comma-separated lists match any of their values. Follow `next_cursor` (same filters) for older records of the same day. Older days are read from the archive (`source`: `archive`).",
        "operationId": "list_activity",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Trading day `YYYY-MM-DD` (IST); today when absent.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account",
            "in": "query",
            "description": "Only records touching this account.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "Comma-separated `ActivityKind` values (e.g. `place,cancel`).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "Comma-separated `ActivityCategory` values (e.g. `orders,protection`).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "description": "Comma-separated `ActivityOutcome` values (e.g. `failed,partial`).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "description": "Case-insensitive text in the summary or trading symbol (at most 64 characters).",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`next_cursor` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size, at least 1 (default 50; above 200 means 200).",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_ActivityPage"
                },
                "examples": {
                  "filtered": {
                    "summary": "Only successful order records of one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "items": [
                          {
                            "id": "01M3MQZWW6BZSTR16YB6359R87",
                            "username": "user-01M3MQZWS63GTYZTS4FNMT47RV",
                            "at": "2026-09-28T19:31:11.875323958Z",
                            "kind": "place",
                            "category": "orders",
                            "source": {
                              "type": "app",
                              "name": null
                            },
                            "request_id": "01M3MQZWW3EWEM5BWG2XZRAMS3",
                            "instrument": {
                              "cirrus_token": "CT:TEST:RELIANCE",
                              "tradingsymbol": "RELIANCE-EQ",
                              "exchange": "NSE",
                              "instrument_token": "CT:TEST:RELIANCE"
                            },
                            "side": "BUY",
                            "order_type": "LIMIT",
                            "product": "DELIVERY",
                            "quantity": 1,
                            "price": 2500,
                            "trigger_price": null,
                            "summary": "Buy 1 RELIANCE-EQ at ₹2,500 (Limit) in 1 account",
                            "message": null,
                            "outcome": "ok",
                            "duration_ms": 2,
                            "accounts": [
                              {
                                "account": "P1",
                                "broker": "paper",
                                "status": "placed",
                                "order_ids": [
                                  "PAPER-1"
                                ],
                                "message": null,
                                "broker_message": null,
                                "duration_ms": 1
                              }
                            ]
                          }
                        ],
                        "next_cursor": null,
                        "source": "hot"
                      },
                      "error": null
                    }
                  },
                  "success": {
                    "summary": "Today's records, newest first",
                    "value": {
                      "status": "success",
                      "data": {
                        "items": [
                          {
                            "id": "01M3MQZWW6BZSTR16YB6359R87",
                            "username": "user-01M3MQZWS63GTYZTS4FNMT47RV",
                            "at": "2026-09-28T19:31:11.875323958Z",
                            "kind": "place",
                            "category": "orders",
                            "source": {
                              "type": "app",
                              "name": null
                            },
                            "request_id": "01M3MQZWW3EWEM5BWG2XZRAMS3",
                            "instrument": {
                              "cirrus_token": "CT:TEST:RELIANCE",
                              "tradingsymbol": "RELIANCE-EQ",
                              "exchange": "NSE",
                              "instrument_token": "CT:TEST:RELIANCE"
                            },
                            "side": "BUY",
                            "order_type": "LIMIT",
                            "product": "DELIVERY",
                            "quantity": 1,
                            "price": 2500,
                            "trigger_price": null,
                            "summary": "Buy 1 RELIANCE-EQ at ₹2,500 (Limit) in 1 account",
                            "message": null,
                            "outcome": "ok",
                            "duration_ms": 2,
                            "accounts": [
                              {
                                "account": "P1",
                                "broker": "paper",
                                "status": "placed",
                                "order_ids": [
                                  "PAPER-1"
                                ],
                                "message": null,
                                "broker_message": null,
                                "duration_ms": 1
                              }
                            ]
                          }
                        ],
                        "next_cursor": null,
                        "source": "hot"
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unreadable query string (an unknown parameter, or `limit` not a whole number): a plain-text answer, not the JSON envelope.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "`invalid_request` (`field` names the parameter: `date` not `YYYY-MM-DD` or out of range, unknown `kind` / `category` / `outcome`, `q` too long, bad `cursor`, `limit` 0), or `archive_day_too_large`: that archived day is too large to serve.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_kind": {
                    "summary": "An unknown kind is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "unknown kind `teleport`",
                        "field": "kind"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: the activity log is not available on this server, or temporarily unavailable; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/activity/{id}": {
      "get": {
        "tags": [
          "activity"
        ],
        "summary": "One activity record",
        "description": "The record with its `timeline`: every step of the orders it touched (from the order journal), oldest first. Archived records are found by the day in their id.",
        "operationId": "get_activity",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Record id (a ULID).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The record, with `timeline`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_ActivityRecord"
                },
                "examples": {
                  "success": {
                    "summary": "An order placement with its timeline",
                    "value": {
                      "status": "success",
                      "data": {
                        "id": "01M3MQZWWD5WSM33JA5AJ680C5",
                        "username": "user-01M3MQZWS7J3SMP5VGDZ3X17SS",
                        "at": "2026-09-28T19:31:11.882796667Z",
                        "kind": "place",
                        "category": "orders",
                        "source": {
                          "type": "app",
                          "name": null
                        },
                        "request_id": "01M3MQZWWAJC9KDSNW93HHA938",
                        "instrument": {
                          "cirrus_token": "CT:TEST:RELIANCE",
                          "tradingsymbol": "RELIANCE-EQ",
                          "exchange": "NSE",
                          "instrument_token": "CT:TEST:RELIANCE"
                        },
                        "side": "BUY",
                        "order_type": "LIMIT",
                        "product": "DELIVERY",
                        "quantity": 1,
                        "price": 2500,
                        "trigger_price": null,
                        "summary": "Buy 1 RELIANCE-EQ at ₹2,500 (Limit) in 1 account",
                        "message": null,
                        "outcome": "ok",
                        "duration_ms": 2,
                        "accounts": [
                          {
                            "account": "P1",
                            "broker": "paper",
                            "status": "placed",
                            "order_ids": [
                              "PAPER-1"
                            ],
                            "message": null,
                            "broker_message": null,
                            "duration_ms": 1
                          }
                        ],
                        "timeline": [
                          {
                            "at": "2026-09-28T19:31:12.992525Z",
                            "account": "P1",
                            "order_id": "PAPER-1",
                            "state": "OPEN",
                            "message": null,
                            "filled_qty": 0,
                            "average_price": null
                          },
                          {
                            "at": "2026-09-28T19:31:13.992525Z",
                            "account": "P1",
                            "order_id": "PAPER-1",
                            "state": "FILLED",
                            "message": null,
                            "filled_qty": 1,
                            "average_price": 2499.5
                          }
                        ]
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`activity_not_found`: no record with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "activity_not_found": {
                    "summary": "No record with this id",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "activity_not_found",
                        "message": "Activity not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`archive_day_too_large`: the record's archived day is too large to read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: the activity log is not available on this server, or temporarily unavailable; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          },
          {
            "partner_oauth": [
              "read"
            ]
          },
          {
            "app_session": []
          }
        ],
        "x-required-scope": "read"
      }
    },
    "/v1/postbacks": {
      "get": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "List webhooks",
        "description": "The signed-in user's webhooks (never their secrets), oldest first. Event bodies are described in the document's `webhooks` section (`order_update`, `trade`, `account_alert`, `positions`, `ping`; components `WebhookOrderUpdate`, `WebhookTrade`, `WebhookAccountAlert`, `WebhookPositions`, `WebhookPing`), with how deliveries are signed and retried.",
        "operationId": "list_webhooks",
        "responses": {
          "200": {
            "description": "The user's webhooks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_WebhookView"
                },
                "examples": {
                  "success": {
                    "summary": "The user's webhooks",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "id": "pb_01m3mqzx4p5tfpgbyqjgnz52kv",
                          "url": "http://127.0.0.1:60716/hooks/orders",
                          "events": [
                            "order_update",
                            "trade"
                          ],
                          "accounts": [
                            "P1"
                          ],
                          "description": "Order desk",
                          "enabled": true,
                          "disabled_reason": null,
                          "disabled_at": null,
                          "consecutive_failures": 0,
                          "last_success_at": null,
                          "last_failure_at": null,
                          "previous_secret_expires_at": null,
                          "secret_rotated_at": null,
                          "created_at": "2026-09-28T19:31:12.150Z",
                          "updated_at": "2026-09-28T19:31:12.150Z"
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "No credential",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unauthorized",
                        "message": "Missing access token",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      },
      "post": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "Create a webhook",
        "description": "Registers an HTTPS receiver for the chosen events (optionally only for some of the user's accounts). The signing secret is in this response only: store it now. A user may have at most 5 webhooks. Event bodies are described in the document's `webhooks` section (`order_update`, `trade`, `account_alert`, `positions`, `ping`; components `WebhookOrderUpdate`, `WebhookTrade`, `WebhookAccountAlert`, `WebhookPositions`, `WebhookPing`), with how deliveries are signed and retried.\n\nOnly the account holder, signed in themselves, can create webhooks.",
        "operationId": "create_webhook",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewWebhook"
              },
              "examples": {
                "success": {
                  "summary": "Order and trade events of one account",
                  "value": {
                    "url": "http://127.0.0.1:60716/hooks/orders",
                    "events": [
                      "order_update",
                      "trade"
                    ],
                    "accounts": [
                      "P1"
                    ],
                    "description": "Order desk"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the secret is shown only here.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_WebhookWithSecret"
                },
                "examples": {
                  "success": {
                    "summary": "Order and trade events of one account",
                    "value": {
                      "status": "success",
                      "data": {
                        "id": "pb_01m3mqzx4p5tfpgbyqjgnz52kv",
                        "url": "http://127.0.0.1:60716/hooks/orders",
                        "events": [
                          "order_update",
                          "trade"
                        ],
                        "accounts": [
                          "P1"
                        ],
                        "description": "Order desk",
                        "enabled": true,
                        "disabled_reason": null,
                        "disabled_at": null,
                        "consecutive_failures": 0,
                        "last_success_at": null,
                        "last_failure_at": null,
                        "previous_secret_expires_at": null,
                        "secret_rotated_at": null,
                        "created_at": "2026-09-28T19:31:12.150Z",
                        "updated_at": "2026-09-28T19:31:12.150Z",
                        "secret": "whsec_txDdiAC9WzSW48p9DLpz8/Y/pqIXJOzIWhiB7agVaC0=",
                        "note": "Store the secret now: it is not shown again."
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`: the body is not JSON or does not fit (unknown field, wrong type).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_field": {
                    "summary": "The secret cannot be chosen",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "malformed_json",
                        "message": "invalid request body: unknown field `secret`, expected one of `url`, `events`, `accounts`, `description`",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session (an operator acting as the user); or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "own_session_required": {
                    "summary": "An operator acting as the user cannot create webhooks",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "own_session_required",
                        "message": "Only the account holder, signed in themselves, can do this",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`webhook_limit_reached`: the user already has 5 webhooks; delete one first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`; `field` names the input: `url` (not an `https://` URL on a public host), `events` (none, unknown or `ping`), `accounts` (empty, or not the user's) or `description` (over 200 characters).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_event": {
                    "summary": "An unknown event name is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "unknown event `fills`; expected one of order_update, trade, account_alert, positions",
                        "field": "events"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/postbacks/{id}": {
      "get": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "Get a webhook",
        "description": "One webhook (never its secret): its settings and delivery health.",
        "operationId": "get_webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The webhook's `id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_WebhookView"
                },
                "examples": {
                  "success": {
                    "summary": "One webhook",
                    "value": {
                      "status": "success",
                      "data": {
                        "id": "pb_01m3mqzx4p5tfpgbyqjgnz52kv",
                        "url": "http://127.0.0.1:60716/hooks/orders",
                        "events": [
                          "order_update",
                          "trade"
                        ],
                        "accounts": [
                          "P1"
                        ],
                        "description": "Order desk",
                        "enabled": true,
                        "disabled_reason": null,
                        "disabled_at": null,
                        "consecutive_failures": 0,
                        "last_success_at": null,
                        "last_failure_at": null,
                        "previous_secret_expires_at": null,
                        "secret_rotated_at": null,
                        "created_at": "2026-09-28T19:31:12.150Z",
                        "updated_at": "2026-09-28T19:31:12.150Z"
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`webhook_not_found`: no webhook with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No such webhook",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "webhook_not_found",
                        "message": "Webhook not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      },
      "delete": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "Delete a webhook",
        "description": "Deletes the webhook; nothing more is sent to it. Only the account holder, signed in themselves, can delete webhooks.",
        "operationId": "delete_webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The webhook's `id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_DeletedWebhook"
                },
                "examples": {
                  "success": {
                    "summary": "Deleted",
                    "value": {
                      "status": "success",
                      "data": {
                        "id": "pb_01m3mqzx58t3ezceq1ecb498yv",
                        "deleted": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session (an operator acting as the user); or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`webhook_not_found`: no webhook with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "Already deleted",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "webhook_not_found",
                        "message": "Webhook not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      },
      "patch": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "Change a webhook",
        "description": "Changes only the fields sent: `url`, `events`, `accounts` (`null` = every account), `description` (`null` removes it) and `enabled`. `enabled: true` turns a webhook back on, also after it was turned off for failing (its failure count starts again). An empty body changes nothing.\n\nOnly the account holder, signed in themselves, can change webhooks.",
        "operationId": "update_webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The webhook's `id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPatch"
              },
              "examples": {
                "success": {
                  "summary": "Every account, one more event, turned off",
                  "value": {
                    "events": [
                      "order_update",
                      "trade",
                      "positions"
                    ],
                    "accounts": null,
                    "enabled": false
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The webhook after the change.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_WebhookView"
                },
                "examples": {
                  "success": {
                    "summary": "Every account, one more event, turned off",
                    "value": {
                      "status": "success",
                      "data": {
                        "id": "pb_01m3mqzx4p5tfpgbyqjgnz52kv",
                        "url": "http://127.0.0.1:60716/hooks/orders",
                        "events": [
                          "order_update",
                          "trade",
                          "positions"
                        ],
                        "accounts": null,
                        "description": "Order desk",
                        "enabled": false,
                        "disabled_reason": "disabled_by_user",
                        "disabled_at": "2026-09-28T19:31:12.156Z",
                        "consecutive_failures": 0,
                        "last_success_at": null,
                        "last_failure_at": null,
                        "previous_secret_expires_at": null,
                        "secret_rotated_at": null,
                        "created_at": "2026-09-28T19:31:12.150Z",
                        "updated_at": "2026-09-28T19:31:12.156Z"
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`: the body is not JSON or does not fit (unknown field, wrong type).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session (an operator acting as the user); or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`webhook_not_found`: no webhook with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`; `field` names the input: `url`, `events`, `accounts` or `description` (same rules as on creation).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_own_account": {
                    "summary": "Only the user's own accounts",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "`NOT-MINE` is not one of your accounts",
                        "field": "accounts"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/postbacks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "Rotate a webhook's secret",
        "description": "Issues a new signing secret, shown only in this response. For 24 hours deliveries are signed with both the new and the previous secret (one signature each in `webhook-signature`), so the receiver can switch without losing any. Only the account holder, signed in themselves, can rotate secrets.",
        "operationId": "rotate_webhook_secret",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The webhook's `id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook with its new secret (shown only here).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_WebhookWithSecret"
                },
                "examples": {
                  "success": {
                    "summary": "A new secret; the old one signs for 24 hours",
                    "value": {
                      "status": "success",
                      "data": {
                        "id": "pb_01m3mqzx58t3ezceq1ecb498yv",
                        "url": "http://127.0.0.1:60710/hooks/alerts",
                        "events": [
                          "account_alert"
                        ],
                        "accounts": null,
                        "description": null,
                        "enabled": true,
                        "disabled_reason": null,
                        "disabled_at": null,
                        "consecutive_failures": 0,
                        "last_success_at": null,
                        "last_failure_at": null,
                        "previous_secret_expires_at": "2026-09-29T19:31:12.173Z",
                        "secret_rotated_at": "2026-09-28T19:31:12.173Z",
                        "created_at": "2026-09-28T19:31:12.168Z",
                        "updated_at": "2026-09-28T19:31:12.173Z",
                        "secret": "whsec_fqwXMrqAHOadNV3Pw3Lq83azTavNzXwNNP+D8P6jU6Q=",
                        "note": "Store the secret now: it is not shown again."
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session (an operator acting as the user); or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`webhook_not_found`: no webhook with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No such webhook",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "webhook_not_found",
                        "message": "Webhook not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/postbacks/{id}/test": {
      "post": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "Send a test delivery",
        "description": "Sends one signed `ping` event (body: component `WebhookPing`) to the webhook now, even when it is turned off, and says how the receiver answered. One attempt, no retry; it is logged with the webhook's deliveries. Only the account holder, signed in themselves, can send tests.",
        "operationId": "test_webhook",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The webhook's `id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The attempt was made (check `delivered`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_WebhookTestResult"
                },
                "examples": {
                  "success": {
                    "summary": "The receiver answered 200",
                    "value": {
                      "status": "success",
                      "data": {
                        "event_id": "evt_bbde86f7815e23802cf72965f007b693",
                        "delivered": true,
                        "status_code": 200,
                        "duration_ms": 0,
                        "error_kind": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session (an operator acting as the user); or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`webhook_not_found`: no webhook with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No such webhook",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "webhook_not_found",
                        "message": "Webhook not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/postbacks/{id}/deliveries": {
      "get": {
        "tags": [
          "webhooks",
          "app_session_only"
        ],
        "summary": "List a webhook's delivery attempts",
        "description": "Every delivery attempt of the last 7 days, newest first: event, attempt number, outcome, the receiver's status and timing (never the body). Page with `limit` and `cursor`.",
        "operationId": "list_webhook_deliveries",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The webhook's `id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size, 1-200 (default 50).",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`next_cursor` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of attempts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_WebhookDeliveryPage"
                },
                "examples": {
                  "success": {
                    "summary": "The test delivery",
                    "value": {
                      "status": "success",
                      "data": {
                        "deliveries": [
                          {
                            "id": "01M3MQZX5CX39YTHPWEFADXTQN",
                            "event_id": "evt_bbde86f7815e23802cf72965f007b693",
                            "type": "ping",
                            "attempt": 1,
                            "outcome": "delivered",
                            "status_code": 200,
                            "duration_ms": 0,
                            "error_kind": null,
                            "at": "2026-09-28T19:31:12.172Z"
                          }
                        ],
                        "next_cursor": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The query string does not parse (e.g. `limit` is not a number); plain-text reply.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`webhook_not_found`: no webhook with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No such webhook",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "webhook_not_found",
                        "message": "Webhook not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `limit`): `limit` is not 1-200.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_limit": {
                    "summary": "At most 200 per page",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "limit must be 1 to 200",
                        "field": "limit"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`webhooks_disabled`: webhooks are not enabled on this server; or `service_unavailable`: the webhook store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/hooks/endpoints": {
      "get": {
        "tags": [
          "signal_urls",
          "app_session_only"
        ],
        "summary": "List signal URLs",
        "description": "The signed-in user's live signal URLs (never their secrets).",
        "operationId": "list_signal_urls",
        "responses": {
          "200": {
            "description": "Live signal URLs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_SignalUrl"
                },
                "examples": {
                  "success": {
                    "summary": "The user's live URLs",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "endpoint_id": "we_K64Mxu5q5wJHhyDd",
                          "kind": "tradingview",
                          "strategy_id": "nifty-breakout-01M3MQZX2RZXFZ4BA4K46TY12A",
                          "created_at": "2026-09-28T19:31:12.090922+00:00",
                          "has_body_secret": true
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "No credential",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unauthorized",
                        "message": "Missing access token",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: signal URLs are not enabled on this server, or their store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      },
      "post": {
        "tags": [
          "signal_urls",
          "app_session_only"
        ],
        "summary": "Issue a signal URL",
        "description": "Issues a secret URL for one strategy and provider. Give the provider the API origin followed by `path`; for TradingView also put `\"secret\": \"<body_secret>\"` in the alert message. The URL (and body secret) are shown only in this response. Issuing a new URL for the same strategy and provider revokes the previous one at once.\n\nWhat each provider sends to the URL, and every reply, is described on `POST /v1/hooks/{kind}/{secret}`. Only the account holder, signed in themselves, can issue URLs.",
        "operationId": "issue_signal_url",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IssueSignalUrlRequest"
              },
              "examples": {
                "success": {
                  "summary": "A TradingView URL (with a body secret)",
                  "value": {
                    "kind": "tradingview",
                    "strategy_id": "nifty-breakout-01M3MQZX2RZXFZ4BA4K46TY12A"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Issued; the URL is shown only here.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_IssuedSignalUrl"
                },
                "examples": {
                  "success": {
                    "summary": "A TradingView URL (with a body secret)",
                    "value": {
                      "status": "success",
                      "data": {
                        "endpoint_id": "we_K64Mxu5q5wJHhyDd",
                        "kind": "tradingview",
                        "strategy_id": "nifty-breakout-01M3MQZX2RZXFZ4BA4K46TY12A",
                        "created_at": "2026-09-28T19:31:12.090922+00:00",
                        "has_body_secret": true,
                        "path": "/v1/hooks/tradingview/wh_j3eXpOAgQQ8ZbCwZLudcszn3KWc4V1sC3rIHcXTV2Le",
                        "body_secret": "tvs_7QaFOF9HjMwawCKqUxiSl5nnIMYI4Sue",
                        "note": "Keep this URL private: anyone with it can send signals. Issuing a new one revokes this."
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`: the body is not JSON or does not fit (unknown field, unknown `kind`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_kind": {
                    "summary": "An unknown provider is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "malformed_json",
                        "message": "invalid request body: unknown variant `telegram`, expected one of `kuberhunt`, `tradingview`, `chartink`",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session; or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `strategy_id`): not 1-64 letters, digits, `-` or `_`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_strategy_id": {
                    "summary": "Strategy ids are letters, digits, - and _",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "strategy_id must be 1-64 letters, digits, '-' or '_'",
                        "field": "strategy_id"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: signal URLs are not enabled on this server, or their store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/hooks/endpoints/{endpoint_id}": {
      "delete": {
        "tags": [
          "signal_urls",
          "app_session_only"
        ],
        "summary": "Revoke a signal URL",
        "description": "Revokes the URL at once: the provider's next request gets 404.",
        "operationId": "revoke_signal_url",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "description": "The signal URL's `endpoint_id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_RevokedSignalUrl"
                },
                "examples": {
                  "success": {
                    "summary": "Revoked",
                    "value": {
                      "status": "success",
                      "data": {
                        "endpoint_id": "we_K64Mxu5q5wJHhyDd",
                        "revoked": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`endpoint_not_found`: no live signal URL with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "Already revoked",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "endpoint_not_found",
                        "message": "Webhook endpoint not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: signal URLs are not enabled on this server, or their store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/hooks/endpoints/{endpoint_id}/rotate": {
      "post": {
        "tags": [
          "signal_urls",
          "app_session_only"
        ],
        "summary": "Rotate a signal URL",
        "description": "Issues a new secret URL (and, for TradingView, a new body secret) for the same `endpoint_id`, shown only in this response. The old URL stops working at once. Only the account holder, signed in themselves, can rotate URLs.",
        "operationId": "rotate_signal_url",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "description": "The signal URL's `endpoint_id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The new URL (shown only here).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_IssuedSignalUrl"
                },
                "examples": {
                  "success": {
                    "summary": "A new URL and body secret; the old URL is dead",
                    "value": {
                      "status": "success",
                      "data": {
                        "endpoint_id": "we_K64Mxu5q5wJHhyDd",
                        "kind": "tradingview",
                        "strategy_id": "nifty-breakout-01M3MQZX2RZXFZ4BA4K46TY12A",
                        "created_at": "2026-09-28T19:31:12.102166+00:00",
                        "has_body_secret": true,
                        "path": "/v1/hooks/tradingview/wh_PcykPFU3b0Mb1P1W7tKaTqbO1VHULzPXd92rqxKZL8l",
                        "body_secret": "tvs_VCszf9naN0LnUt2SujREKjNTtsac8dHg",
                        "note": "Give the provider this new URL now: the old one no longer works. It is shown only once."
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session; or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`endpoint_not_found`: no live signal URL with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "A revoked URL",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "endpoint_not_found",
                        "message": "Webhook endpoint not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: signal URLs are not enabled on this server, or their store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/hooks/endpoints/{endpoint_id}/deliveries": {
      "get": {
        "tags": [
          "signal_urls",
          "app_session_only"
        ],
        "summary": "List what a signal URL received",
        "description": "Every request the URL received in the last 7 days, newest first: when, the outcome in one word, why in plain words, the orders it placed and the status the provider was answered with (never the payload). Page with `limit` and `cursor`.",
        "operationId": "list_signal_url_deliveries",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "description": "The signal URL's `endpoint_id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size, at least 1 (default 50; above 200 counts as 200).",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`next_cursor` of the previous page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_SignalUrlDeliveryPage"
                },
                "examples": {
                  "success": {
                    "summary": "Newest first: rate limited, two duplicates, placed",
                    "value": {
                      "status": "success",
                      "data": {
                        "items": [
                          {
                            "delivery_id": "01M3MQZX4AT9WSGE09S4CWXHSX",
                            "at": "2026-09-28T19:31:12.138Z",
                            "provider": "chartink",
                            "outcome": "rate_limited",
                            "reason": "too many alerts in a short time; extra ones were refused",
                            "orders_placed": 0,
                            "order_ids": [],
                            "http_status": 429,
                            "request_id": "01M3MQZX48WJ21J1E118EVG2RD"
                          },
                          {
                            "delivery_id": "01M3MQZX48QJW2DXVP6XD85QRZ",
                            "at": "2026-09-28T19:31:12.136Z",
                            "provider": "chartink",
                            "outcome": "duplicate",
                            "reason": "the same alert arrived twice; the copy was skipped",
                            "orders_placed": 0,
                            "order_ids": [],
                            "http_status": 200,
                            "request_id": "01M3MQZX46RRRBQ3D201CTZH6P"
                          },
                          {
                            "delivery_id": "01M3MQZX46B5BP5AXHF8YS4HE0",
                            "at": "2026-09-28T19:31:12.134Z",
                            "provider": "chartink",
                            "outcome": "duplicate",
                            "reason": "the same alert arrived twice; the copy was skipped",
                            "orders_placed": 0,
                            "order_ids": [],
                            "http_status": 200,
                            "request_id": "01M3MQZX45JJPVMR5GRH6Z1T77"
                          },
                          {
                            "delivery_id": "01M3MQZX455MFC6KCR2TWPM699",
                            "at": "2026-09-28T19:31:12.133Z",
                            "provider": "chartink",
                            "outcome": "placed",
                            "reason": null,
                            "orders_placed": 1,
                            "order_ids": [
                              "PAPER-1"
                            ],
                            "http_status": 200,
                            "request_id": "01M3MQZX40EW38WXHT3CDF1KAE"
                          }
                        ],
                        "next_cursor": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The query string does not parse (unknown parameter, `limit` not a number); plain-text reply.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`endpoint_not_found`: no live signal URL with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No such signal URL",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "endpoint_not_found",
                        "message": "Webhook endpoint not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`; `field` is `limit` (0) or `cursor` (not a cursor this route gave).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_cursor": {
                    "summary": "A cursor this route did not give",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "invalid cursor",
                        "field": "cursor"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: signal URLs are not enabled on this server, or their store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/hooks/endpoints/{endpoint_id}/test": {
      "post": {
        "tags": [
          "signal_urls",
          "app_session_only"
        ],
        "summary": "Dry-run a signal",
        "description": "Runs a payload through the same checks, parsing and strategy rules as a real delivery to this URL and says which orders it would place, without placing anything or touching any state (duplicate / sequence checks, daily entry counts, the URL's rate limit, the activity and delivery logs). Send the provider's payload as the body (for Kuberhunt, with its signature headers to check the signature too); an empty body checks a sample alert. Problems with the payload are reported in `errors` with 200, not as HTTP errors.",
        "operationId": "test_signal_url",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "description": "The signal URL's `endpoint_id`.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kuberhunt-Signature",
            "in": "header",
            "description": "Kuberhunt only: `v1=<hex HMAC-SHA256>`; without it the signature is not checked (a warning says so).",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "X-Kuberhunt-Timestamp",
            "in": "header",
            "description": "Kuberhunt only: Unix seconds the signature was made at.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "description": "The payload the provider would send (optional).",
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/TradingViewAlert"
                  },
                  {
                    "$ref": "#/components/schemas/ChartinkAlert"
                  },
                  {
                    "$ref": "#/components/schemas/KuberhuntEvent"
                  }
                ],
                "description": "What the provider sends, by the URL's `kind`: `tradingview` -> `TradingViewAlert` (the alert's message as JSON, with the body secret), `chartink` -> `ChartinkAlert` (Chartink's scanner alert as it sends it), `kuberhunt` -> `KuberhuntEvent` (signed with `X-Kuberhunt-Signature` / `X-Kuberhunt-Timestamp`)."
              },
              "examples": {
                "would_place": {
                  "summary": "A Chartink alert would place one order",
                  "value": {
                    "stocks": "TESTSU",
                    "trigger_prices": "100.03",
                    "triggered_at": "9:30 am",
                    "scan_name": "Breakouts",
                    "alert_name": "Breakout alert"
                  }
                },
                "wrong_secret": {
                  "summary": "A TradingView alert with the wrong body secret would be refused",
                  "value": {
                    "type": "entry",
                    "secret": "tvs_not_the_secret"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "What a real delivery would do (check `valid`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_SignalDryRun"
                },
                "examples": {
                  "would_place": {
                    "summary": "A Chartink alert would place one order",
                    "value": {
                      "status": "success",
                      "data": {
                        "valid": true,
                        "errors": [],
                        "warnings": [],
                        "would_place": [
                          {
                            "account": "P1",
                            "symbol": "TESTSU-EQ",
                            "exchange": "NSE",
                            "side": "BUY",
                            "qty": 3,
                            "order_type": "LIMIT",
                            "price": 100.55,
                            "product": "MIS"
                          }
                        ]
                      },
                      "error": null
                    }
                  },
                  "wrong_secret": {
                    "summary": "A TradingView alert with the wrong body secret would be refused",
                    "value": {
                      "status": "success",
                      "data": {
                        "valid": false,
                        "errors": [
                          "the alert's secret did not match this strategy"
                        ],
                        "warnings": [],
                        "would_place": []
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`endpoint_not_found`: no live signal URL with this id for the caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "No such signal URL",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "endpoint_not_found",
                        "message": "Webhook endpoint not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: signal URLs are not enabled on this server, or the URL or strategy store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/hooks/{kind}/{secret}": {
      "post": {
        "tags": [
          "signal_urls"
        ],
        "summary": "Receive a provider signal",
        "description": "The URL a provider (TradingView, Chartink, Kuberhunt) calls; no `Authorization`: the secret in the URL is the credential (plus the body secret for TradingView and the signature for Kuberhunt). The body depends on `kind` (see `TradingViewAlert`, `ChartinkAlert`, `KuberhuntEvent`). Orders are placed as the URL's owner, following the strategy's settings.\n\nReplies are not the REST envelope: they are made for the providers, which only look at the status. 200 means received (whatever it came to: see the URL's deliveries and the activity log); only 503 asks for the same delivery again. Each URL has its own rate limit, shown in `X-RateLimit-Limit` / `X-RateLimit-Remaining` on every reply once the URL is known.",
        "operationId": "receive_signal",
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "description": "The provider the URL was issued for.",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/SignalProvider"
            }
          },
          {
            "name": "secret",
            "in": "path",
            "description": "The URL secret (`wh_...`), from `path` when the URL was issued.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kuberhunt-Signature",
            "in": "header",
            "description": "Kuberhunt: `v1=<hex HMAC-SHA256>` of `{timestamp}.{raw body}`, keyed with the strategy's Kuberhunt webhook secret.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          {
            "name": "X-Kuberhunt-Timestamp",
            "in": "header",
            "description": "Kuberhunt: Unix seconds, within 300 s of now.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "description": "The provider's payload, by `kind`.",
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/TradingViewAlert"
                  },
                  {
                    "$ref": "#/components/schemas/ChartinkAlert"
                  },
                  {
                    "$ref": "#/components/schemas/KuberhuntEvent"
                  }
                ],
                "description": "What the provider sends, by the URL's `kind`: `tradingview` -> `TradingViewAlert` (the alert's message as JSON, with the body secret), `chartink` -> `ChartinkAlert` (Chartink's scanner alert as it sends it), `kuberhunt` -> `KuberhuntEvent` (signed with `X-Kuberhunt-Signature` / `X-Kuberhunt-Timestamp`)."
              },
              "examples": {
                "chartink_alert": {
                  "summary": "A Chartink alert placed its orders",
                  "value": {
                    "stocks": "TESTSU",
                    "trigger_prices": "100.03",
                    "triggered_at": "9:20 am",
                    "scan_name": "Breakouts",
                    "alert_name": "Breakout alert"
                  }
                },
                "duplicate": {
                  "summary": "The same alert again: skipped",
                  "value": {
                    "stocks": "TESTSU",
                    "trigger_prices": "100.03",
                    "triggered_at": "9:20 am",
                    "scan_name": "Breakouts",
                    "alert_name": "Breakout alert"
                  }
                },
                "kuberhunt_event": {
                  "summary": "A signed Kuberhunt entry placed its order",
                  "value": {
                    "event": "reco.activated",
                    "event_id": "evt-01M3MQZX4008JKRYAEEQFTQZE6",
                    "event_seq": 1,
                    "timestamp": "2026-09-28T19:31:12.128754+00:00",
                    "reco": {
                      "reco_id": "reco-01M3MQZX40MZ8DY1GX7FKRWR35",
                      "instrument_token": "CT:TEST:RELIANCE",
                      "action": "BUY",
                      "product": "INTRADAY",
                      "lower_price": 2490,
                      "entry_price": 2500
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Received (also when nothing was placed: duplicates, paused strategies, unreadable payloads and failed Kuberhunt signature checks are answered 200 so the provider does not retry).",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer",
                  "format": "int32",
                  "minimum": 0
                },
                "description": "Requests this URL may receive per window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer",
                  "format": "int32",
                  "minimum": 0
                },
                "description": "Requests left in the window."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalAck",
                  "description": "Received (see `SignalAckMessage` for every message)."
                },
                "examples": {
                  "chartink_alert": {
                    "summary": "A Chartink alert placed its orders",
                    "value": {
                      "message": "Webhook received"
                    }
                  },
                  "duplicate": {
                    "summary": "The same alert again: skipped",
                    "value": {
                      "message": "Duplicate"
                    }
                  },
                  "kuberhunt_event": {
                    "summary": "A signed Kuberhunt entry placed its order",
                    "value": {
                      "message": "Webhook received"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The TradingView body secret is missing or wrong (`SignalForbidden`), or the URL's owner is not enabled for order management (`oms_not_enabled`, REST envelope).",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SignalForbidden"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ],
                  "description": "`SignalForbidden` (`Invalid secret`: the TradingView body secret is missing or wrong), or the standard error envelope with `error.code` `oms_not_enabled` (the URL's owner is not enabled for order management)."
                },
                "examples": {
                  "wrong_body_secret": {
                    "summary": "A TradingView alert with the wrong body secret",
                    "value": {
                      "message": "Invalid secret"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`Unknown webhook`: unknown, revoked or malformed URL (also when signal URLs are off on this server).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalError",
                  "description": "Before the URL's strategy is known."
                },
                "examples": {
                  "unknown_url": {
                    "summary": "An unknown or revoked URL",
                    "value": {
                      "status": "error",
                      "message": "Unknown webhook"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate limited; retry in {n} ms`: the URL's rate limit is reached; nothing was processed.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                },
                "description": "Seconds to wait."
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer",
                  "format": "int32",
                  "minimum": 0
                },
                "description": "Requests this URL may receive per window."
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer",
                  "format": "int32",
                  "minimum": 0
                },
                "description": "Always 0."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalError",
                  "description": "Before the URL's strategy is known."
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Over the URL's rate limit",
                    "value": {
                      "status": "error",
                      "message": "rate limited; retry in 992 ms"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable; send the same delivery again later.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SignalRetry"
                    },
                    {
                      "$ref": "#/components/schemas/SignalError"
                    }
                  ],
                  "description": "Send the same delivery again later: `SignalRetry` once the URL is known, `SignalError` (`temporarily unavailable`) when the URL could not be looked up."
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/kuberhunt/execute-signal/{token}": {
      "post": {
        "tags": [
          "signal_urls"
        ],
        "summary": "Receive a Kuberhunt signal (pre-v1 URL)",
        "description": "The pre-v1 Kuberhunt URL, kept working until its sunset date for strategies that have not moved: issue a signal URL (`POST /v1/hooks/endpoints`, `kind: kuberhunt`) and give Kuberhunt that instead. Same body, headers and handling as `POST /v1/hooks/kuberhunt/{secret}`. The URL is retired for good (410) once the strategy's new URL has received an accepted delivery, and for every strategy after the sunset date. Replies carry `Deprecation: true` and `Sunset` headers.",
        "operationId": "receive_kuberhunt_signal_legacy",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "description": "The token of the pre-v1 URL.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kuberhunt-Signature",
            "in": "header",
            "description": "`v1=<hex HMAC-SHA256>` of `{timestamp}.{raw body}`, keyed with the strategy's Kuberhunt webhook secret.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kuberhunt-Timestamp",
            "in": "header",
            "description": "Unix seconds, within 300 s of now.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "A Kuberhunt event.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KuberhuntEvent",
                "description": "A Kuberhunt event, signed with `X-Kuberhunt-Signature` / `X-Kuberhunt-Timestamp`."
              },
              "examples": {
                "invalid_token": {
                  "summary": "An invalid token is acknowledged",
                  "value": {
                    "event": "reco.pending",
                    "event_id": "evt-01M3MQZX3D8S7PVE50R620Z1ZH",
                    "event_seq": 2,
                    "timestamp": "2026-09-28T19:31:12.109950+00:00",
                    "reco": {
                      "reco_id": "reco-01M3MQZX3DXV28Z839ZA2W2H7W",
                      "instrument_token": "CT:TEST:RELIANCE",
                      "action": "BUY",
                      "product": "INTRADAY",
                      "lower_price": 2490,
                      "entry_price": 2500
                    }
                  }
                },
                "success": {
                  "summary": "A signed entry, before the strategy moved",
                  "value": {
                    "event": "reco.activated",
                    "event_id": "evt-01M3MQZX3DWDASD14A3P6GB38X",
                    "event_seq": 1,
                    "timestamp": "2026-09-28T19:31:12.109937+00:00",
                    "reco": {
                      "reco_id": "reco-01M3MQZX3DHPE3JE8APQXGCQGA",
                      "instrument_token": "CT:TEST:RELIANCE",
                      "action": "BUY",
                      "product": "INTRADAY",
                      "lower_price": 2490,
                      "entry_price": 2500
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Received (as on the v1 URL); `Invalid ID` when the token is invalid or expired.",
            "headers": {
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "`true`."
              },
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "When the URL stops working (HTTP date)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalAck",
                  "description": "Received (see `SignalAckMessage` for every message)."
                },
                "examples": {
                  "invalid_token": {
                    "summary": "An invalid token is acknowledged",
                    "value": {
                      "message": "Invalid ID"
                    }
                  },
                  "success": {
                    "summary": "A signed entry, before the strategy moved",
                    "value": {
                      "message": "Webhook received"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The URL's owner is not enabled for order management (`oms_not_enabled`, REST envelope).",
            "headers": {
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "`true`."
              },
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "When the URL stops working (HTTP date)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SignalForbidden"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ],
                  "description": "`SignalForbidden` (`Invalid secret`: the TradingView body secret is missing or wrong), or the standard error envelope with `error.code` `oms_not_enabled` (the URL's owner is not enabled for order management)."
                }
              }
            }
          },
          "404": {
            "description": "Pre-v1 URLs are not served by this server (empty body)."
          },
          "410": {
            "description": "Retired: issue a new URL for the strategy. Without the deprecation headers once the sunset date has passed.",
            "headers": {
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "`true`."
              },
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "When the URL stops working (HTTP date)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalRetired",
                  "description": "The URL is retired: issue a new one for the strategy."
                },
                "examples": {
                  "retired": {
                    "summary": "Retired once the strategy's new URL received a delivery",
                    "value": {
                      "message": "This URL has been retired. Issue a new one for the strategy in the app."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate limited; retry in {n} ms`: the strategy's rate limit is reached; nothing was processed.",
            "headers": {
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "`true`."
              },
              "Retry-After": {
                "schema": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0
                },
                "description": "Seconds to wait."
              },
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "When the URL stops working (HTTP date)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalError",
                  "description": "Before the URL's strategy is known."
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable; send the same delivery again later.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SignalRetry"
                    },
                    {
                      "$ref": "#/components/schemas/SignalError"
                    }
                  ],
                  "description": "Send the same delivery again later: `SignalRetry` once the URL is known, `SignalError` (`temporarily unavailable`) when the URL could not be looked up."
                }
              }
            }
          }
        },
        "deprecated": true,
        "security": []
      }
    },
    "/v1/api-keys": {
      "get": {
        "tags": [
          "api_keys",
          "app_session_only"
        ],
        "summary": "List API keys",
        "description": "The signed-in user's active API keys (revoked ones are not listed). Secrets are never returned.",
        "operationId": "list_api_keys",
        "responses": {
          "200": {
            "description": "Active keys, oldest first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_ApiKeyView"
                },
                "examples": {
                  "success": {
                    "summary": "The user's active keys",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "key_id": "ck_MpGKDrd64Jc2XT2CyQGW",
                          "name": "Trading bot",
                          "scopes": [
                            "read",
                            "orders"
                          ],
                          "ip_allowlist": [
                            "203.0.113.7"
                          ],
                          "created_at": "2026-09-28T19:31:11.878729+00:00",
                          "last_used_at": null
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "No credential",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unauthorized",
                        "message": "Missing access token",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: API keys are not enabled on this server, or the key store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      },
      "post": {
        "tags": [
          "api_keys",
          "app_session_only"
        ],
        "summary": "Create an API key",
        "description": "Creates a long-lived API key with the chosen scopes (and optionally an IP allowlist). The secret is in this response only: store it now. Authenticate with `Authorization: token <key_id>:<api_secret>`. At most 10 keys may be active at once.\n\nOnly the account holder, signed in themselves, can create keys (an operator acting as the user gets 403 `own_session_required`).",
        "operationId": "create_api_key",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewApiKey"
              },
              "examples": {
                "success": {
                  "summary": "A key for reads and orders from one IP",
                  "value": {
                    "name": "Trading bot",
                    "scopes": [
                      "read",
                      "orders"
                    ],
                    "ip_allowlist": [
                      "203.0.113.7"
                    ]
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created; the secret is shown only here.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_CreatedApiKey"
                },
                "examples": {
                  "success": {
                    "summary": "A key for reads and orders from one IP",
                    "value": {
                      "status": "success",
                      "data": {
                        "key_id": "ck_MpGKDrd64Jc2XT2CyQGW",
                        "name": "Trading bot",
                        "scopes": [
                          "read",
                          "orders"
                        ],
                        "ip_allowlist": [
                          "203.0.113.7"
                        ],
                        "created_at": "2026-09-28T19:31:11.878729+00:00",
                        "last_used_at": null,
                        "api_secret": "cs_9vnItUrl5NTPwetZAFJRnRRJup9U5KC8lsHvSmu8",
                        "note": "Store the secret now: it is not shown again."
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`: the body is not JSON or does not fit (unknown field, unknown scope, wrong type).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_scope": {
                    "summary": "An unknown scope is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "malformed_json",
                        "message": "invalid request body: unknown variant `admin`, expected one of `read`, `orders`, `triggers`",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the account holder's own session; or `forbidden` (see the standard 403).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "own_session_required": {
                    "summary": "An operator acting as the user cannot create keys",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "own_session_required",
                        "message": "Only the account holder, signed in themselves, can do this",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `api_key`): name not 1-64 characters, no scope, more than 20 or an invalid IP address, or 10 keys already active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "no_scope": {
                    "summary": "A key needs at least one scope",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "choose at least one scope",
                        "field": "api_key"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: API keys are not enabled on this server, or the key store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/api-keys/{key_id}": {
      "delete": {
        "tags": [
          "api_keys",
          "app_session_only"
        ],
        "summary": "Revoke an API key",
        "description": "Revokes the key at once: requests with it are refused from now on (on every server within a few seconds at most).",
        "operationId": "revoke_api_key",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "description": "The key's `key_id` (`ck_...`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_RevokedApiKey"
                },
                "examples": {
                  "success": {
                    "summary": "Revoked",
                    "value": {
                      "status": "success",
                      "data": {
                        "key_id": "ck_MpGKDrd64Jc2XT2CyQGW",
                        "revoked": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`api_key_not_found`: no active key with this id for the caller (unknown, another user's, or already revoked).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_found": {
                    "summary": "Already revoked",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "api_key_not_found",
                        "message": "API key not found",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: API keys are not enabled on this server, or the key store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/partner-apps": {
      "get": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "List your partner apps",
        "description": "The partner apps the signed-in user registered, oldest first, disabled ones included (`disabled: true`). Client secrets are never shown again.",
        "operationId": "list_partner_apps",
        "responses": {
          "200": {
            "description": "The user's apps.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_PartnerApp"
                },
                "examples": {
                  "success": {
                    "summary": "The user's apps",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "client_id": "cp_YtJe2ihlan6rj5LcW7KI",
                          "owner": "user-01M3NVXMEG6YJNY2F10FCRF2Q9",
                          "name": "Charts Co",
                          "verified": false,
                          "logo_url": "https://partner.example/logo.png",
                          "redirect_uris": [
                            "https://partner.example/callback"
                          ],
                          "scopes": [
                            "read",
                            "orders"
                          ],
                          "created_at": "2026-09-29T05:59:06.498541+00:00",
                          "disabled": false
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unavailable": {
                    "summary": "Partner access is off on this server",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "service_unavailable",
                        "message": "Partner access is not enabled on this server",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      },
      "post": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "Register a partner app",
        "description": "Registers an OAuth client owned by the signed-in user (at most 10 active apps per user). The response carries `client_secret` once: store it now, it cannot be shown again. New apps are unverified.",
        "operationId": "create_partner_app",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewPartnerApp"
              },
              "examples": {
                "success": {
                  "summary": "Registered; the client secret is shown once",
                  "value": {
                    "name": "Charts Co",
                    "redirect_uris": [
                      "https://partner.example/callback"
                    ],
                    "scopes": [
                      "read",
                      "orders"
                    ],
                    "logo_url": "https://partner.example/logo.png"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Registered; `client_secret` is shown only here.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_RegisteredPartnerApp"
                },
                "examples": {
                  "success": {
                    "summary": "Registered; the client secret is shown once",
                    "value": {
                      "status": "success",
                      "data": {
                        "client_id": "cp_YtJe2ihlan6rj5LcW7KI",
                        "owner": "user-01M3NVXMEG6YJNY2F10FCRF2Q9",
                        "name": "Charts Co",
                        "verified": false,
                        "logo_url": "https://partner.example/logo.png",
                        "redirect_uris": [
                          "https://partner.example/callback"
                        ],
                        "scopes": [
                          "read",
                          "orders"
                        ],
                        "created_at": "2026-09-29T05:59:06.498541+00:00",
                        "disabled": false,
                        "client_secret": "cps_hXhW1Bnl4McDJuAMpoGqQVEYPG6b4We9lATUXNKJ7CqigI1y",
                        "note": "Store the client secret now: it is not shown again."
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`: not JSON, an unknown field, or an unknown scope name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_scope": {
                    "summary": "An unknown scope name is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "malformed_json",
                        "message": "invalid request body: unknown variant `admin`, expected one of `read`, `orders`, `triggers`",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: only the account holder, signed in themselves, can register apps; `forbidden`: not an app session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: bad name (1-80 characters), redirect URIs (1-10, https or localhost, no fragment) or `logo_url` (https), or the 10 active apps limit is reached; `invalid_scope`: no scope chosen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_redirect_uri": {
                    "summary": "A plain-HTTP redirect URI (not localhost) is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "redirect URI `http://partner.example/cb` must be https (http only for localhost), without a fragment",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/partner-apps/{client_id}": {
      "delete": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "Disable a partner app",
        "description": "Disables one of the user's own apps: every token issued to it stops working at once, for every user who connected it. Cannot be undone.",
        "operationId": "disable_partner_app",
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "description": "The app's client id (`cp_...`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Disabled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_DisabledPartnerApp"
                },
                "examples": {
                  "success": {
                    "summary": "Disabled; its tokens stop working",
                    "value": {
                      "status": "success",
                      "data": {
                        "client_id": "cp_YtJe2ihlan6rj5LcW7KI",
                        "disabled": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`unknown_app`: no active app with this client id owned by the user (unknown, someone else's, or already disabled).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_app": {
                    "summary": "Already disabled (or not the user's app)",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unknown_app",
                        "message": "No such active app of yours",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/partner-apps/{client_id}/rotate-secret": {
      "post": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "Rotate a partner app's client secret",
        "description": "Issues a new client secret (shown once). The previous secret keeps working until `previous_secret_expires_at` (24 hours), so the partner can roll the new one out without downtime; rotating again replaces it. Own session only.",
        "operationId": "rotate_partner_app_secret",
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "description": "The app's client id (`cp_...`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_RotatedPartnerSecret"
                },
                "examples": {
                  "success": {
                    "summary": "New secret; the old one works for 24 hours",
                    "value": {
                      "status": "success",
                      "data": {
                        "client_id": "cp_ddSuxziFxtMzFwliLeK7",
                        "client_secret": "cps_MOIPAboqpyrIceK6zY3QpdbtBbZMqbhlorqoAcLY4ysPBJCb",
                        "previous_secret_expires_at": "2026-09-30T05:59:06Z"
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: not the user's own session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`unknown_app`: no such active app of yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_app": {
                    "summary": "Not an active app of the user",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unknown_app",
                        "message": "No such active app of yours",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off or temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/oauth/consent": {
      "get": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "Check an authorization request",
        "description": "Step 1 of the authorization code flow, called by the app's consent screen with the query the partner sent the user there with. Checks the app, the redirect URI and the scopes, and returns what to show the user. Other query parameters (`state`, `code_challenge`, ...) are ignored here; pass them to `POST /v1/oauth/authorize` once the user approves.\n\nShow any error to the user; never redirect on an error (the redirect URI is not trusted until it matched).",
        "operationId": "get_oauth_consent",
        "parameters": [
          {
            "name": "client_id",
            "in": "query",
            "description": "The partner app's client id.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "description": "One of the app's registered redirect URIs, exactly.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "description": "Requested scopes, space separated (`read`, `orders`, `triggers`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "What the consent screen shows.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_OAuthConsent"
                },
                "examples": {
                  "success": {
                    "summary": "What the consent screen shows",
                    "value": {
                      "status": "success",
                      "data": {
                        "client_id": "cp_XwdEn1dFZHLEjiQdFZrN",
                        "name": "Charts Co",
                        "logo_url": "https://partner.example/logo.png",
                        "verified": false,
                        "scopes": [
                          "read",
                          "orders"
                        ]
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`client_id`, `redirect_uri` or `scope` is missing (plain-text body).",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`unknown_app`: unknown or disabled partner app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_app": {
                    "summary": "Unknown or disabled app",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "unknown_app",
                        "message": "Unknown or disabled partner app",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: `redirect_uri` is not registered for the app; `invalid_scope`: no scope, an unknown scope, or one the app may not request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "scope_not_allowed": {
                    "summary": "A scope the app may not request",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_scope",
                        "message": "this app may not request `triggers`",
                        "field": null
                      }
                    }
                  },
                  "unregistered_redirect_uri": {
                    "summary": "The redirect URI is not registered for the app",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "redirect_uri is not registered for this app",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/oauth/authorize": {
      "post": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "Approve an authorization request",
        "description": "Step 2: the user approved on the consent screen. Issues a single-use authorization code (valid 60 seconds) bound to the app, the redirect URI, the scopes and the PKCE challenge (`S256` only), and returns the URL to send the browser to: `redirect_uri` with `code` and, when given, `state` appended to its query. The partner then exchanges the code at `POST /v1/oauth/token`.",
        "operationId": "authorize_partner",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthAuthorizeRequest"
              },
              "examples": {
                "success": {
                  "summary": "Approved: send the browser to the redirect URL",
                  "value": {
                    "client_id": "cp_XwdEn1dFZHLEjiQdFZrN",
                    "redirect_uri": "https://partner.example/callback",
                    "scope": "read orders",
                    "state": "af0ifjsldkj",
                    "code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
                    "code_challenge_method": "S256"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Approved; send the browser to `redirect_url`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_OAuthAuthorizeResponse"
                },
                "examples": {
                  "success": {
                    "summary": "Approved: send the browser to the redirect URL",
                    "value": {
                      "status": "success",
                      "data": {
                        "redirect_url": "https://partner.example/callback?code=oc_kKvlHo8I44VhkZzyfq28JnXWS2NjrIp05txf7DFj&state=af0ifjsldkj"
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`malformed_json`: not JSON, an unknown field or a missing one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`own_session_required`: only the account holder, signed in themselves, can connect apps; `forbidden`: not an app session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "`unknown_app`: unknown or disabled partner app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request`: PKCE missing or not `S256` (the challenge must be 43 base64url characters), or `redirect_uri` not registered; `invalid_scope`: no scope, an unknown scope, or one the app may not request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "pkce_required": {
                    "summary": "PKCE other than S256 is refused",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "PKCE with code_challenge_method=S256 is required",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/oauth/token": {
      "post": {
        "tags": [
          "partners"
        ],
        "summary": "Exchange a code or refresh token for tokens",
        "description": "The partner's server-to-server token endpoint (RFC 6749). No API credential: the client authenticates with `client_id` + `client_secret` in the body or with HTTP Basic.\n\n- `grant_type=authorization_code`: exchanges the code from the redirect (single use, valid 60 seconds) with the same `redirect_uri` and the PKCE `code_verifier`.\n- `grant_type=refresh_token`: rotates the refresh token. Each refresh token works once; presenting a used one again revokes the whole connection (a theft signal), except within 30 seconds of its rotation, which returns the same new pair (so concurrent refreshes are safe).\n\nAccess tokens last one day (`expires_in: 86400`), refresh tokens 90 days. Responses (success and error) are not the usual envelope: success is the RFC 6749 token response, errors are `{\"error\", \"error_description\"}`. Every response carries `Cache-Control: no-store`. After too many failed client or grant checks from one source (counted with failed API-key attempts), requests get 429 `slow_down` with `Retry-After` until the window is over.",
        "operationId": "issue_oauth_token",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "description": "Optional HTTP Basic client authentication: `Basic base64(client_id:client_secret)`.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "requestBody": {
          "description": "Form-encoded (`application/x-www-form-urlencoded`, per RFC 6749) or JSON (when `Content-Type` is `application/json`).",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthTokenRequest"
              },
              "examples": {
                "authorization_code": {
                  "summary": "Exchange a code (PKCE)",
                  "value": {
                    "grant_type": "authorization_code",
                    "code": "oc_3zb5bRr1InWe3ipR7EXinezj5kpxNWDpk9piRJNB",
                    "redirect_uri": "https://partner.example/callback",
                    "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
                    "client_id": "cp_3Oq3YXcuepv3Qx5Z2iC2",
                    "client_secret": "cps_dG69y0yLbVBxwXqsWbWbrQk1aP0sEuT7mYw2HcN4vZ8LxJfR"
                  }
                },
                "refresh_token": {
                  "summary": "Refresh token rotated: new access and refresh tokens",
                  "value": {
                    "grant_type": "refresh_token",
                    "refresh_token": "pr_GWiBQeI7nOqJt9PoEovV8T2Nr82NA1jXAJJVHzUG9CFvpK6heN2TmZ76",
                    "client_id": "cp_r4H24O62tTWUrB6ttGyg",
                    "client_secret": "cps_4lr6MVESW0nwdBnkggME0pmsik7MkCaWih0akqujmPs7yHON"
                  }
                }
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/OAuthTokenRequest"
              },
              "examples": {
                "authorization_code": {
                  "summary": "Exchange a code (PKCE)",
                  "value": {
                    "grant_type": "authorization_code",
                    "code": "oc_3zb5bRr1InWe3ipR7EXinezj5kpxNWDpk9piRJNB",
                    "redirect_uri": "https://partner.example/callback",
                    "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
                    "client_id": "cp_3Oq3YXcuepv3Qx5Z2iC2",
                    "client_secret": "cps_dG69y0yLbVBxwXqsWbWbrQk1aP0sEuT7mYw2HcN4vZ8LxJfR"
                  }
                },
                "refresh_token": {
                  "summary": "Rotate a refresh token",
                  "value": {
                    "grant_type": "refresh_token",
                    "refresh_token": "pr_osYL5rbnTCReFsHjMztYb2B4hTERl1EKUfZTM1sNvUT0pwXPpsaTWNyu",
                    "client_id": "cp_3Oq3YXcuepv3Qx5Z2iC2",
                    "client_secret": "cps_dG69y0yLbVBxwXqsWbWbrQk1aP0sEuT7mYw2HcN4vZ8LxJfR"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Tokens issued.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`no-store`."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthTokenResponse"
                },
                "examples": {
                  "authorization_code": {
                    "summary": "Code exchanged for an access and a refresh token",
                    "value": {
                      "access_token": "pa_pyoxfMeCpLKlvksr5Io8XkG7z5ZaKnLz3QEF9m2nuyECcwr2",
                      "token_type": "Bearer",
                      "expires_in": 86400,
                      "refresh_token": "pr_GWiBQeI7nOqJt9PoEovV8T2Nr82NA1jXAJJVHzUG9CFvpK6heN2TmZ76",
                      "scope": "read orders"
                    }
                  },
                  "refresh_token": {
                    "summary": "Refresh token rotated: new access and refresh tokens",
                    "value": {
                      "access_token": "pa_Mn1gAb1cljCkrXUWf3VEAMaGKxmxFx2NoK33lLZ4Zz1nkhI9",
                      "token_type": "Bearer",
                      "expires_in": 86400,
                      "refresh_token": "pr_qKIa3tl8tPdlC9ukkFwGyRgEJJ4GvZbF4YZpj5mbTMm9rNwCRfG3VBAo",
                      "scope": "read orders"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: unreadable body or a missing field (`code`, `redirect_uri`, `code_verifier`, `refresh_token`). `unsupported_grant_type`: `grant_type` missing or not `authorization_code` / `refresh_token`. `invalid_grant`: the code is invalid, expired or already used, was issued to another client or `redirect_uri`, or `code_verifier` does not match; the refresh token is invalid, already used, expired, or the user revoked the connection.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`no-store`."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthErrorResponse"
                },
                "examples": {
                  "invalid_grant": {
                    "summary": "An authorization code used twice is refused",
                    "value": {
                      "error": "invalid_grant",
                      "error_description": "code is invalid, expired or already used"
                    }
                  },
                  "unsupported_grant_type": {
                    "summary": "Only authorization_code and refresh_token are supported",
                    "value": {
                      "error": "unsupported_grant_type",
                      "error_description": "unsupported grant_type `password`; use authorization_code or refresh_token"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`invalid_client`: no client credentials, an unknown or disabled app, or a wrong secret.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`no-store`."
              },
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "`Basic` challenge, when the client authenticated with HTTP Basic."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthErrorResponse"
                },
                "examples": {
                  "invalid_client": {
                    "summary": "Wrong client secret",
                    "value": {
                      "error": "invalid_client",
                      "error_description": "client authentication failed"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`slow_down`: too many failed attempts from this source; retry after `Retry-After` seconds.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`no-store`."
              },
              "Retry-After": {
                "schema": {
                  "type": "string"
                },
                "description": "Seconds to wait."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "`temporarily_unavailable`: partner access is off on this server or its store is temporarily unavailable; retry.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`no-store`."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthErrorResponse"
                },
                "examples": {
                  "temporarily_unavailable": {
                    "summary": "Partner access is off on this server",
                    "value": {
                      "error": "temporarily_unavailable",
                      "error_description": "storage unavailable: partner access is not enabled"
                    }
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/v1/connections": {
      "get": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "List connected partner apps",
        "description": "The partner apps the user has granted access to (live connections only).",
        "operationId": "list_partner_connections",
        "responses": {
          "200": {
            "description": "The user's connections.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_PartnerConnection"
                },
                "examples": {
                  "success": {
                    "summary": "One connected app",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "client_id": "cp_5C5uooATLM4C2m4Vd41e",
                          "app_name": "Charts Co",
                          "verified": false,
                          "scopes": [
                            "read",
                            "orders"
                          ],
                          "connected_at": "2026-09-29T05:59:06.502090+00:00",
                          "updated_at": "2026-09-29T05:59:06.502090+00:00"
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unavailable": {
                    "summary": "Partner access is off on this server",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "service_unavailable",
                        "message": "Partner access is not enabled on this server",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/connections/{client_id}": {
      "delete": {
        "tags": [
          "partners",
          "app_session_only"
        ],
        "summary": "Disconnect a partner app",
        "description": "Revokes the user's connection to the app: every access token dies at once and every refresh token is deleted. The partner must ask the user to connect again.",
        "operationId": "revoke_partner_connection",
        "parameters": [
          {
            "name": "client_id",
            "in": "path",
            "description": "The app's client id (`cp_...`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Disconnected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_RevokedPartnerConnection"
                },
                "examples": {
                  "success": {
                    "summary": "Disconnected; every token of the app for this user dies",
                    "value": {
                      "status": "success",
                      "data": {
                        "client_id": "cp_5C5uooATLM4C2m4Vd41e",
                        "revoked": true
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "`connection_not_found`: no live connection to that app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "connection_not_found": {
                    "summary": "No live connection to that app",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "connection_not_found",
                        "message": "No live connection to that app",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: partner access is off on this server or its store is temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/shared": {
      "get": {
        "tags": [
          "shared",
          "app_session_only"
        ],
        "summary": "List portfolios shared with you",
        "description": "The active shares other users granted to the caller: who, what (`scopes`) and which accounts. Use `owner_username` with the other shared routes.",
        "operationId": "list_shared_portfolios",
        "responses": {
          "200": {
            "description": "Incoming shares.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_Vec_SharedGrant"
                },
                "examples": {
                  "success": {
                    "summary": "One owner shares everything",
                    "value": {
                      "status": "success",
                      "data": [
                        {
                          "owner_username": "owner-01M3MQZX0M1RYSP2CE8YHM2N65",
                          "owner_name": "Asha Owner",
                          "scopes": [
                            "login",
                            "funds",
                            "positions",
                            "holdings",
                            "open_orders",
                            "order_history"
                          ],
                          "account_scope": "all"
                        }
                      ],
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: shared data (or the owner's accounts) is temporarily unavailable, or sharing is off on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unavailable": {
                    "summary": "Sharing is off on this server",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "service_unavailable",
                        "message": "Data sharing is not available right now.",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/shared/consolidated": {
      "get": {
        "tags": [
          "shared",
          "app_session_only"
        ],
        "summary": "Every shared account on one screen",
        "description": "One card per owner and shared account (balances, P&L, counts, and login status when `login` is shared), plus every shared position with its owner. Each number needs its scope; a problem reading one owner only blanks that owner's numbers.",
        "operationId": "get_consolidated_shared_portfolio",
        "responses": {
          "200": {
            "description": "Owners and positions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_SharedConsolidated"
                },
                "examples": {
                  "success": {
                    "summary": "One owner, two shared accounts (one without data yet)",
                    "value": {
                      "status": "success",
                      "data": {
                        "owners": [
                          {
                            "owner_username": "owner-01M3MQZX0M1RYSP2CE8YHM2N65",
                            "owner_name": "Asha Owner",
                            "scopes": [
                              "login",
                              "funds",
                              "positions",
                              "holdings",
                              "open_orders",
                              "order_history"
                            ],
                            "account_scope": "all",
                            "accounts": [
                              {
                                "client_id": "O1",
                                "has_login": true,
                                "has_funds": true,
                                "has_positions": true,
                                "opening_balance": 100000,
                                "usable_balance": 80000,
                                "utilisation": 20000,
                                "pnl": 120.5,
                                "positions_count": 1,
                                "holdings_count": 1,
                                "broker": "paper",
                                "account_tag": "main",
                                "last_login_at": "1790623872",
                                "logged_in_today": true
                              },
                              {
                                "client_id": "O2",
                                "has_login": true,
                                "has_funds": true,
                                "has_positions": true,
                                "opening_balance": null,
                                "usable_balance": null,
                                "utilisation": null,
                                "pnl": null,
                                "positions_count": 0,
                                "holdings_count": 0,
                                "broker": "paper",
                                "account_tag": null,
                                "last_login_at": null,
                                "logged_in_today": false
                              }
                            ]
                          }
                        ],
                        "positions": [
                          {
                            "account": "O1",
                            "cirrus_token": "CT:TEST:RELIANCE",
                            "tradingsymbol": "RELIANCE-EQ",
                            "product": "MIS",
                            "net_qty": 5,
                            "buy_qty": 5,
                            "sell_qty": 0,
                            "buy_value": 12500,
                            "sell_value": 0,
                            "average_price": 2500,
                            "buy_average_price": 2500,
                            "sell_average_price": 0,
                            "pnl": 120.5,
                            "lot_size": 1,
                            "exchange": "NSE",
                            "instrument_type": "EQUITY",
                            "symbol": "RELIANCE",
                            "expiry": "",
                            "strike": 0,
                            "option_type": "",
                            "ltp": 2500,
                            "prev_close": 0,
                            "owner_username": "owner-01M3MQZX0M1RYSP2CE8YHM2N65",
                            "owner_name": "Asha Owner",
                            "instrument_token": "CT:TEST:RELIANCE"
                          }
                        ]
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: shared data (or the owner's accounts) is temporarily unavailable, or sharing is off on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unavailable": {
                    "summary": "Sharing is off on this server",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "service_unavailable",
                        "message": "Data sharing is not available right now.",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/shared/consolidated/refresh": {
      "post": {
        "tags": [
          "shared",
          "app_session_only"
        ],
        "summary": "Refresh every shared portfolio",
        "description": "Asks for fresh data for every owner sharing with the caller (at most one refresh per owner every 10 seconds, by anyone; failures for one owner are skipped).",
        "operationId": "refresh_consolidated_shared_portfolio",
        "responses": {
          "202": {
            "description": "Refreshes asked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_SharedConsolidatedRefresh"
                },
                "examples": {
                  "success": {
                    "summary": "Every owner refreshed",
                    "value": {
                      "status": "success",
                      "data": {
                        "owners": 1,
                        "dispatched": 1
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: shared data (or the owner's accounts) is temporarily unavailable, or sharing is off on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unavailable": {
                    "summary": "Sharing is off on this server",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "service_unavailable",
                        "message": "Data sharing is not available right now.",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/shared/{owner}/refresh": {
      "post": {
        "tags": [
          "shared",
          "app_session_only"
        ],
        "summary": "Refresh a shared portfolio",
        "description": "Asks for fresh data from the broker for the owner's shared accounts. At most one refresh per owner every 10 seconds, by anyone: within that window nothing is asked and `requested` is `null`. The data arrives in the views moments later.",
        "operationId": "refresh_shared_portfolio",
        "parameters": [
          {
            "name": "owner",
            "in": "path",
            "description": "The owner's username (`owner_username` from `GET /v1/shared`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Refresh asked (or skipped: see `requested`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_SharedRefresh"
                },
                "examples": {
                  "success": {
                    "summary": "Both shared accounts asked to refresh",
                    "value": {
                      "status": "success",
                      "data": {
                        "requested": 2
                      },
                      "error": null
                    }
                  },
                  "throttled": {
                    "summary": "Refreshed moments ago: nothing asked",
                    "value": {
                      "status": "success",
                      "data": {
                        "requested": null
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`not_shared`: that user shares nothing (or not this data) with the caller; `oms_not_enabled`: that user is not served by this deployment; `forbidden`: not an app session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_shared": {
                    "summary": "That user shares nothing with the caller",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "not_shared",
                        "message": "Not shared with you",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: shared data (or the owner's accounts) is temporarily unavailable, or sharing is off on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/shared/{owner}/{view}": {
      "get": {
        "tags": [
          "shared",
          "app_session_only"
        ],
        "summary": "Read one view of a shared portfolio",
        "description": "One kind of data from the owner's shared accounts, read from the same live snapshots as the owner's own portfolio and limited to the accounts the share covers. Each view needs its scope: `accounts` -> `login`, `positions`, `holdings`, `margins` -> `funds`, `open_orders`, `order_history`. `accounts` returns `SharedAccounts`; the others return `SharedPortfolio` (accounts without data yet under `missing`). Credentials never appear.",
        "operationId": "get_shared_view",
        "parameters": [
          {
            "name": "owner",
            "in": "path",
            "description": "The owner's username (`owner_username` from `GET /v1/shared`).",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "view",
            "in": "path",
            "description": "What to read: `accounts` (needs `login`), `positions`, `holdings`, `margins` (needs `funds`), `open_orders`, `order_history`.",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The data a shared view returns (`GET /v1/shared/{owner}/{view}`).",
              "enum": [
                "accounts",
                "positions",
                "holdings",
                "margins",
                "open_orders",
                "order_history"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The view's data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success_SharedViewData"
                },
                "examples": {
                  "accounts": {
                    "summary": "The shared accounts",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "client_id": "O1",
                            "broker": "paper",
                            "account_tag": "main",
                            "last_login_at": "1790623872",
                            "logged_in_today": true
                          },
                          {
                            "client_id": "O2",
                            "broker": "paper",
                            "account_tag": null,
                            "last_login_at": null,
                            "logged_in_today": false
                          }
                        ]
                      },
                      "error": null
                    }
                  },
                  "holdings": {
                    "summary": "Holdings",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "O1",
                            "updated_at": "2026-09-28T19:31:12.056329Z",
                            "data": [
                              {
                                "account": "O1",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "product": "DELIVERY",
                                "quantity": 2,
                                "average_price": 2400,
                                "invested_amount": 4800,
                                "pnl": 200,
                                "pnl_percent": 4.17,
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE"
                              }
                            ]
                          }
                        ],
                        "missing": [
                          {
                            "account": "O2",
                            "reason": "No live data yet for this account"
                          }
                        ]
                      },
                      "error": null
                    }
                  },
                  "margins": {
                    "summary": "Funds (one object per account)",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "O1",
                            "updated_at": "2026-09-28T19:31:12.057977Z",
                            "data": {
                              "account": "O1",
                              "opening_balance": 100000,
                              "available": 80000,
                              "utilised": 20000
                            }
                          }
                        ],
                        "missing": [
                          {
                            "account": "O2",
                            "reason": "No live data yet for this account"
                          }
                        ]
                      },
                      "error": null
                    }
                  },
                  "open_orders": {
                    "summary": "Today's orders not yet final",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "O1",
                            "updated_at": "2026-09-28T19:31:12.059804Z",
                            "data": [
                              {
                                "cirrus_tag": "01M3MQZX1VF18XYYZ816DH4YMM",
                                "broker_tag": null,
                                "order_id": "PAPER-7",
                                "parent_tag": null,
                                "username": "owner-01M3MQZX0N9F3JN8RA4N535CZP",
                                "account": "O1",
                                "broker": "paper",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "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": "2026-09-28T19:31:12.059776Z",
                                "created_at": "2026-09-28T19:31:12.059776Z",
                                "status_history": [
                                  {
                                    "from": "SUBMITTED",
                                    "to": "OPEN",
                                    "at": "2026-09-28T19:31:12.059776Z",
                                    "message": null
                                  }
                                ],
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE",
                                "order_tag": "01M3MQZX1VF18XYYZ816DH4YMM"
                              }
                            ]
                          }
                        ],
                        "missing": [
                          {
                            "account": "O2",
                            "reason": "No live data yet for this account"
                          }
                        ]
                      },
                      "error": null
                    }
                  },
                  "order_history": {
                    "summary": "Today's final orders",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "O1",
                            "updated_at": "2026-09-28T19:31:12.059804Z",
                            "data": [
                              {
                                "cirrus_tag": "01M3MQZX1V0BKXD7R94R3N9WWD",
                                "broker_tag": null,
                                "order_id": "PAPER-6",
                                "parent_tag": null,
                                "username": "owner-01M3MQZX0N9F3JN8RA4N535CZP",
                                "account": "O1",
                                "broker": "paper",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "side": "BUY",
                                "order_type": "LIMIT",
                                "product": "MIS",
                                "quantity": 5,
                                "price": 2500,
                                "trigger_price": null,
                                "state": "FILLED",
                                "filled_qty": 5,
                                "average_price": 2500,
                                "status_message": null,
                                "broker_updated_at": "2026-09-28T19:31:12.059804Z",
                                "created_at": "2026-09-28T19:31:12.059804Z",
                                "status_history": [
                                  {
                                    "from": "SUBMITTED",
                                    "to": "FILLED",
                                    "at": "2026-09-28T19:31:12.059804Z",
                                    "message": null
                                  }
                                ],
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE",
                                "order_tag": "01M3MQZX1V0BKXD7R94R3N9WWD"
                              }
                            ]
                          }
                        ],
                        "missing": [
                          {
                            "account": "O2",
                            "reason": "No live data yet for this account"
                          }
                        ]
                      },
                      "error": null
                    }
                  },
                  "positions": {
                    "summary": "Positions; the account without data is under missing",
                    "value": {
                      "status": "success",
                      "data": {
                        "accounts": [
                          {
                            "account": "O1",
                            "updated_at": "2026-09-28T19:31:12.055576Z",
                            "data": [
                              {
                                "account": "O1",
                                "cirrus_token": "CT:TEST:RELIANCE",
                                "tradingsymbol": "RELIANCE-EQ",
                                "product": "MIS",
                                "net_qty": 5,
                                "buy_qty": 5,
                                "sell_qty": 0,
                                "buy_value": 12500,
                                "sell_value": 0,
                                "average_price": 2500,
                                "buy_average_price": 2500,
                                "sell_average_price": 0,
                                "pnl": 120.5,
                                "lot_size": 1,
                                "exchange": "NSE",
                                "instrument_type": "EQUITY",
                                "symbol": "RELIANCE",
                                "expiry": "",
                                "strike": 0,
                                "option_type": "",
                                "ltp": 2500,
                                "prev_close": 0,
                                "instrument_token": "CT:TEST:RELIANCE"
                              }
                            ]
                          }
                        ],
                        "missing": [
                          {
                            "account": "O2",
                            "reason": "No live data yet for this account"
                          }
                        ]
                      },
                      "error": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "`not_shared`: that user shares nothing (or not this data) with the caller; `oms_not_enabled`: that user is not served by this deployment; `forbidden`: not an app session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_shared": {
                    "summary": "That user shares nothing with the caller",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "not_shared",
                        "message": "Not shared with you",
                        "field": null
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "`invalid_request` (`field`: `view`): not one of the views.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "unknown_view": {
                    "summary": "Not one of the views",
                    "value": {
                      "status": "error",
                      "data": null,
                      "error": {
                        "code": "invalid_request",
                        "message": "view must be one of accounts, positions, holdings, margins, open_orders, order_history",
                        "field": "view"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`service_unavailable`: shared data (or the owner's accounts) is temporarily unavailable, or sharing is off on this server.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "app_session": []
          }
        ],
        "x-app-only": true
      }
    },
    "/v1/openapi.json": {
      "get": {
        "tags": [
          "meta"
        ],
        "summary": "API description",
        "description": "This document: an OpenAPI 3.1 description of every public route, the stream protocol and the webhook payloads. No credential needed. Cached for five minutes; send `If-None-Match` with the last `ETag` to revalidate.",
        "operationId": "get_openapi",
        "parameters": [
          {
            "name": "If-None-Match",
            "in": "header",
            "description": "An `ETag` from an earlier response.",
            "required": false,
            "schema": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string"
                },
                "description": "`public, max-age=300`."
              },
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "Changes whenever the document changes."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "304": {
            "description": "Not modified: the `If-None-Match` ETag is current.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                },
                "description": "The current ETag."
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "tags": [
    {
      "name": "orders",
      "description": "Place, modify and cancel orders (one order across many accounts), bracket and cover orders, margin estimates and position conversion."
    },
    {
      "name": "gtt",
      "description": "Good-till-triggered orders held by the broker."
    },
    {
      "name": "triggers",
      "description": "Stop-loss, target and trailing protection evaluated on every tick, exiting at market when hit."
    },
    {
      "name": "portfolio",
      "description": "Order book, positions, holdings, trades and funds, from live per-account snapshots."
    },
    {
      "name": "accounts",
      "description": "The user's linked broker accounts, their session and live-update health."
    },
    {
      "name": "instruments",
      "description": "Instrument search, details and the full instrument list."
    },
    {
      "name": "user",
      "description": "The signed-in user."
    },
    {
      "name": "stream",
      "description": "WebSocket stream of order, portfolio and activity changes."
    },
    {
      "name": "activity",
      "description": "The activity log: every order action, fill, rejection, trigger and access change, in plain English."
    },
    {
      "name": "webhooks",
      "description": "Outbound webhooks: signed HTTPS deliveries of order, trade, position and account events."
    },
    {
      "name": "signal_urls",
      "description": "Signal URLs: secret URLs that turn alerts from charting and screener tools into orders."
    },
    {
      "name": "api_keys",
      "description": "The user's API keys."
    },
    {
      "name": "partners",
      "description": "Partner apps and OAuth 2.0 (authorization code with PKCE)."
    },
    {
      "name": "shared",
      "description": "Portfolios other users shared with the caller."
    },
    {
      "name": "meta",
      "description": "This description."
    },
    {
      "name": "app_session_only",
      "description": "Available only to the signed-in app session; API keys and partner tokens get 403."
    }
  ],
  "components": {
    "schemas": {
      "AccountDetail": {
        "allOf": [
          {
            "type": "object",
            "description": "One linked broker account and whether it can trade. Never a\ncredential.",
            "required": [
              "account",
              "broker",
              "broker_name",
              "tag",
              "multiplier",
              "supported",
              "status",
              "missing",
              "updates",
              "static_ip",
              "last_login_at",
              "session_expires_at",
              "seat_assigned",
              "last_update_at"
            ],
            "properties": {
              "account": {
                "type": "string",
                "description": "Account id (the broker's client code), as used in an order's\n`accounts` and the `account` filters."
              },
              "broker": {
                "type": "string",
                "description": "Broker id (`zerodha`, `upstox`, `paper`, ...)."
              },
              "broker_name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Broker display name; null for an unknown broker."
              },
              "tag": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The user's own label for the account."
              },
              "multiplier": {
                "type": "number",
                "format": "double",
                "description": "Quantity multiplier applied when an order is placed in this account."
              },
              "supported": {
                "type": "boolean",
                "description": "Whether the broker is supported for trading."
              },
              "status": {
                "$ref": "#/components/schemas/AccountReadiness"
              },
              "missing": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AccountMissingField"
                },
                "description": "Fields the account lacks (empty when complete)."
              },
              "updates": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/AccountUpdates",
                    "description": "Null for an unsupported broker."
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "static_ip": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The account's static IP address, if one is assigned."
              },
              "last_login_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Last broker login."
              },
              "session_expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the broker session expires; null when there is no active\nsession (always null for paper accounts, which need none)."
              },
              "seat_assigned": {
                "type": [
                  "boolean",
                  "null"
                ],
                "description": "Whether the account has a trading seat assigned (null when unknown)."
              },
              "last_update_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the order book was last read from the broker."
              }
            }
          },
          {
            "type": "object",
            "required": [
              "health"
            ],
            "properties": {
              "health": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/AccountHealth",
                    "description": "Null when no live worker has reported for the account recently."
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            }
          }
        ],
        "description": "One linked broker account plus what its live worker last reported."
      },
      "AccountGtts": {
        "type": "object",
        "description": "One account's GTTs at the broker.",
        "required": [
          "account",
          "broker",
          "gtts",
          "error"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "broker": {
            "type": "string",
            "description": "The account's broker."
          },
          "gtts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Gtt"
            },
            "description": "Empty when the list could not be read (`error` says why)."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why this account's list is missing (others still listed); null\nwhen it was read."
          }
        }
      },
      "AccountHealth": {
        "type": "object",
        "description": "What the account's live worker last reported; any field may be null\n(older workers, partial writes).",
        "required": [
          "stream",
          "polls",
          "last_book_read_at",
          "open_orders",
          "last_error_kind",
          "last_error_at"
        ],
        "properties": {
          "stream": {
            "type": [
              "string",
              "null"
            ],
            "description": "The broker's live order-update stream: `up`, `down` or `none` (the\nbroker pushes nothing for this account)."
          },
          "polls": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "`true` while the order book is polled."
          },
          "last_book_read_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the order book was last read from the broker."
          },
          "open_orders": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Open orders at that read.",
            "minimum": 0
          },
          "last_error_kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "Kind of the last failed broker call (never its message)."
          },
          "last_error_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When that call failed."
          }
        }
      },
      "AccountList": {
        "type": "object",
        "description": "The caller's linked broker accounts, sorted by id.",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountView"
            }
          }
        }
      },
      "AccountMissingField": {
        "type": "object",
        "description": "A field the broker account lacks.",
        "required": [
          "field",
          "label",
          "required"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "snake_case id, e.g. `api_secret`."
          },
          "label": {
            "type": "string",
            "description": "As shown in the app, e.g. `API Secret`."
          },
          "required": {
            "type": "boolean",
            "description": "`true`: the account cannot trade without it; `false`: one feature\nis off."
          }
        }
      },
      "AccountReadiness": {
        "type": "string",
        "description": "Whether the account can trade now: `ready`, `login_required` (log in to\nthe broker again), `setup_incomplete` (a required field is missing, see\n`missing`) or `unsupported` (broker not supported for trading).",
        "enum": [
          "ready",
          "login_required",
          "setup_incomplete",
          "unsupported"
        ]
      },
      "AccountResult": {
        "type": "object",
        "description": "What one account did.",
        "required": [
          "account",
          "broker",
          "status",
          "order_ids",
          "message",
          "broker_message",
          "duration_ms"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "broker": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/AccountStatus"
          },
          "order_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plain-English reason, e.g. \"Zerodha rejected it: not enough funds\"."
          },
          "broker_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "The broker's own text, unchanged."
          },
          "duration_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "AccountStatus": {
        "type": "string",
        "description": "What happened in one account: `placed` (accepted by the broker and\nworking), `done` (completed), `rejected` (refused by the broker or\nexchange), `failed` (could not be sent, or did not complete) or\n`unknown` (no answer in time; the broker may or may not have it).",
        "enum": [
          "placed",
          "done",
          "rejected",
          "failed",
          "unknown"
        ]
      },
      "AccountUpdates": {
        "type": "string",
        "description": "How order updates arrive right now: `stream` (the broker's live\nstream), `postback` (the broker calls back) or `polling` (the order\nbook is read every few seconds).",
        "enum": [
          "stream",
          "postback",
          "polling"
        ]
      },
      "AccountView": {
        "type": "object",
        "description": "One linked broker account and whether it can trade. Never a\ncredential.",
        "required": [
          "account",
          "broker",
          "broker_name",
          "tag",
          "multiplier",
          "supported",
          "status",
          "missing",
          "updates",
          "static_ip",
          "last_login_at",
          "session_expires_at",
          "seat_assigned",
          "last_update_at"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id (the broker's client code), as used in an order's\n`accounts` and the `account` filters."
          },
          "broker": {
            "type": "string",
            "description": "Broker id (`zerodha`, `upstox`, `paper`, ...)."
          },
          "broker_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker display name; null for an unknown broker."
          },
          "tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "The user's own label for the account."
          },
          "multiplier": {
            "type": "number",
            "format": "double",
            "description": "Quantity multiplier applied when an order is placed in this account."
          },
          "supported": {
            "type": "boolean",
            "description": "Whether the broker is supported for trading."
          },
          "status": {
            "$ref": "#/components/schemas/AccountReadiness"
          },
          "missing": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountMissingField"
            },
            "description": "Fields the account lacks (empty when complete)."
          },
          "updates": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AccountUpdates",
                "description": "Null for an unsupported broker."
              },
              {
                "type": "null"
              }
            ]
          },
          "static_ip": {
            "type": [
              "string",
              "null"
            ],
            "description": "The account's static IP address, if one is assigned."
          },
          "last_login_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Last broker login."
          },
          "session_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the broker session expires; null when there is no active\nsession (always null for paper accounts, which need none)."
          },
          "seat_assigned": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the account has a trading seat assigned (null when unknown)."
          },
          "last_update_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the order book was last read from the broker."
          }
        }
      },
      "ActivityCategory": {
        "type": "string",
        "description": "Filter group of a record, derived from its `kind`: `orders`,\n`protection`, `signals`, `account` or `access`.",
        "enum": [
          "orders",
          "protection",
          "signals",
          "account",
          "access"
        ]
      },
      "ActivityInstrument": {
        "type": "object",
        "required": [
          "instrument_token",
          "tradingsymbol",
          "exchange"
        ],
        "properties": {
          "instrument_token": {
            "type": "string",
            "description": "Instrument id (also returned as `instrument_token`)."
          },
          "tradingsymbol": {
            "type": "string"
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "ActivityKind": {
        "type": "string",
        "description": "What happened. Serialized snake_case (`order_filled`, `gtt_create`...).",
        "enum": [
          "place",
          "bracket",
          "modify",
          "cancel",
          "convert",
          "order_filled",
          "order_partially_filled",
          "order_rejected",
          "order_cancelled_by_broker",
          "external_order",
          "order_unknown",
          "gtt_create",
          "gtt_modify",
          "gtt_delete",
          "gtt_triggered",
          "trigger_create",
          "trigger_modify",
          "trigger_delete",
          "trigger_hit",
          "trigger_exit",
          "protection_armed",
          "protection_failed",
          "signal",
          "session_expired",
          "relogin_detected",
          "live_updates_unavailable",
          "live_updates_restored",
          "portfolio_refresh",
          "account_setup_incomplete",
          "api_key_created",
          "api_key_revoked",
          "partner_connected",
          "partner_revoked",
          "partner_app_disabled",
          "partner_app_secret_rotated",
          "signal_url_issued",
          "signal_url_revoked",
          "signal_url_rotated",
          "webhook_created",
          "webhook_updated",
          "webhook_deleted",
          "webhook_secret_rotated",
          "webhook_disabled"
        ]
      },
      "ActivityOutcome": {
        "type": "string",
        "description": "`ok` (every account succeeded), `partial` or `failed` (none did).",
        "enum": [
          "ok",
          "partial",
          "failed"
        ]
      },
      "ActivityPage": {
        "type": "object",
        "description": "One page of a day's activity, newest first.",
        "required": [
          "items",
          "next_cursor",
          "source"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityRecord"
            },
            "description": "Records without `timeline` (see `GET /v1/activity/{id}`)."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next (older) page; null on the last page."
          },
          "source": {
            "$ref": "#/components/schemas/ActivityPageSource"
          }
        }
      },
      "ActivityPageSource": {
        "type": "string",
        "description": "Where a page was read from: `hot` (the live store) or `archive` (the\nday's archive, for older days).",
        "enum": [
          "hot",
          "archive"
        ]
      },
      "ActivityRecord": {
        "type": "object",
        "description": "One activity-log record: something that happened to the user's\naccounts, in plain English, with the per-account results.",
        "required": [
          "id",
          "username",
          "at",
          "kind",
          "category",
          "source",
          "request_id",
          "instrument",
          "side",
          "order_type",
          "product",
          "quantity",
          "price",
          "trigger_price",
          "summary",
          "message",
          "outcome",
          "duration_ms",
          "accounts"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "ULID (sorts by creation time)."
          },
          "username": {
            "type": "string"
          },
          "at": {
            "type": "string",
            "format": "date-time",
            "description": "When the action started."
          },
          "kind": {
            "$ref": "#/components/schemas/ActivityKind"
          },
          "category": {
            "$ref": "#/components/schemas/ActivityCategory"
          },
          "source": {
            "$ref": "#/components/schemas/ActivitySource"
          },
          "request_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `x-request-id` of the API call that started it, if any."
          },
          "instrument": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ActivityInstrument"
              },
              {
                "type": "null"
              }
            ]
          },
          "side": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Side"
              },
              {
                "type": "null"
              }
            ]
          },
          "order_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`MARKET`, `LIMIT`, `SL` or `SL_M`."
          },
          "product": {
            "type": [
              "string",
              "null"
            ],
            "description": "`MIS`, `CARRYFORWARD`, `DELIVERY` or `MTF`."
          },
          "quantity": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "minimum": 0
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "trigger_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "summary": {
            "type": "string"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plain reason for records without a per-account result (an ignored\nsignal, a lost session, protection that failed...)."
          },
          "outcome": {
            "$ref": "#/components/schemas/ActivityOutcome"
          },
          "duration_ms": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountResult"
            }
          },
          "timeline": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/TimelineEntry"
            },
            "description": "Only on detail responses and in the archive."
          }
        }
      },
      "ActivitySource": {
        "type": "object",
        "description": "Who or what started an activity.",
        "required": [
          "type",
          "name"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/ActivitySourceType"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "API key name, partner app name, \"TradingView: <strategy>\",\n\"Stop-loss\" / \"Target\" / \"Trailing SL\", broker name."
          }
        }
      },
      "ActivitySourceType": {
        "type": "string",
        "description": "Who or what started it: `app` (signed-in app session), `api_key`,\n`partner`, `signal` (a signal URL), `trigger` (a stop-loss / target\ntrigger), `broker` (the broker or exchange) or `system` (housekeeping).",
        "enum": [
          "app",
          "api_key",
          "partner",
          "signal",
          "trigger",
          "broker",
          "system"
        ]
      },
      "AmendResult": {
        "type": "object",
        "description": "The broker's answer to a modify or cancel. `status`: `accepted` (the\nbroker took the change; the order book follows on the stream),\n`rejected` (refused, e.g. by the broker or the account's order rate\nlimit; `message` says why) or `unknown` (no answer in time: check the\norder book before retrying).",
        "required": [
          "account",
          "order_id",
          "status",
          "message"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/SliceStatus"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it was rejected, or what is unknown; null when accepted."
          }
        }
      },
      "ApiKeyView": {
        "type": "object",
        "description": "An active API key as its owner sees it (never the secret or its hash).",
        "required": [
          "key_id",
          "name",
          "scopes",
          "ip_allowlist",
          "created_at",
          "last_used_at"
        ],
        "properties": {
          "key_id": {
            "type": "string",
            "description": "Public key id (`ck_...`): the part before `:` in\n`Authorization: token <key_id>:<key_secret>`."
          },
          "name": {
            "type": "string",
            "description": "The owner's label for the key."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "What the key may do."
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IP addresses the key may be used from; empty = any."
          },
          "created_at": {
            "type": "string",
            "description": "When the key was created (RFC 3339)."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the key was last used (RFC 3339, updated at most once a\nminute); null when never used."
          }
        }
      },
      "BracketOrderKind": {
        "type": "string",
        "description": "`BO` (bracket: entry + stop-loss + target) or `CO` (cover: entry +\nstop-loss).",
        "enum": [
          "BO",
          "CO"
        ]
      },
      "BracketRequest": {
        "type": "object",
        "description": "A bracket or cover order in one account. Legs are absolute prices on\nthe tick grid, on the right side of the entry (the limit price, or LTP\nfor a market entry): a BUY needs stop-loss < entry < target, a SELL the\nreverse.",
        "required": [
          "account",
          "instrument_token",
          "kind",
          "side",
          "order_type",
          "product",
          "quantity",
          "stop_loss"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id (see `/v1/accounts`)."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id (see `/v1/instruments`)."
          },
          "kind": {
            "$ref": "#/components/schemas/BracketOrderKind"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType",
            "description": "Entry order type: `LIMIT` or `MARKET`."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units, or lots when `qty_is_in_lot`; a multiple of the lot size.",
            "minimum": 0
          },
          "qty_is_in_lot": {
            "type": "boolean",
            "description": "`quantity` counts lots, not units."
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Entry limit price (`LIMIT`); 0 or absent for `MARKET`."
          },
          "stop_loss": {
            "type": "number",
            "format": "double",
            "description": "Stop-loss price."
          },
          "target": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Target price: required for `BO`, not allowed for `CO`."
          },
          "trailing_stop_loss": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Trailing stop-loss step, in points (on the tick grid)."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "BracketResult": {
        "type": "object",
        "description": "The broker's answer. `status`: `accepted`, `rejected` (`message` says\nwhy) or `unknown` (no answer in time: check the order book before\nretrying).",
        "required": [
          "account",
          "basket_id",
          "order_id",
          "status",
          "message"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "basket_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker basket / parent id (placement only; null otherwise)."
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The order changed or cancelled (null on placement)."
          },
          "status": {
            "$ref": "#/components/schemas/SliceStatus"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it was rejected, or what is unknown; null when accepted."
          }
        }
      },
      "ConvertRequest": {
        "type": "object",
        "description": "Move (part of) an open position to another product.",
        "required": [
          "account",
          "instrument_token",
          "side",
          "quantity",
          "from",
          "to"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id holding the position."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id of the position."
          },
          "side": {
            "$ref": "#/components/schemas/Side",
            "description": "Side of the open position (BUY for long, SELL for short)."
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units to convert (greater than 0).",
            "minimum": 0
          },
          "from": {
            "$ref": "#/components/schemas/Product",
            "description": "The position's current product."
          },
          "to": {
            "$ref": "#/components/schemas/Product",
            "description": "The product to move it to (different from `from`)."
          },
          "overnight": {
            "type": "boolean",
            "description": "The position was carried from a previous session (not opened\ntoday)."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "ConvertResult": {
        "type": "object",
        "description": "The broker's answer: `accepted` (positions refresh shortly),\n`rejected` (`message` says why) or `unknown` (no answer in time: check\npositions before retrying).",
        "required": [
          "account",
          "status",
          "message"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/SliceStatus"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it was rejected, or what is unknown; null when accepted."
          }
        }
      },
      "CreatedApiKey": {
        "type": "object",
        "description": "A new API key with its secret (shown only here). Doc-only mirror of the\nbody `create` builds.",
        "required": [
          "key_id",
          "name",
          "scopes",
          "ip_allowlist",
          "created_at",
          "last_used_at",
          "api_secret",
          "note"
        ],
        "properties": {
          "key_id": {
            "type": "string",
            "description": "Public key id (`ck_...`)."
          },
          "name": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            }
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IP addresses the key may be used from; empty = any."
          },
          "created_at": {
            "type": "string",
            "description": "When the key was created (RFC 3339)."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null for a new key."
          },
          "api_secret": {
            "type": "string",
            "description": "The key secret (`cs_...`). Store it now: it is never shown again.\nAuthenticate with `Authorization: token <key_id>:<api_secret>`."
          },
          "note": {
            "type": "string",
            "description": "A reminder that the secret is shown only once."
          }
        }
      },
      "DeletedWebhook": {
        "type": "object",
        "description": "A deleted webhook. Doc-only mirror of the body `remove` builds.",
        "required": [
          "id",
          "deleted"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "description": "Always `true`."
          }
        }
      },
      "DisabledPartnerApp": {
        "type": "object",
        "description": "The app was disabled.",
        "required": [
          "client_id",
          "disabled"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "disabled": {
            "type": "boolean",
            "description": "Always `true`."
          }
        }
      },
      "ErrorBody": {
        "type": "object",
        "description": "What went wrong.",
        "required": [
          "code",
          "message",
          "field"
        ],
        "properties": {
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation; may change, never parse it."
          },
          "field": {
            "type": [
              "string",
              "null"
            ],
            "description": "The offending input, e.g. `orders[0].price`; null when the error is\nnot about one field."
          }
        }
      },
      "ErrorCode": {
        "type": "string",
        "description": "Stable error code: branch on this, never on the message.\n\n| code | HTTP status | meaning |\n|---|---|---|\n| `malformed_json` | 400 | The body is not JSON, or does not fit the request shape (unknown or missing fields, wrong types). |\n| `invalid_query` | 400 | The query string does not fit the route's parameters. |\n| `idempotency_key_required` | 400 | The `Idempotency-Key` header is missing (use a new UUID per order request). |\n| `invalid_idempotency_key` | 400 | The `Idempotency-Key` header is not 1-128 printable characters. |\n| `unauthorized` | 401 | No credential, or the credential is invalid, expired or revoked. |\n| `forbidden` | 403 | The credential may not use this route (missing scope, app-session-only route, IP not allowed). |\n| `own_session_required` | 403 | Credentials can only be created from the user's own signed-in session. |\n| `oms_not_enabled` | 403 | Order management is not enabled for this user. |\n| `not_shared` | 403 | That user has not shared this data with the caller. |\n| `account_not_found` | 404 | No linked broker account with this id for the caller. |\n| `instrument_not_found` | 404 | No instrument with this token (unknown or expired). |\n| `trigger_not_found` | 404 | No trigger with this id for the caller. |\n| `api_key_not_found` | 404 | No API key with this id for the caller. |\n| `connection_not_found` | 404 | No connected partner app with this client id. |\n| `unknown_app` | 404 | Unknown or disabled partner app. |\n| `endpoint_not_found` | 404 | No signal URL with this id (or this secret) for the caller. |\n| `webhook_not_found` | 404 | No webhook with this id for the caller. |\n| `activity_not_found` | 404 | No activity record with this id for the caller. |\n| `request_in_progress` | 409 | A request with this `Idempotency-Key` is still being processed. |\n| `trigger_busy` | 409 | The trigger changed while it was being updated; retry. |\n| `trigger_fired` | 409 | The trigger already fired; its exit is being handled. |\n| `broker_held` | 409 | The protection is held by the broker; change the broker order instead. |\n| `webhook_limit_reached` | 409 | The webhook limit is reached; delete one first. |\n| `invalid_request` | 422 | The request is well-formed but not valid; `field` names the input. |\n| `idempotency_key_reused` | 422 | This `Idempotency-Key` was already used with a different request. |\n| `archive_day_too_large` | 422 | That day's archived activity is too large to serve at once. |\n| `invalid_client` | 422 | OAuth: unknown partner app, or wrong client credentials. |\n| `invalid_grant` | 422 | OAuth: the authorization code or refresh token is invalid, used or expired. |\n| `unsupported_grant_type` | 400 | OAuth token endpoint: `grant_type` is missing or not supported. |\n| `slow_down` | 429 | OAuth token endpoint: too many failed attempts from this source; retry after `Retry-After`. |\n| `invalid_scope` | 422 | OAuth: a requested scope is unknown or not allowed for the app. |\n| `temporarily_unavailable` | 503 | OAuth: the authorization server is temporarily unavailable. |\n| `rate_limited` | 429 | Too many requests for this credential (or too many failed attempts); retry later. |\n| `broker_refused` | 502 | The broker refused the change. |\n| `service_unavailable` | 503 | A dependency is temporarily unavailable, or the feature is off on this server; retry later. |\n| `instruments_unavailable` | 503 | The instrument master is not loaded yet; retry shortly. |\n| `trigger_worker_down` | 503 | No trigger exit worker is running; nothing was created. |\n| `webhooks_disabled` | 503 | Webhooks are not enabled on this server. |\n| `unavailable` | 503 | Stream only: live updates are unavailable; reconnect. |",
        "enum": [
          "malformed_json",
          "invalid_query",
          "idempotency_key_required",
          "invalid_idempotency_key",
          "unauthorized",
          "forbidden",
          "own_session_required",
          "oms_not_enabled",
          "not_shared",
          "account_not_found",
          "instrument_not_found",
          "trigger_not_found",
          "api_key_not_found",
          "connection_not_found",
          "unknown_app",
          "endpoint_not_found",
          "webhook_not_found",
          "activity_not_found",
          "request_in_progress",
          "trigger_busy",
          "trigger_fired",
          "broker_held",
          "webhook_limit_reached",
          "invalid_request",
          "idempotency_key_reused",
          "archive_day_too_large",
          "invalid_client",
          "invalid_grant",
          "unsupported_grant_type",
          "slow_down",
          "invalid_scope",
          "temporarily_unavailable",
          "rate_limited",
          "broker_refused",
          "service_unavailable",
          "instruments_unavailable",
          "trigger_worker_down",
          "webhooks_disabled",
          "unavailable"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Failed request: `data` is null; `error.code` is stable to branch on,\n`error.message` is for people.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/ErrorStatus"
          },
          "data": {
            "type": "null"
          },
          "error": {
            "$ref": "#/components/schemas/ErrorBody"
          }
        }
      },
      "ErrorStatus": {
        "type": "string",
        "description": "Always `error`.",
        "enum": [
          "error"
        ]
      },
      "Gtt": {
        "type": "object",
        "description": "A GTT at the broker, in one shape for every broker (includes GTTs made\noutside this API, e.g. in the broker's own app).",
        "required": [
          "trigger_id",
          "status",
          "instrument_token",
          "tradingsymbol",
          "exchange",
          "side",
          "product",
          "quantity",
          "last_price",
          "legs",
          "created_at",
          "updated_at",
          "expires_at"
        ],
        "properties": {
          "trigger_id": {
            "type": "string",
            "description": "The broker's GTT id."
          },
          "status": {
            "type": "string",
            "description": "Broker status, lower-case (`active`, `triggered`, `cancelled`, ...)."
          },
          "instrument_token": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument id; null when the broker's instrument is not known here."
          },
          "tradingsymbol": {
            "type": "string"
          },
          "exchange": {
            "type": "string"
          },
          "side": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Side",
                "description": "Side of the order(s) a trigger places."
              },
              {
                "type": "null"
              }
            ]
          },
          "product": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Product"
              },
              {
                "type": "null"
              }
            ]
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units.",
            "minimum": 0
          },
          "last_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "LTP when the GTT was created / last modified."
          },
          "legs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GttLevel"
            },
            "description": "One leg (single) or two (stop-loss first, then target)."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "GttLegInput": {
        "type": "object",
        "description": "One GTT leg: the price that fires it and the order's limit price.",
        "required": [
          "trigger"
        ],
        "properties": {
          "trigger": {
            "type": "number",
            "format": "double",
            "description": "Price that fires the leg (on the tick grid)."
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Limit price of the order placed; defaults to the trigger."
          }
        },
        "additionalProperties": false
      },
      "GttLevel": {
        "type": "object",
        "description": "One leg of a GTT at the broker.",
        "required": [
          "trigger",
          "price"
        ],
        "properties": {
          "trigger": {
            "type": "number",
            "format": "double",
            "description": "Price that fires the leg."
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Limit price of the order it places."
          }
        }
      },
      "GttRequest": {
        "type": "object",
        "description": "A GTT in one account: a stop-loss, a target, or both (one\ncancels the other). With both, a SELL's stop-loss sits below LTP and\nits target above (reversed for BUY); a single leg may be either side\nbut not at LTP.",
        "required": [
          "account",
          "instrument_token",
          "side",
          "product",
          "quantity"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id (see `/v1/accounts`)."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id (see `/v1/instruments`)."
          },
          "side": {
            "$ref": "#/components/schemas/Side",
            "description": "Side of the order a trigger places (SELL to protect a long)."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units, or lots when `qty_is_in_lot`; a multiple of the lot size.",
            "minimum": 0
          },
          "qty_is_in_lot": {
            "type": "boolean",
            "description": "`quantity` counts lots, not units."
          },
          "stop_loss": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/GttLegInput"
              },
              {
                "type": "null"
              }
            ]
          },
          "target": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/GttLegInput"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "GttResult": {
        "type": "object",
        "description": "The broker's answer. `status`: `accepted`, `rejected` (`message` says\nwhy) or `unknown` (no answer in time: list the account's GTTs before\nretrying).",
        "required": [
          "account",
          "trigger_id",
          "status",
          "message"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "trigger_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The broker's GTT id; null when creating failed."
          },
          "status": {
            "$ref": "#/components/schemas/SliceStatus"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it was rejected, or what is unknown; null when accepted."
          }
        }
      },
      "HoldingRow": {
        "type": "object",
        "description": "One holding row (enriched).",
        "required": [
          "account",
          "instrument_token",
          "tradingsymbol",
          "product",
          "quantity",
          "average_price",
          "invested_amount",
          "pnl",
          "pnl_percent"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "instrument_token": {
            "type": "string"
          },
          "tradingsymbol": {
            "type": "string"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "average_price": {
            "type": "number",
            "format": "double"
          },
          "invested_amount": {
            "type": "number",
            "format": "double"
          },
          "pnl": {
            "type": "number",
            "format": "double"
          },
          "pnl_percent": {
            "type": "number",
            "format": "double"
          },
          "lot_size": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Contract lot size (added when the instrument is known).",
            "minimum": 0
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ],
            "description": "Exchange (`NSE`, `NFO`, `BSE`, `BFO`, `MCX`, ...)."
          },
          "instrument_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument type (`EQ`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
          },
          "symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Underlying symbol (the trading symbol for equities)."
          },
          "expiry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date (`YYYY-MM-DD`); empty for non-derivatives."
          },
          "strike": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Strike price; `0` for non-options."
          },
          "option_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`CE` / `PE`; empty for non-options."
          },
          "instrument_missing": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Present (`true`) only when the instrument is not known; the\ninstrument fields above are then absent."
          },
          "ltp": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Last traded price (added when a quote is available)."
          },
          "prev_close": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Previous close (`0` when unknown), sent with `ltp`."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "InstrumentRow": {
        "type": "object",
        "description": "One instrument, as in the instrument list (a field the source lacks is\nnull).",
        "required": [
          "instrument_token",
          "exchange",
          "instrument",
          "exchange_token",
          "lot_size",
          "expiry",
          "strike",
          "option_type",
          "tick_size",
          "underlying_symbol",
          "isin",
          "freeze_qty",
          "name",
          "tradingsymbol",
          "sector",
          "indices"
        ],
        "properties": {
          "instrument_token": {
            "type": "string",
            "description": "Instrument id: what orders, triggers and every row call\n`instrument_token`."
          },
          "exchange": {
            "type": "string",
            "description": "Exchange (`NSE`, `BSE`, `NFO`, `BFO`, `MCX`, ...), upper case."
          },
          "instrument": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument type (`EQUITY`, `INDEX`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
          },
          "exchange_token": {
            "type": [
              "string",
              "null"
            ],
            "description": "The exchange's own token for the instrument."
          },
          "lot_size": {
            "type": "integer",
            "format": "int64",
            "description": "Contract lot size; `0` for indices (not tradable).",
            "minimum": 0
          },
          "expiry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date (`YYYY-MM-DD`); null for non-derivatives."
          },
          "strike": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Strike price; null for non-options."
          },
          "option_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`CE` / `PE`; null for non-options."
          },
          "tick_size": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Smallest price step."
          },
          "underlying_symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Underlying symbol (derivatives), or the stock's own symbol."
          },
          "isin": {
            "type": [
              "string",
              "null"
            ]
          },
          "freeze_qty": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Exchange freeze quantity: larger orders are split into slices.",
            "minimum": 0
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company or instrument name."
          },
          "tradingsymbol": {
            "type": "string",
            "description": "Trading symbol, as the exchange lists it."
          },
          "sector": {
            "type": [
              "string",
              "null"
            ]
          },
          "indices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Index memberships (e.g. `NIFTY 50`); empty when none."
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "InstrumentSearchResult": {
        "type": "object",
        "description": "Matching instruments, best match first.",
        "required": [
          "items",
          "count"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InstrumentRow"
            }
          },
          "count": {
            "type": "integer",
            "description": "Number of `items`.",
            "minimum": 0
          }
        }
      },
      "IssueSignalUrlRequest": {
        "type": "object",
        "description": "A new signal URL for one of the user's strategies.",
        "required": [
          "kind",
          "strategy_id"
        ],
        "properties": {
          "kind": {
            "$ref": "#/components/schemas/SignalProvider",
            "description": "The provider that will call the URL."
          },
          "strategy_id": {
            "type": "string",
            "description": "The strategy's id: 1-64 letters, digits, `-` or `_`."
          }
        },
        "additionalProperties": false
      },
      "IssuedSignalUrl": {
        "type": "object",
        "description": "A new signal URL (issued or rotated). Its path and body secret are\nshown only in this response. Doc-only mirror of the body the handlers\nbuild.",
        "required": [
          "endpoint_id",
          "kind",
          "strategy_id",
          "created_at",
          "has_body_secret",
          "path",
          "body_secret",
          "note"
        ],
        "properties": {
          "endpoint_id": {
            "type": "string",
            "description": "Public id (`we_...`), kept across rotations."
          },
          "kind": {
            "$ref": "#/components/schemas/SignalProvider"
          },
          "strategy_id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "description": "When this URL was issued (RFC 3339)."
          },
          "has_body_secret": {
            "type": "boolean",
            "description": "TradingView: alerts must carry `body_secret`."
          },
          "path": {
            "type": "string",
            "description": "The path to give the provider, prefixed with the API origin\n(`/v1/hooks/{kind}/wh_...`). It is the credential: keep it private."
          },
          "body_secret": {
            "type": [
              "string",
              "null"
            ],
            "description": "TradingView only: put `\"secret\": \"<this>\"` (`tvs_...`) in the alert\nmessage. Null for other providers."
          },
          "note": {
            "type": "string",
            "description": "A reminder that the URL is shown only once."
          }
        }
      },
      "MarginRow": {
        "type": "object",
        "description": "Funds of one account (a single object, not a list).",
        "required": [
          "account",
          "opening_balance",
          "available",
          "utilised"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "opening_balance": {
            "type": "number",
            "format": "double"
          },
          "available": {
            "type": "number",
            "format": "double"
          },
          "utilised": {
            "type": "number",
            "format": "double"
          }
        },
        "additionalProperties": false
      },
      "ModifyBracketRequest": {
        "type": "object",
        "description": "Changes to a bracket or cover order; absent fields stay as they are.\nA bracket's legs change together (`stop_loss` and `target`); a cover\nhas no target.",
        "required": [
          "account",
          "instrument_token",
          "kind",
          "side",
          "entry_price"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id the order is in."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id of the order."
          },
          "kind": {
            "$ref": "#/components/schemas/BracketOrderKind"
          },
          "side": {
            "$ref": "#/components/schemas/Side",
            "description": "Side of the entry."
          },
          "entry_price": {
            "type": "number",
            "format": "double",
            "description": "Entry price the legs are measured from."
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "New entry limit price."
          },
          "quantity": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "New quantity, in units.",
            "minimum": 0
          },
          "stop_loss": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "New stop-loss price."
          },
          "target": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "New target price (`BO` only)."
          },
          "trailing_stop_loss": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "New trailing stop-loss step, in points."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "ModifyOrderRequest": {
        "type": "object",
        "description": "The order as it should be now (the full order, not a patch).",
        "required": [
          "account",
          "instrument_token",
          "side",
          "order_type",
          "product",
          "quantity"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id the order is in (see `/v1/accounts`)."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id of the order."
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units, or lots when `qty_is_in_lot`; a multiple of the lot size.",
            "minimum": 0
          },
          "qty_is_in_lot": {
            "type": "boolean",
            "description": "`quantity` counts lots, not units."
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Limit price (`LIMIT`, `SL`); 0 or absent for market orders."
          },
          "trigger_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Trigger price for `SL` / `SL_M`."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "ModifyTriggerRequest": {
        "type": "object",
        "description": "What to change; give at least one field. Levels are recomputed only\nfor the legs whose inputs changed (trailing progress is kept).",
        "properties": {
          "rules": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Rules",
                "description": "New rules (all three legs)."
              },
              {
                "type": "null"
              }
            ]
          },
          "quantity": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "New quantity, in units.",
            "minimum": 0
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "New entry price the levels are measured from."
          }
        },
        "additionalProperties": false
      },
      "NewApiKey": {
        "type": "object",
        "description": "A new API key. At most 10 keys may be active at once.",
        "required": [
          "name",
          "scopes"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "A label for the key, 1-64 characters (trimmed)."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "What the key may do; at least one."
          },
          "ip_allowlist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "IP addresses (v4 or v6) the key may be used from, at most 20;\nempty or absent = any."
          }
        },
        "additionalProperties": false
      },
      "NewPartnerApp": {
        "type": "object",
        "description": "A partner app to register.",
        "required": [
          "name",
          "redirect_uris",
          "scopes"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name shown to users on the consent screen (1-80 characters)."
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "1-10 redirect URIs, matched exactly (no prefixes, no wildcards):\n`https://`, or `http://localhost` / `http://127.0.0.1` for\ndevelopment; no fragment, at most 512 characters."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "The most a user can grant the app (at least one)."
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTPS URL of the app's logo."
          }
        },
        "additionalProperties": false
      },
      "NewWebhook": {
        "type": "object",
        "description": "A new webhook. A user may have at most 5.",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "The receiver: an `https://` URL on a public host (private, loopback\nand link-local addresses are refused)."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "Events to send, at least one: `order_update`, `trade`,\n`account_alert`, `positions` (`ping` cannot be subscribed to)."
          },
          "accounts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Only these of the user's accounts (non-empty, the user's own); leave\nout or null for every account, including ones added later."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "A note for the owner, at most 200 characters."
          }
        },
        "additionalProperties": false
      },
      "OAuthAuthorizeRequest": {
        "type": "object",
        "description": "The user approved the partner's request on the consent screen.",
        "required": [
          "client_id",
          "redirect_uri",
          "scope",
          "code_challenge",
          "code_challenge_method"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The partner app's client id."
          },
          "redirect_uri": {
            "type": "string",
            "description": "One of the app's registered redirect URIs, exactly."
          },
          "scope": {
            "type": "string",
            "description": "Requested scopes, space separated (`read`, `orders`, `triggers`);\neach must be allowed for the app."
          },
          "state": {
            "type": [
              "string",
              "null"
            ],
            "description": "The partner's opaque `state`, returned unchanged (URL-encoded) in\nthe redirect."
          },
          "code_challenge": {
            "type": "string",
            "description": "PKCE challenge: base64url (no padding) SHA-256 of the partner's\n`code_verifier` (43 characters)."
          },
          "code_challenge_method": {
            "type": "string",
            "description": "Must be `S256` (plain PKCE is refused).",
            "example": "S256"
          }
        },
        "additionalProperties": false
      },
      "OAuthAuthorizeResponse": {
        "type": "object",
        "description": "Where to send the user's browser after approval.",
        "required": [
          "redirect_url"
        ],
        "properties": {
          "redirect_url": {
            "type": "string",
            "description": "The registered `redirect_uri` with `code` (single use, valid 60\nseconds) and, when one was sent, `state` (URL-encoded) appended to\nits query, e.g. `https://partner.example/cb?code=oc_...&state=xyz`."
          }
        }
      },
      "OAuthConsent": {
        "type": "object",
        "description": "What the consent screen shows before the user approves.",
        "required": [
          "client_id",
          "name",
          "logo_url",
          "verified",
          "scopes"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The partner app's client id."
          },
          "name": {
            "type": "string",
            "description": "The app's name."
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTPS URL of the app's logo."
          },
          "verified": {
            "type": "boolean",
            "description": "`false`: warn the user that the app's name is not verified."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "The scopes requested (validated, duplicates removed)."
          }
        }
      },
      "OAuthErrorCode": {
        "type": "string",
        "description": "Token endpoint error codes (RFC 6749 section 5.2) and their status:\n`invalid_request` (400), `invalid_grant` (400), `invalid_client` (401),\n`temporarily_unavailable` (503), `unsupported_grant_type` (400),\n`slow_down` (429, with `Retry-After`).",
        "enum": [
          "invalid_request",
          "invalid_grant",
          "invalid_client",
          "temporarily_unavailable",
          "unsupported_grant_type",
          "slow_down"
        ]
      },
      "OAuthErrorResponse": {
        "type": "object",
        "description": "Token endpoint error (RFC 6749 section 5.2). Not the usual envelope.",
        "required": [
          "error",
          "error_description"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/OAuthErrorCode"
          },
          "error_description": {
            "type": "string",
            "description": "Human-readable explanation; may change, never parse it."
          }
        }
      },
      "OAuthGrantType": {
        "type": "string",
        "description": "Supported `grant_type` values; any other is refused with\n`invalid_request`.",
        "enum": [
          "authorization_code",
          "refresh_token"
        ]
      },
      "OAuthTokenRequest": {
        "type": "object",
        "description": "Token request (RFC 6749 sections 4.1.3 and 6), form-encoded or JSON.\nWhich fields are needed depends on `grant_type`:\n- `authorization_code`: `code`, `redirect_uri`, `code_verifier`\n- `refresh_token`: `refresh_token`\n\nClient authentication: `client_id` + `client_secret` here, or HTTP\nBasic (`Authorization: Basic base64(client_id:client_secret)`), which\nwins when both are sent. Unknown fields are ignored.",
        "required": [
          "grant_type"
        ],
        "properties": {
          "grant_type": {
            "$ref": "#/components/schemas/OAuthGrantType",
            "description": "`authorization_code` or `refresh_token`; missing or anything else is\n`unsupported_grant_type`."
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "`authorization_code`: the code from the redirect (`oc_...`)."
          },
          "redirect_uri": {
            "type": [
              "string",
              "null"
            ],
            "description": "`authorization_code`: the same `redirect_uri` the code was issued for."
          },
          "code_verifier": {
            "type": [
              "string",
              "null"
            ],
            "description": "`authorization_code`: the PKCE verifier (43-128 characters of\n`A-Z a-z 0-9 - . _ ~`) whose S256 challenge was sent to authorize."
          },
          "refresh_token": {
            "type": [
              "string",
              "null"
            ],
            "description": "`refresh_token`: the latest refresh token (`pr_...`)."
          },
          "client_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The app's client id (unless sent with HTTP Basic)."
          },
          "client_secret": {
            "type": [
              "string",
              "null"
            ],
            "description": "The app's client secret (unless sent with HTTP Basic)."
          }
        }
      },
      "OAuthTokenResponse": {
        "type": "object",
        "description": "Token response (RFC 6749 section 5.1): a new access token and a new\nrefresh token. Not wrapped in the usual response envelope.",
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "refresh_token",
          "scope"
        ],
        "properties": {
          "access_token": {
            "type": "string",
            "description": "Access token (`pa_...`); send it as `Authorization: Bearer <access_token>`."
          },
          "token_type": {
            "type": "string",
            "description": "Always `Bearer`.",
            "example": "Bearer"
          },
          "expires_in": {
            "type": "integer",
            "format": "int64",
            "description": "Seconds until the access token expires (86400: one day).",
            "minimum": 0
          },
          "refresh_token": {
            "type": "string",
            "description": "Refresh token (`pr_...`), valid for 90 days and single use: every\nrefresh returns a new one. Presenting a used refresh token again\nrevokes the whole connection."
          },
          "scope": {
            "type": "string",
            "description": "Granted scopes, space separated (OAuth convention), e.g. `read orders`."
          }
        }
      },
      "OrderData": {
        "type": "object",
        "description": "An order as it is delivered live: the tracked order plus instrument\ndetails and live prices (added when the instrument is known).\n\n`instrument_token` and `order_tag` are also sent under their legacy\nnames, always with the same value; read the primary names.",
        "required": [
          "order_tag",
          "username",
          "account",
          "broker",
          "instrument_token",
          "tradingsymbol",
          "side",
          "order_type",
          "product",
          "quantity",
          "price",
          "state",
          "filled_qty",
          "created_at",
          "status_history"
        ],
        "properties": {
          "order_tag": {
            "type": "string",
            "description": "The order's id, chosen when it was placed (a ULID)."
          },
          "broker_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "Tag as sent to the broker (format depends on the broker)."
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker-assigned order id; `null` until the broker acknowledges."
          },
          "parent_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "`order_tag` of the order this one belongs to (a protective leg's\nentry), if any."
          },
          "username": {
            "type": "string"
          },
          "account": {
            "type": "string"
          },
          "broker": {
            "type": "string",
            "description": "Broker id (`zerodha`, `upstox`, ...)."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id."
          },
          "tradingsymbol": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Limit price; `0` for market orders."
          },
          "trigger_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "state": {
            "$ref": "#/components/schemas/OrderState"
          },
          "filled_qty": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "average_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          },
          "status_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "The broker's latest status text (rejection reason, ...)."
          },
          "broker_updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Broker time of the last update applied."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "status_history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StatusChange"
            },
            "description": "Every state change so far, oldest first."
          },
          "lot_size": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Contract lot size (added when the instrument is known).",
            "minimum": 0
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ],
            "description": "Exchange (`NSE`, `NFO`, `BSE`, `BFO`, `MCX`, ...)."
          },
          "instrument_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument type (`EQ`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
          },
          "symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Underlying symbol (the trading symbol for equities)."
          },
          "expiry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date (`YYYY-MM-DD`); empty for non-derivatives."
          },
          "strike": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Strike price; `0` for non-options."
          },
          "option_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`CE` / `PE`; empty for non-options."
          },
          "instrument_missing": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Present (`true`) only when the instrument is not known; the\ninstrument fields above are then absent."
          },
          "ltp": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Last traded price (added when a quote is available)."
          },
          "prev_close": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Previous close (`0` when unknown), sent with `ltp`."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token",
          "cirrus_tag": "order_tag"
        }
      },
      "OrderInput": {
        "type": "object",
        "description": "One order, to place in each of `accounts`.",
        "required": [
          "instrument_token",
          "side",
          "order_type",
          "product",
          "quantity",
          "accounts"
        ],
        "properties": {
          "instrument_token": {
            "type": "string",
            "description": "Instrument id, e.g. `CT:1:2885:RELIANCE-EQ` (see `/v1/instruments`)."
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units, or lots when `qty_is_in_lot`; a multiple of the lot size.",
            "minimum": 0
          },
          "qty_is_in_lot": {
            "type": "boolean",
            "description": "`quantity` counts lots, not units."
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Limit price (`LIMIT`, `SL`); 0 or absent for market orders."
          },
          "trigger_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Trigger price for `SL` / `SL_M`."
          },
          "accounts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Account ids to place this order in (see `/v1/accounts`).",
            "minItems": 1
          },
          "protection": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Rules",
                "description": "Stop-loss / target / trail armed once this order fills (as a broker\nbracket / cover / GTT order when the broker supports it, otherwise a\nserver-side trigger)."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "OrderMarginResponse": {
        "type": "object",
        "description": "Margin per order and account, and the total.",
        "required": [
          "results",
          "total_required"
        ],
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderMarginResult"
            }
          },
          "total_required": {
            "type": "number",
            "format": "double",
            "description": "Sum over results that have a figure."
          }
        }
      },
      "OrderMarginResult": {
        "type": "object",
        "description": "Margin for one order in one account.",
        "required": [
          "order_index",
          "account",
          "instrument_token",
          "quantity",
          "total_required",
          "message"
        ],
        "properties": {
          "order_index": {
            "type": "integer",
            "description": "Index of the order in the request.",
            "minimum": 0
          },
          "account": {
            "type": "string"
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id."
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units that would be sent (after lot and multiplier sizing); 0 when\nthe account would refuse the order.",
            "minimum": 0
          },
          "total_required": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Margin the broker requires; null when there is no figure\n(`message` says why)."
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why there is no figure (the order would be refused, the broker\ncannot calculate margins, or it did not answer)."
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "OrderState": {
        "type": "string",
        "description": "Order state: `SUBMITTED` (sent, not yet acknowledged), `OPEN`,\n`TRIGGER_PENDING` (stop-loss waiting for its trigger), `PARTIALLY_FILLED`,\n`FILLED`, `CANCELLED`, `REJECTED`, `EXPIRED` (day order ended unfilled)\nor `UNKNOWN` (not confirmed yet; never a guessed terminal state).",
        "enum": [
          "SUBMITTED",
          "OPEN",
          "TRIGGER_PENDING",
          "PARTIALLY_FILLED",
          "FILLED",
          "CANCELLED",
          "REJECTED",
          "EXPIRED",
          "UNKNOWN"
        ]
      },
      "OrderTag": {
        "type": "string",
        "description": "Order tag: a ULID (26 characters, sorts by creation time), assigned when the order is created.",
        "examples": [
          "01J8Z6Q3W5X7Y9A1B3C5D7E9F1"
        ],
        "pattern": "^[0-9A-HJKMNP-TV-Z]{26}$"
      },
      "OrderType": {
        "type": "string",
        "description": "`MARKET`, `LIMIT`, `SL` (stop-loss limit) or `SL_M` (stop-loss market;\n`SL-M` and `SLM` are accepted in requests).",
        "enum": [
          "MARKET",
          "LIMIT",
          "SL",
          "SL_M"
        ]
      },
      "PartnerApp": {
        "type": "object",
        "description": "A registered partner app.",
        "required": [
          "client_id",
          "owner",
          "name",
          "verified",
          "logo_url",
          "redirect_uris",
          "scopes",
          "created_at",
          "disabled"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "OAuth client id (`cp_...`)."
          },
          "owner": {
            "type": "string",
            "description": "Username of the user who registered the app."
          },
          "name": {
            "type": "string",
            "description": "Name shown to users on the consent screen."
          },
          "verified": {
            "type": "boolean",
            "description": "Whether the operator has confirmed that the app's name belongs to\nits owner; never set through the API. Unverified apps are flagged\non the consent screen."
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTPS URL of the app's logo."
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Exact redirect URIs a user may be sent back to."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "The most a user can grant this partner."
          },
          "created_at": {
            "type": "string",
            "description": "RFC 3339 time of registration."
          },
          "disabled": {
            "type": "boolean",
            "description": "`true` once the owner disabled the app (its tokens stop working)."
          }
        }
      },
      "PartnerConnection": {
        "type": "object",
        "description": "A partner app the user connected (granted access to).",
        "required": [
          "client_id",
          "app_name",
          "verified",
          "scopes",
          "connected_at",
          "updated_at"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The partner app's client id."
          },
          "app_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The app's name; `null` when the app has since been disabled."
          },
          "verified": {
            "type": "boolean",
            "description": "Whether the app is verified (see `PartnerApp.verified`)."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "Scopes the user granted."
          },
          "connected_at": {
            "type": "string",
            "description": "RFC 3339 time of the first connection."
          },
          "updated_at": {
            "type": "string",
            "description": "RFC 3339 time of the latest grant."
          }
        }
      },
      "PlaceOrdersRequest": {
        "type": "object",
        "description": "One or more orders, each placed in every account it names.",
        "required": [
          "orders"
        ],
        "properties": {
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderInput"
            },
            "minItems": 1
          },
          "use_multiplier": {
            "type": "boolean",
            "description": "Scale quantity by each account's `Multiplier`."
          }
        },
        "additionalProperties": false
      },
      "PlaceOrdersResponse": {
        "type": "object",
        "description": "Per-slice results (some accounts may succeed while others are\nrefused) and the count of each status.",
        "required": [
          "results",
          "accepted",
          "rejected",
          "unknown"
        ],
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SliceResult"
            }
          },
          "accepted": {
            "type": "integer",
            "minimum": 0
          },
          "rejected": {
            "type": "integer",
            "minimum": 0
          },
          "unknown": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "PortfolioAccountData": {
        "type": "object",
        "description": "One account's data of the requested kind.",
        "required": [
          "account",
          "updated_at",
          "data"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the data was last read from the broker (for `orders`: the\nlatest broker update of any order); null when unknown."
          },
          "data": {
            "$ref": "#/components/schemas/SnapshotData",
            "description": "`orders`: today's orders, newest first (`OrderData` rows);\n`positions`, `holdings`, `trades`: `PositionRow`, `HoldingRow`,\n`TradeRow` rows (`trades`: today's fills only); `margins`: one\n`MarginRow` object."
          }
        }
      },
      "PortfolioMissing": {
        "type": "object",
        "description": "An account with no data to show (yet).",
        "required": [
          "account",
          "reason"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "reason": {
            "type": "string",
            "description": "Why, in plain English (no live data yet: broker not supported, or\nno active session)."
          }
        }
      },
      "PortfolioRefresh": {
        "type": "object",
        "description": "A refresh was requested.",
        "required": [
          "requested"
        ],
        "properties": {
          "requested": {
            "type": "integer",
            "description": "How many accounts were asked to re-read.",
            "minimum": 0
          }
        }
      },
      "PortfolioResponse": {
        "type": "object",
        "description": "Per-account data of one kind; accounts without data are listed under\n`missing`, never silently left out.",
        "required": [
          "accounts",
          "missing"
        ],
        "properties": {
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortfolioAccountData"
            }
          },
          "missing": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PortfolioMissing"
            }
          }
        }
      },
      "PositionRow": {
        "type": "object",
        "description": "One open position row (as the broker reports it, enriched).",
        "required": [
          "account",
          "instrument_token",
          "tradingsymbol",
          "product",
          "net_qty",
          "buy_qty",
          "sell_qty",
          "buy_value",
          "sell_value",
          "average_price",
          "buy_average_price",
          "sell_average_price",
          "pnl"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "instrument_token": {
            "type": "string"
          },
          "tradingsymbol": {
            "type": "string"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "net_qty": {
            "type": "integer",
            "format": "int64",
            "description": "Positive long, negative short."
          },
          "buy_qty": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "sell_qty": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "buy_value": {
            "type": "number",
            "format": "double"
          },
          "sell_value": {
            "type": "number",
            "format": "double"
          },
          "average_price": {
            "type": "number",
            "format": "double"
          },
          "buy_average_price": {
            "type": "number",
            "format": "double"
          },
          "sell_average_price": {
            "type": "number",
            "format": "double"
          },
          "pnl": {
            "type": "number",
            "format": "double",
            "description": "Mark-to-market P&L as reported by the broker."
          },
          "lot_size": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Contract lot size (added when the instrument is known).",
            "minimum": 0
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ],
            "description": "Exchange (`NSE`, `NFO`, `BSE`, `BFO`, `MCX`, ...)."
          },
          "instrument_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument type (`EQ`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
          },
          "symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Underlying symbol (the trading symbol for equities)."
          },
          "expiry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date (`YYYY-MM-DD`); empty for non-derivatives."
          },
          "strike": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Strike price; `0` for non-options."
          },
          "option_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`CE` / `PE`; empty for non-options."
          },
          "instrument_missing": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Present (`true`) only when the instrument is not known; the\ninstrument fields above are then absent."
          },
          "ltp": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Last traded price (added when a quote is available)."
          },
          "prev_close": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Previous close (`0` when unknown), sent with `ltp`."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "Product": {
        "type": "string",
        "description": "`MIS` (intraday), `CARRYFORWARD` (overnight derivatives, NRML),\n`DELIVERY` (equity delivery, CNC) or `MTF` (margin trading facility).",
        "enum": [
          "MIS",
          "CARRYFORWARD",
          "DELIVERY",
          "MTF"
        ]
      },
      "ProfileAuth": {
        "oneOf": [
          {
            "type": "object",
            "description": "Signed in to the app. `impersonated`: an operator acting as the user.",
            "required": [
              "impersonated",
              "scopes",
              "kind"
            ],
            "properties": {
              "impersonated": {
                "type": "boolean",
                "description": "`true` when an operator is acting as the user."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                },
                "description": "Always every scope."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "session"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "The user's own API key.",
            "required": [
              "key_id",
              "name",
              "scopes",
              "ip_allowlist",
              "kind"
            ],
            "properties": {
              "key_id": {
                "type": "string",
                "description": "The key's public id."
              },
              "name": {
                "type": "string",
                "description": "The user's name for the key."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                }
              },
              "ip_allowlist": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "IP addresses the key may be used from (empty: any address)."
              },
              "kind": {
                "type": "string",
                "enum": [
                  "api_key"
                ]
              }
            }
          },
          {
            "type": "object",
            "description": "A partner app the user connected (OAuth).",
            "required": [
              "client_id",
              "name",
              "scopes",
              "kind"
            ],
            "properties": {
              "client_id": {
                "type": "string",
                "description": "The partner app's client id."
              },
              "name": {
                "type": "string",
                "description": "The partner app's name."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                }
              },
              "kind": {
                "type": "string",
                "enum": [
                  "partner"
                ]
              }
            }
          }
        ],
        "description": "The credential of this request, told apart by `kind`: `session` (the\nsigned-in app), `api_key` or `partner` (a connected partner app)."
      },
      "ProtectRequest": {
        "type": "object",
        "description": "Protect an open position with a server-side stop-loss / target.",
        "required": [
          "account",
          "instrument_token",
          "side",
          "product",
          "quantity",
          "rules"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id (see `/v1/accounts`)."
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id (see `/v1/instruments`)."
          },
          "side": {
            "$ref": "#/components/schemas/Side",
            "description": "Side of the position's entry (BUY = long, protected by a SELL exit)."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units to exit when a level is hit.",
            "minimum": 0
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Entry / average price the levels are measured from; LTP if absent."
          },
          "rules": {
            "$ref": "#/components/schemas/Rules"
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "ProtectionRoute": {
        "type": "string",
        "description": "Where an order's protection lives: a broker `bracket` or `cover`\norder placed with the entry, a broker `gtt` placed once the entry\nfills, or a server-side `trigger` armed once the entry fills.",
        "enum": [
          "bracket",
          "cover",
          "gtt",
          "trigger"
        ]
      },
      "RegisteredPartnerApp": {
        "type": "object",
        "description": "A newly registered partner app, with its client secret (shown once).",
        "required": [
          "client_id",
          "owner",
          "name",
          "verified",
          "logo_url",
          "redirect_uris",
          "scopes",
          "created_at",
          "disabled",
          "client_secret",
          "note"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "OAuth client id (`cp_...`)."
          },
          "owner": {
            "type": "string",
            "description": "Username of the user who registered the app."
          },
          "name": {
            "type": "string",
            "description": "Name shown to users on the consent screen."
          },
          "verified": {
            "type": "boolean",
            "description": "Always `false` for a new app (see `PartnerApp.verified`)."
          },
          "logo_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "HTTPS URL of the app's logo."
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Exact redirect URIs a user may be sent back to."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "description": "The most a user can grant this partner."
          },
          "created_at": {
            "type": "string",
            "description": "RFC 3339 time of registration."
          },
          "disabled": {
            "type": "boolean",
            "description": "Always `false` for a new app."
          },
          "client_secret": {
            "type": "string",
            "description": "The client secret (`cps_...`). Shown only in this response: store it\nnow. Only its keyed hash is kept."
          },
          "note": {
            "type": "string",
            "description": "A reminder to store the secret."
          }
        }
      },
      "RevokedApiKey": {
        "type": "object",
        "description": "A revoked API key. Doc-only mirror of the body `revoke` builds.",
        "required": [
          "key_id",
          "revoked"
        ],
        "properties": {
          "key_id": {
            "type": "string"
          },
          "revoked": {
            "type": "boolean",
            "description": "Always `true`."
          }
        }
      },
      "RevokedPartnerConnection": {
        "type": "object",
        "description": "The connection was revoked.",
        "required": [
          "client_id",
          "revoked"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "revoked": {
            "type": "boolean",
            "description": "Always `true`."
          }
        }
      },
      "RevokedSignalUrl": {
        "type": "object",
        "description": "A revoked signal URL. Doc-only mirror of the body `revoke` builds.",
        "required": [
          "endpoint_id",
          "revoked"
        ],
        "properties": {
          "endpoint_id": {
            "type": "string"
          },
          "revoked": {
            "type": "boolean",
            "description": "Always `true`."
          }
        }
      },
      "RotatedPartnerSecret": {
        "type": "object",
        "description": "A rotated client secret (shown once).",
        "required": [
          "client_id",
          "client_secret",
          "previous_secret_expires_at"
        ],
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": "string",
            "description": "The new secret (`cps_...`); store it now, it is never shown again."
          },
          "previous_secret_expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Until when the previous secret is still accepted."
          }
        }
      },
      "Rule": {
        "type": "object",
        "description": "One leg of protection.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Off unless `true`."
          },
          "type": {
            "$ref": "#/components/schemas/RuleType"
          },
          "value": {
            "type": "number",
            "format": "double",
            "description": "Greater than 0 when enabled."
          }
        }
      },
      "RuleType": {
        "type": "string",
        "description": "How a rule's `value` is read: `percentage` of the entry price,\n`points` from it, or an absolute `price`. Case-insensitive in requests.",
        "enum": [
          "percentage",
          "points",
          "price"
        ]
      },
      "Rules": {
        "type": "object",
        "description": "Stop-loss, target and trailing stop-loss. Enable a stop-loss, a\ntarget or both; a trail needs a stop-loss and is `percentage` or\n`points`.",
        "properties": {
          "target": {
            "$ref": "#/components/schemas/Rule"
          },
          "stop_loss": {
            "$ref": "#/components/schemas/Rule"
          },
          "trail": {
            "$ref": "#/components/schemas/Rule"
          }
        }
      },
      "Scope": {
        "type": "string",
        "description": "What an API key or partner token may do: `read` (portfolio, orders,\ntriggers, GTT and activity reads; the stream), `orders` (place, modify,\ncancel and convert orders, bracket orders, GTT) or `triggers` (create,\nchange and remove server-side triggers). App sessions may do everything.",
        "enum": [
          "read",
          "orders",
          "triggers"
        ]
      },
      "ShareAccountScope": {
        "oneOf": [
          {
            "type": "string",
            "description": "Every account of the owner, current and future.",
            "enum": [
              "all"
            ]
          },
          {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Only these account ids."
          }
        ],
        "description": "Which of the owner's accounts the share covers: `\"all\"` or a list of account ids."
      },
      "ShareScope": {
        "type": "string",
        "description": "What an owner shared: `login` (account list and login status), `funds`,\n`positions`, `holdings`, `open_orders`, `order_history`.",
        "enum": [
          "login",
          "funds",
          "positions",
          "holdings",
          "open_orders",
          "order_history"
        ]
      },
      "SharedAccount": {
        "type": "object",
        "description": "One shared account: non-secret facts only.",
        "required": [
          "client_id",
          "broker",
          "account_tag",
          "last_login_at",
          "logged_in_today"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The broker account id."
          },
          "broker": {
            "type": "string",
            "description": "Broker id (`zerodha`, `upstox`, ...)."
          },
          "account_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "The owner's label for the account."
          },
          "last_login_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "Last broker login, as text (Unix seconds); `null` when unknown."
          },
          "logged_in_today": {
            "type": "boolean",
            "description": "Logged in since the start of the current trading day (08:00 IST)."
          }
        }
      },
      "SharedAccountCard": {
        "type": "object",
        "description": "One shared account on the consolidated screen. Balances need `funds`,\nP&L and counts `positions` (holdings count: `holdings`); the account\nfacts (`broker`, `account_tag`, `last_login_at`, `logged_in_today`) are\npresent only with `login`.",
        "required": [
          "client_id",
          "has_login",
          "has_funds",
          "has_positions",
          "opening_balance",
          "usable_balance",
          "utilisation",
          "pnl",
          "positions_count",
          "holdings_count"
        ],
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The broker account id."
          },
          "has_login": {
            "type": "boolean",
            "description": "Whether `login` is shared (the account facts below are present)."
          },
          "has_funds": {
            "type": "boolean",
            "description": "Whether `funds` is shared."
          },
          "has_positions": {
            "type": "boolean",
            "description": "Whether `positions` is shared."
          },
          "opening_balance": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Opening balance; `null` without funds data."
          },
          "usable_balance": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Available funds; `null` without funds data."
          },
          "utilisation": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Funds in use; `null` without funds data."
          },
          "pnl": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Sum of the positions' P&L; `null` without open positions."
          },
          "positions_count": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "holdings_count": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "broker": {
            "type": [
              "string",
              "null"
            ],
            "description": "With `login`: broker id."
          },
          "account_tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "With `login`: the owner's label for the account (may be `null`)."
          },
          "last_login_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "With `login`: last broker login (Unix seconds as text; may be `null`)."
          },
          "logged_in_today": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "With `login`: logged in since 08:00 IST today."
          }
        }
      },
      "SharedAccountData": {
        "type": "object",
        "description": "One shared account's data.",
        "required": [
          "account",
          "updated_at",
          "data"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "The broker account id."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the data was last read from the broker (orders: the latest\nbroker update); `null` when unknown."
          },
          "data": {
            "$ref": "#/components/schemas/SharedRows"
          }
        }
      },
      "SharedAccounts": {
        "type": "object",
        "description": "`accounts` view: the shared accounts.",
        "required": [
          "accounts"
        ],
        "properties": {
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SharedAccount"
            }
          }
        }
      },
      "SharedConsolidated": {
        "type": "object",
        "description": "Every shared account on one screen.",
        "required": [
          "owners",
          "positions"
        ],
        "properties": {
          "owners": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SharedOwnerSummary"
            }
          },
          "positions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SharedPositionRow"
            },
            "description": "Every shared position, across owners and accounts."
          }
        }
      },
      "SharedConsolidatedRefresh": {
        "type": "object",
        "description": "A refresh request for every owner.",
        "required": [
          "owners",
          "dispatched"
        ],
        "properties": {
          "owners": {
            "type": "integer",
            "format": "int64",
            "description": "Owners sharing with the caller.",
            "minimum": 0
          },
          "dispatched": {
            "type": "integer",
            "format": "int64",
            "description": "Owners actually refreshed (the others were refreshed moments ago).",
            "minimum": 0
          }
        }
      },
      "SharedGrant": {
        "type": "object",
        "description": "A share another user granted to the caller.",
        "required": [
          "owner_username",
          "owner_name",
          "scopes",
          "account_scope"
        ],
        "properties": {
          "owner_username": {
            "type": "string",
            "description": "Username of the owner (the path segment `{owner}` of the other\nshared routes)."
          },
          "owner_name": {
            "type": "string",
            "description": "The owner's display name (their username when none is set)."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShareScope"
            },
            "description": "What the owner shared."
          },
          "account_scope": {
            "$ref": "#/components/schemas/ShareAccountScope"
          }
        }
      },
      "SharedMissingAccount": {
        "type": "object",
        "description": "A shared account with no data yet.",
        "required": [
          "account",
          "reason"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "The broker account id."
          },
          "reason": {
            "type": "string",
            "description": "Why there is no data."
          }
        }
      },
      "SharedOwnerSummary": {
        "type": "object",
        "description": "One owner on the consolidated screen: the share and its accounts.",
        "required": [
          "owner_username",
          "owner_name",
          "scopes",
          "account_scope",
          "accounts"
        ],
        "properties": {
          "owner_username": {
            "type": "string",
            "description": "Username of the owner."
          },
          "owner_name": {
            "type": "string",
            "description": "The owner's display name."
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShareScope"
            },
            "description": "What the owner shared."
          },
          "account_scope": {
            "$ref": "#/components/schemas/ShareAccountScope"
          },
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SharedAccountCard"
            }
          }
        }
      },
      "SharedPortfolio": {
        "type": "object",
        "description": "`positions`, `holdings`, `margins`, `open_orders` and `order_history`\nviews: one entry per shared account with data; the others under\n`missing`.",
        "required": [
          "accounts",
          "missing"
        ],
        "properties": {
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SharedAccountData"
            }
          },
          "missing": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SharedMissingAccount"
            }
          }
        }
      },
      "SharedPositionRow": {
        "type": "object",
        "description": "A position row from a shared account (see `PositionRow`) plus its owner.",
        "required": [
          "account",
          "instrument_token",
          "tradingsymbol",
          "product",
          "net_qty",
          "buy_qty",
          "sell_qty",
          "buy_value",
          "sell_value",
          "average_price",
          "buy_average_price",
          "sell_average_price",
          "pnl",
          "owner_username",
          "owner_name"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "instrument_token": {
            "type": "string"
          },
          "tradingsymbol": {
            "type": "string"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "net_qty": {
            "type": "integer",
            "format": "int64",
            "description": "Positive long, negative short."
          },
          "buy_qty": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "sell_qty": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "buy_value": {
            "type": "number",
            "format": "double"
          },
          "sell_value": {
            "type": "number",
            "format": "double"
          },
          "average_price": {
            "type": "number",
            "format": "double"
          },
          "buy_average_price": {
            "type": "number",
            "format": "double"
          },
          "sell_average_price": {
            "type": "number",
            "format": "double"
          },
          "pnl": {
            "type": "number",
            "format": "double",
            "description": "Mark-to-market P&L as reported by the broker."
          },
          "lot_size": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Contract lot size (added when the instrument is known).",
            "minimum": 0
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ],
            "description": "Exchange (`NSE`, `NFO`, `BSE`, `BFO`, `MCX`, ...)."
          },
          "instrument_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument type (`EQ`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
          },
          "symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Underlying symbol (the trading symbol for equities)."
          },
          "expiry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date (`YYYY-MM-DD`); empty for non-derivatives."
          },
          "strike": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Strike price; `0` for non-options."
          },
          "option_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`CE` / `PE`; empty for non-options."
          },
          "instrument_missing": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Present (`true`) only when the instrument is not known; the\ninstrument fields above are then absent."
          },
          "ltp": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Last traded price (added when a quote is available)."
          },
          "prev_close": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Previous close (`0` when unknown), sent with `ltp`."
          },
          "owner_username": {
            "type": "string",
            "description": "Username of the owner."
          },
          "owner_name": {
            "type": "string",
            "description": "The owner's display name."
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "SharedRefresh": {
        "type": "object",
        "description": "A refresh request for one owner.",
        "required": [
          "requested"
        ],
        "properties": {
          "requested": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Accounts asked to refresh; `null` when the owner was refreshed\nmoments ago (within 10 seconds, by anyone) and nothing was asked.",
            "minimum": 0
          }
        }
      },
      "SharedRows": {
        "anyOf": [
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PositionRow"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HoldingRow"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderData"
            }
          },
          {
            "$ref": "#/components/schemas/MarginRow"
          }
        ],
        "description": "`positions`, `holdings`, `open_orders`, `order_history`: a list of rows (may be empty); `margins`: one object."
      },
      "SharedViewData": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/SharedAccounts"
          },
          {
            "$ref": "#/components/schemas/SharedPortfolio"
          }
        ],
        "description": "`accounts`: `SharedAccounts`; every other view: `SharedPortfolio`."
      },
      "Side": {
        "type": "string",
        "description": "Order side.",
        "enum": [
          "BUY",
          "SELL"
        ]
      },
      "SignalDeliveryOutcome": {
        "type": "string",
        "description": "A delivery's result in one word: `placed` (every order it asked for\nwas placed), `partially_placed`, `failed` (orders were attempted, none\nplaced), `processed` (handled without new orders: levels updated,\nlifecycle event...), `ignored` (valid, but the strategy's rules meant\nnothing to do), `refused` (wrong secret or signature, unreadable\npayload), `duplicate` (the same alert again; skipped) or `rate_limited`\n(over the URL's limit; not processed).",
        "enum": [
          "placed",
          "partially_placed",
          "failed",
          "processed",
          "ignored",
          "refused",
          "duplicate",
          "rate_limited"
        ]
      },
      "SignalDryRun": {
        "type": "object",
        "description": "What a delivery of the payload would do, without doing it.",
        "required": [
          "valid",
          "errors",
          "warnings",
          "would_place"
        ],
        "properties": {
          "valid": {
            "type": "boolean",
            "description": "True when `errors` is empty: a real delivery would be acted on."
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Why a real delivery would place nothing, in plain words."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What it would skip, or could not check (e.g. an unsigned Kuberhunt\ntest, a sample payload, test mode on the strategy)."
          },
          "would_place": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignalWouldPlace"
            },
            "description": "The orders it would place."
          }
        }
      },
      "SignalProvider": {
        "type": "string",
        "description": "The signal provider a URL is for: `tradingview` (TradingView alerts),\n`chartink` (Chartink scanner alerts) or `kuberhunt` (Kuberhunt\nrecommendation events).",
        "enum": [
          "kuberhunt",
          "tradingview",
          "chartink"
        ]
      },
      "SignalUrl": {
        "type": "object",
        "description": "A live signal URL (never its secret).",
        "required": [
          "endpoint_id",
          "kind",
          "strategy_id",
          "created_at",
          "has_body_secret"
        ],
        "properties": {
          "endpoint_id": {
            "type": "string",
            "description": "Public id (`we_...`), kept across rotations."
          },
          "kind": {
            "$ref": "#/components/schemas/SignalProvider"
          },
          "strategy_id": {
            "type": "string",
            "description": "The strategy the URL's signals trade."
          },
          "created_at": {
            "type": "string",
            "description": "When this URL (its current secret) was issued (RFC 3339)."
          },
          "has_body_secret": {
            "type": "boolean",
            "description": "TradingView: alerts must carry the body secret."
          }
        }
      },
      "SignalUrlDelivery": {
        "type": "object",
        "description": "One request a signal URL received (never the payload or the secret).",
        "required": [
          "delivery_id",
          "at",
          "provider",
          "outcome",
          "reason",
          "orders_placed",
          "order_ids",
          "http_status",
          "request_id"
        ],
        "properties": {
          "delivery_id": {
            "type": "string",
            "description": "Delivery id (sorts by arrival)."
          },
          "at": {
            "type": "string",
            "format": "date-time",
            "description": "When it arrived."
          },
          "provider": {
            "$ref": "#/components/schemas/SignalProvider"
          },
          "outcome": {
            "$ref": "#/components/schemas/SignalDeliveryOutcome"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why, in plain words; null when there is nothing to explain."
          },
          "orders_placed": {
            "type": "integer",
            "format": "int64",
            "description": "Orders it placed (one per account slice).",
            "minimum": 0
          },
          "order_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Broker order ids of the orders it placed."
          },
          "http_status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status the provider was answered with.",
            "minimum": 0
          },
          "request_id": {
            "type": "string",
            "description": "The request's id, for support."
          }
        }
      },
      "SignalUrlDeliveryPage": {
        "type": "object",
        "description": "One page of deliveries, newest first.",
        "required": [
          "items",
          "next_cursor"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignalUrlDelivery"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "SignalWouldPlace": {
        "type": "object",
        "description": "One order a delivery would place, per account, sized and priced as the\norder path would.",
        "required": [
          "account",
          "symbol",
          "exchange",
          "side",
          "qty",
          "order_type",
          "price",
          "product"
        ],
        "properties": {
          "account": {
            "type": "string",
            "description": "Account id."
          },
          "symbol": {
            "type": "string",
            "description": "Trading symbol."
          },
          "exchange": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "qty": {
            "type": "integer",
            "format": "int64",
            "description": "Quantity (units, not lots).",
            "minimum": 0
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType"
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Limit price (0 for market orders)."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          }
        }
      },
      "SliceResult": {
        "type": "object",
        "description": "The outcome of one order in one account (one slice; an order above\nthe exchange freeze quantity is split into several).",
        "required": [
          "order_index",
          "account",
          "instrument_token",
          "order_tag",
          "quantity",
          "status",
          "order_id",
          "message",
          "order_type",
          "price"
        ],
        "properties": {
          "order_index": {
            "type": "integer",
            "description": "Index of the order in the request.",
            "minimum": 0
          },
          "account": {
            "type": "string"
          },
          "instrument_token": {
            "type": "string",
            "description": "Instrument id."
          },
          "order_tag": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OrderTag",
                "description": "Order tag for this slice; present once a broker call was attempted."
              },
              {
                "type": "null"
              }
            ]
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Units sent to the broker (after lot and multiplier sizing).",
            "minimum": 0
          },
          "status": {
            "$ref": "#/components/schemas/SliceStatus"
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker order id, when accepted."
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it was rejected, or what is unknown."
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType",
            "description": "Final order type/price after market protection."
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "protection": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ProtectionRoute",
                "description": "Where this slice's protection lives; absent for unprotected orders."
              },
              {
                "type": "null"
              }
            ]
          },
          "protection_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker basket id when the broker holds the legs from placement."
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token",
          "cirrus_tag": "order_tag"
        }
      },
      "SliceStatus": {
        "type": "string",
        "description": "`accepted` (the broker took it; fills arrive on the stream),\n`rejected` (refused before or by the broker; nothing was placed) or\n`unknown` (the broker may or may not have it, e.g. a timeout;\nreconciliation settles it: never retry blindly).",
        "enum": [
          "accepted",
          "rejected",
          "unknown"
        ]
      },
      "SnapshotData": {
        "anyOf": [
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderData"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PositionRow"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HoldingRow"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TradeRow"
            }
          },
          {
            "$ref": "#/components/schemas/MarginRow"
          }
        ],
        "description": "`orders`, `positions`, `holdings`, `trades`: a list of rows (may be empty); `margins`: one object."
      },
      "StatusChange": {
        "type": "object",
        "description": "One entry in an order's audit trail.",
        "required": [
          "from",
          "to",
          "at",
          "message"
        ],
        "properties": {
          "from": {
            "$ref": "#/components/schemas/OrderState"
          },
          "to": {
            "$ref": "#/components/schemas/OrderState"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "The broker's status text at this step, if any."
          }
        }
      },
      "SuccessStatus": {
        "type": "string",
        "description": "Always `success`.",
        "enum": [
          "success"
        ]
      },
      "Success_AccountDetail": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "allOf": [
              {
                "type": "object",
                "description": "One linked broker account and whether it can trade. Never a\ncredential.",
                "required": [
                  "account",
                  "broker",
                  "broker_name",
                  "tag",
                  "multiplier",
                  "supported",
                  "status",
                  "missing",
                  "updates",
                  "static_ip",
                  "last_login_at",
                  "session_expires_at",
                  "seat_assigned",
                  "last_update_at"
                ],
                "properties": {
                  "account": {
                    "type": "string",
                    "description": "Account id (the broker's client code), as used in an order's\n`accounts` and the `account` filters."
                  },
                  "broker": {
                    "type": "string",
                    "description": "Broker id (`zerodha`, `upstox`, `paper`, ...)."
                  },
                  "broker_name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Broker display name; null for an unknown broker."
                  },
                  "tag": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The user's own label for the account."
                  },
                  "multiplier": {
                    "type": "number",
                    "format": "double",
                    "description": "Quantity multiplier applied when an order is placed in this account."
                  },
                  "supported": {
                    "type": "boolean",
                    "description": "Whether the broker is supported for trading."
                  },
                  "status": {
                    "$ref": "#/components/schemas/AccountReadiness"
                  },
                  "missing": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/AccountMissingField"
                    },
                    "description": "Fields the account lacks (empty when complete)."
                  },
                  "updates": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/AccountUpdates",
                        "description": "Null for an unsupported broker."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "static_ip": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The account's static IP address, if one is assigned."
                  },
                  "last_login_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Last broker login."
                  },
                  "session_expires_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the broker session expires; null when there is no active\nsession (always null for paper accounts, which need none)."
                  },
                  "seat_assigned": {
                    "type": [
                      "boolean",
                      "null"
                    ],
                    "description": "Whether the account has a trading seat assigned (null when unknown)."
                  },
                  "last_update_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the order book was last read from the broker."
                  }
                }
              },
              {
                "type": "object",
                "required": [
                  "health"
                ],
                "properties": {
                  "health": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/AccountHealth",
                        "description": "Null when no live worker has reported for the account recently."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            ],
            "description": "One linked broker account plus what its live worker last reported."
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_AccountList": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The caller's linked broker accounts, sorted by id.",
            "required": [
              "items"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AccountView"
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_ActivityPage": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "One page of a day's activity, newest first.",
            "required": [
              "items",
              "next_cursor",
              "source"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ActivityRecord"
                },
                "description": "Records without `timeline` (see `GET /v1/activity/{id}`)."
              },
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Pass as `cursor` for the next (older) page; null on the last page."
              },
              "source": {
                "$ref": "#/components/schemas/ActivityPageSource"
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_ActivityRecord": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "One activity-log record: something that happened to the user's\naccounts, in plain English, with the per-account results.",
            "required": [
              "id",
              "username",
              "at",
              "kind",
              "category",
              "source",
              "request_id",
              "instrument",
              "side",
              "order_type",
              "product",
              "quantity",
              "price",
              "trigger_price",
              "summary",
              "message",
              "outcome",
              "duration_ms",
              "accounts"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "ULID (sorts by creation time)."
              },
              "username": {
                "type": "string"
              },
              "at": {
                "type": "string",
                "format": "date-time",
                "description": "When the action started."
              },
              "kind": {
                "$ref": "#/components/schemas/ActivityKind"
              },
              "category": {
                "$ref": "#/components/schemas/ActivityCategory"
              },
              "source": {
                "$ref": "#/components/schemas/ActivitySource"
              },
              "request_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The `x-request-id` of the API call that started it, if any."
              },
              "instrument": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/ActivityInstrument"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "side": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Side"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "order_type": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "`MARKET`, `LIMIT`, `SL` or `SL_M`."
              },
              "product": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "`MIS`, `CARRYFORWARD`, `DELIVERY` or `MTF`."
              },
              "quantity": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int64",
                "minimum": 0
              },
              "price": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double"
              },
              "trigger_price": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double"
              },
              "summary": {
                "type": "string"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Plain reason for records without a per-account result (an ignored\nsignal, a lost session, protection that failed...)."
              },
              "outcome": {
                "$ref": "#/components/schemas/ActivityOutcome"
              },
              "duration_ms": {
                "type": "integer",
                "format": "int64",
                "minimum": 0
              },
              "accounts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AccountResult"
                }
              },
              "timeline": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "$ref": "#/components/schemas/TimelineEntry"
                },
                "description": "Only on detail responses and in the archive."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_AmendResult": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The broker's answer to a modify or cancel. `status`: `accepted` (the\nbroker took the change; the order book follows on the stream),\n`rejected` (refused, e.g. by the broker or the account's order rate\nlimit; `message` says why) or `unknown` (no answer in time: check the\norder book before retrying).",
            "required": [
              "account",
              "order_id",
              "status",
              "message"
            ],
            "properties": {
              "account": {
                "type": "string"
              },
              "order_id": {
                "type": "string"
              },
              "status": {
                "$ref": "#/components/schemas/SliceStatus"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Why it was rejected, or what is unknown; null when accepted."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_BracketResult": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The broker's answer. `status`: `accepted`, `rejected` (`message` says\nwhy) or `unknown` (no answer in time: check the order book before\nretrying).",
            "required": [
              "account",
              "basket_id",
              "order_id",
              "status",
              "message"
            ],
            "properties": {
              "account": {
                "type": "string"
              },
              "basket_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Broker basket / parent id (placement only; null otherwise)."
              },
              "order_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The order changed or cancelled (null on placement)."
              },
              "status": {
                "$ref": "#/components/schemas/SliceStatus"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Why it was rejected, or what is unknown; null when accepted."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_ConvertResult": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The broker's answer: `accepted` (positions refresh shortly),\n`rejected` (`message` says why) or `unknown` (no answer in time: check\npositions before retrying).",
            "required": [
              "account",
              "status",
              "message"
            ],
            "properties": {
              "account": {
                "type": "string"
              },
              "status": {
                "$ref": "#/components/schemas/SliceStatus"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Why it was rejected, or what is unknown; null when accepted."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_CreatedApiKey": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A new API key with its secret (shown only here). Doc-only mirror of the\nbody `create` builds.",
            "required": [
              "key_id",
              "name",
              "scopes",
              "ip_allowlist",
              "created_at",
              "last_used_at",
              "api_secret",
              "note"
            ],
            "properties": {
              "key_id": {
                "type": "string",
                "description": "Public key id (`ck_...`)."
              },
              "name": {
                "type": "string"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                }
              },
              "ip_allowlist": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "IP addresses the key may be used from; empty = any."
              },
              "created_at": {
                "type": "string",
                "description": "When the key was created (RFC 3339)."
              },
              "last_used_at": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Always null for a new key."
              },
              "api_secret": {
                "type": "string",
                "description": "The key secret (`cs_...`). Store it now: it is never shown again.\nAuthenticate with `Authorization: token <key_id>:<api_secret>`."
              },
              "note": {
                "type": "string",
                "description": "A reminder that the secret is shown only once."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_DeletedWebhook": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A deleted webhook. Doc-only mirror of the body `remove` builds.",
            "required": [
              "id",
              "deleted"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "deleted": {
                "type": "boolean",
                "description": "Always `true`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_DisabledPartnerApp": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The app was disabled.",
            "required": [
              "client_id",
              "disabled"
            ],
            "properties": {
              "client_id": {
                "type": "string"
              },
              "disabled": {
                "type": "boolean",
                "description": "Always `true`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_GttResult": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The broker's answer. `status`: `accepted`, `rejected` (`message` says\nwhy) or `unknown` (no answer in time: list the account's GTTs before\nretrying).",
            "required": [
              "account",
              "trigger_id",
              "status",
              "message"
            ],
            "properties": {
              "account": {
                "type": "string"
              },
              "trigger_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The broker's GTT id; null when creating failed."
              },
              "status": {
                "$ref": "#/components/schemas/SliceStatus"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Why it was rejected, or what is unknown; null when accepted."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_InstrumentRow": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "One instrument, as in the instrument list (a field the source lacks is\nnull).",
            "required": [
              "instrument_token",
              "exchange",
              "instrument",
              "exchange_token",
              "lot_size",
              "expiry",
              "strike",
              "option_type",
              "tick_size",
              "underlying_symbol",
              "isin",
              "freeze_qty",
              "name",
              "tradingsymbol",
              "sector",
              "indices"
            ],
            "properties": {
              "instrument_token": {
                "type": "string",
                "description": "Instrument id: what orders, triggers and every row call\n`instrument_token`."
              },
              "exchange": {
                "type": "string",
                "description": "Exchange (`NSE`, `BSE`, `NFO`, `BFO`, `MCX`, ...), upper case."
              },
              "instrument": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Instrument type (`EQUITY`, `INDEX`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
              },
              "exchange_token": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The exchange's own token for the instrument."
              },
              "lot_size": {
                "type": "integer",
                "format": "int64",
                "description": "Contract lot size; `0` for indices (not tradable).",
                "minimum": 0
              },
              "expiry": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Expiry date (`YYYY-MM-DD`); null for non-derivatives."
              },
              "strike": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double",
                "description": "Strike price; null for non-options."
              },
              "option_type": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "`CE` / `PE`; null for non-options."
              },
              "tick_size": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double",
                "description": "Smallest price step."
              },
              "underlying_symbol": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Underlying symbol (derivatives), or the stock's own symbol."
              },
              "isin": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "freeze_qty": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int64",
                "description": "Exchange freeze quantity: larger orders are split into slices.",
                "minimum": 0
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Company or instrument name."
              },
              "tradingsymbol": {
                "type": "string",
                "description": "Trading symbol, as the exchange lists it."
              },
              "sector": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "indices": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Index memberships (e.g. `NIFTY 50`); empty when none."
              }
            },
            "x-deprecated-aliases": {
              "cirrus_token": "instrument_token"
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_InstrumentSearchResult": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Matching instruments, best match first.",
            "required": [
              "items",
              "count"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/InstrumentRow"
                }
              },
              "count": {
                "type": "integer",
                "description": "Number of `items`.",
                "minimum": 0
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_IssuedSignalUrl": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A new signal URL (issued or rotated). Its path and body secret are\nshown only in this response. Doc-only mirror of the body the handlers\nbuild.",
            "required": [
              "endpoint_id",
              "kind",
              "strategy_id",
              "created_at",
              "has_body_secret",
              "path",
              "body_secret",
              "note"
            ],
            "properties": {
              "endpoint_id": {
                "type": "string",
                "description": "Public id (`we_...`), kept across rotations."
              },
              "kind": {
                "$ref": "#/components/schemas/SignalProvider"
              },
              "strategy_id": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "description": "When this URL was issued (RFC 3339)."
              },
              "has_body_secret": {
                "type": "boolean",
                "description": "TradingView: alerts must carry `body_secret`."
              },
              "path": {
                "type": "string",
                "description": "The path to give the provider, prefixed with the API origin\n(`/v1/hooks/{kind}/wh_...`). It is the credential: keep it private."
              },
              "body_secret": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "TradingView only: put `\"secret\": \"<this>\"` (`tvs_...`) in the alert\nmessage. Null for other providers."
              },
              "note": {
                "type": "string",
                "description": "A reminder that the URL is shown only once."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_OAuthAuthorizeResponse": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Where to send the user's browser after approval.",
            "required": [
              "redirect_url"
            ],
            "properties": {
              "redirect_url": {
                "type": "string",
                "description": "The registered `redirect_uri` with `code` (single use, valid 60\nseconds) and, when one was sent, `state` (URL-encoded) appended to\nits query, e.g. `https://partner.example/cb?code=oc_...&state=xyz`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_OAuthConsent": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "What the consent screen shows before the user approves.",
            "required": [
              "client_id",
              "name",
              "logo_url",
              "verified",
              "scopes"
            ],
            "properties": {
              "client_id": {
                "type": "string",
                "description": "The partner app's client id."
              },
              "name": {
                "type": "string",
                "description": "The app's name."
              },
              "logo_url": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "HTTPS URL of the app's logo."
              },
              "verified": {
                "type": "boolean",
                "description": "`false`: warn the user that the app's name is not verified."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                },
                "description": "The scopes requested (validated, duplicates removed)."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_OrderMarginResponse": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Margin per order and account, and the total.",
            "required": [
              "results",
              "total_required"
            ],
            "properties": {
              "results": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OrderMarginResult"
                }
              },
              "total_required": {
                "type": "number",
                "format": "double",
                "description": "Sum over results that have a figure."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_PlaceOrdersResponse": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Per-slice results (some accounts may succeed while others are\nrefused) and the count of each status.",
            "required": [
              "results",
              "accepted",
              "rejected",
              "unknown"
            ],
            "properties": {
              "results": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SliceResult"
                }
              },
              "accepted": {
                "type": "integer",
                "minimum": 0
              },
              "rejected": {
                "type": "integer",
                "minimum": 0
              },
              "unknown": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_PortfolioRefresh": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A refresh was requested.",
            "required": [
              "requested"
            ],
            "properties": {
              "requested": {
                "type": "integer",
                "description": "How many accounts were asked to re-read.",
                "minimum": 0
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_PortfolioResponse": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Per-account data of one kind; accounts without data are listed under\n`missing`, never silently left out.",
            "required": [
              "accounts",
              "missing"
            ],
            "properties": {
              "accounts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PortfolioAccountData"
                }
              },
              "missing": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PortfolioMissing"
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_RegisteredPartnerApp": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A newly registered partner app, with its client secret (shown once).",
            "required": [
              "client_id",
              "owner",
              "name",
              "verified",
              "logo_url",
              "redirect_uris",
              "scopes",
              "created_at",
              "disabled",
              "client_secret",
              "note"
            ],
            "properties": {
              "client_id": {
                "type": "string",
                "description": "OAuth client id (`cp_...`)."
              },
              "owner": {
                "type": "string",
                "description": "Username of the user who registered the app."
              },
              "name": {
                "type": "string",
                "description": "Name shown to users on the consent screen."
              },
              "verified": {
                "type": "boolean",
                "description": "Always `false` for a new app (see `PartnerApp.verified`)."
              },
              "logo_url": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "HTTPS URL of the app's logo."
              },
              "redirect_uris": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Exact redirect URIs a user may be sent back to."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Scope"
                },
                "description": "The most a user can grant this partner."
              },
              "created_at": {
                "type": "string",
                "description": "RFC 3339 time of registration."
              },
              "disabled": {
                "type": "boolean",
                "description": "Always `false` for a new app."
              },
              "client_secret": {
                "type": "string",
                "description": "The client secret (`cps_...`). Shown only in this response: store it\nnow. Only its keyed hash is kept."
              },
              "note": {
                "type": "string",
                "description": "A reminder to store the secret."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_RevokedApiKey": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A revoked API key. Doc-only mirror of the body `revoke` builds.",
            "required": [
              "key_id",
              "revoked"
            ],
            "properties": {
              "key_id": {
                "type": "string"
              },
              "revoked": {
                "type": "boolean",
                "description": "Always `true`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_RevokedPartnerConnection": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The connection was revoked.",
            "required": [
              "client_id",
              "revoked"
            ],
            "properties": {
              "client_id": {
                "type": "string"
              },
              "revoked": {
                "type": "boolean",
                "description": "Always `true`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_RevokedSignalUrl": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A revoked signal URL. Doc-only mirror of the body `revoke` builds.",
            "required": [
              "endpoint_id",
              "revoked"
            ],
            "properties": {
              "endpoint_id": {
                "type": "string"
              },
              "revoked": {
                "type": "boolean",
                "description": "Always `true`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_RotatedPartnerSecret": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A rotated client secret (shown once).",
            "required": [
              "client_id",
              "client_secret",
              "previous_secret_expires_at"
            ],
            "properties": {
              "client_id": {
                "type": "string"
              },
              "client_secret": {
                "type": "string",
                "description": "The new secret (`cps_...`); store it now, it is never shown again."
              },
              "previous_secret_expires_at": {
                "type": "string",
                "format": "date-time",
                "description": "Until when the previous secret is still accepted."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_SharedConsolidated": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Every shared account on one screen.",
            "required": [
              "owners",
              "positions"
            ],
            "properties": {
              "owners": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SharedOwnerSummary"
                }
              },
              "positions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SharedPositionRow"
                },
                "description": "Every shared position, across owners and accounts."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_SharedConsolidatedRefresh": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A refresh request for every owner.",
            "required": [
              "owners",
              "dispatched"
            ],
            "properties": {
              "owners": {
                "type": "integer",
                "format": "int64",
                "description": "Owners sharing with the caller.",
                "minimum": 0
              },
              "dispatched": {
                "type": "integer",
                "format": "int64",
                "description": "Owners actually refreshed (the others were refreshed moments ago).",
                "minimum": 0
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_SharedRefresh": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A refresh request for one owner.",
            "required": [
              "requested"
            ],
            "properties": {
              "requested": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int64",
                "description": "Accounts asked to refresh; `null` when the owner was refreshed\nmoments ago (within 10 seconds, by anyone) and nothing was asked.",
                "minimum": 0
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_SharedViewData": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SharedAccounts"
              },
              {
                "$ref": "#/components/schemas/SharedPortfolio"
              }
            ],
            "description": "`accounts`: `SharedAccounts`; every other view: `SharedPortfolio`."
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_SignalDryRun": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "What a delivery of the payload would do, without doing it.",
            "required": [
              "valid",
              "errors",
              "warnings",
              "would_place"
            ],
            "properties": {
              "valid": {
                "type": "boolean",
                "description": "True when `errors` is empty: a real delivery would be acted on."
              },
              "errors": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Why a real delivery would place nothing, in plain words."
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "What it would skip, or could not check (e.g. an unsigned Kuberhunt\ntest, a sample payload, test mode on the strategy)."
              },
              "would_place": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SignalWouldPlace"
                },
                "description": "The orders it would place."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_SignalUrlDeliveryPage": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "One page of deliveries, newest first.",
            "required": [
              "items",
              "next_cursor"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SignalUrlDelivery"
                }
              },
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Pass as `cursor` for the next page; null on the last page."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_TriggerDeleted": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "`DELETE /v1/triggers/{id}` result (built with `json!`; documentation\nonly).",
            "required": [
              "trigger_id",
              "deleted"
            ],
            "properties": {
              "trigger_id": {
                "type": "string"
              },
              "deleted": {
                "type": "boolean",
                "description": "Always `true`."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_TriggerView": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Stop-loss / target protection on a position, with its live levels.",
            "required": [
              "trigger_id",
              "account",
              "instrument_token",
              "name",
              "side",
              "product",
              "quantity",
              "price",
              "order_id",
              "broker_order_id",
              "kind",
              "exits",
              "rules",
              "stop_loss_price",
              "initial_stop_loss_price",
              "target_price",
              "live",
              "status",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "trigger_id": {
                "type": "string"
              },
              "account": {
                "type": "string",
                "description": "Account id (see `/v1/accounts`)."
              },
              "instrument_token": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Instrument id."
              },
              "name": {
                "type": "string",
                "description": "Enabled rules: `SL`, `TGT`, `TSL`, joined with ` + `."
              },
              "side": {
                "type": "string",
                "description": "Side of the protected entry: `BUY` (a long position, exited by a\nSELL) or `SELL`."
              },
              "product": {
                "type": "string",
                "description": "Product of the position (`MIS`, `CARRYFORWARD`, `DELIVERY`, `MTF`)."
              },
              "quantity": {
                "type": "integer",
                "format": "int64",
                "description": "Quantity the exit covers, in units.",
                "minimum": 0
              },
              "price": {
                "type": "number",
                "format": "double",
                "description": "Entry / average price the levels are measured from."
              },
              "order_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The protected entry order, when the trigger came with one."
              },
              "broker_order_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Broker id of the order / GTT holding the legs (broker-held only)."
              },
              "kind": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Where the protection lives: `platform` (a server-side\ntrigger; the server places the exit), `bracket` or `cover` (broker\nbracket / cover order legs), `gtt_oco` or `gtt_single` (broker GTT\nwith two legs or one). Null for triggers created without a kind;\nother values may appear for triggers created elsewhere."
              },
              "exits": {
                "type": "boolean",
                "description": "The server (not the broker) places the exit when a level is hit.\n`false`: the broker holds the legs, so change or cancel them at the\nbroker (only delete works here)."
              },
              "rules": {
                "$ref": "#/components/schemas/TriggerRulesView"
              },
              "stop_loss_price": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double",
                "description": "Current stop-loss level (moves when trailing); null when disabled."
              },
              "initial_stop_loss_price": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double",
                "description": "Stop-loss level before any trailing; null when disabled."
              },
              "target_price": {
                "type": [
                  "number",
                  "null"
                ],
                "format": "double",
                "description": "Target level; null when disabled."
              },
              "live": {
                "type": "boolean",
                "description": "Protection is armed (the entry filled)."
              },
              "status": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Set once the trigger fired or ended: `sl_hit`, `target_hit`,\n`target_reached`, `invalidated`, `exit`, `cancelled`, ...; null while\nit watches."
              },
              "created_at": {
                "type": "string",
                "description": "Creation time (India time, `YYYY-MM-DD HH:MM:SS`)."
              },
              "updated_at": {
                "type": "string",
                "description": "Last change (India time, `YYYY-MM-DD HH:MM:SS`)."
              }
            },
            "x-deprecated-aliases": {
              "cirrus_token": "instrument_token",
              "cirrus_exits": "exits"
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_UserProfile": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "Who is calling, and with what credential. Never a secret.",
            "required": [
              "username",
              "auth"
            ],
            "properties": {
              "username": {
                "type": "string",
                "description": "The user's id."
              },
              "auth": {
                "$ref": "#/components/schemas/ProfileAuth"
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_AccountGtts": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "One account's GTTs at the broker.",
              "required": [
                "account",
                "broker",
                "gtts",
                "error"
              ],
              "properties": {
                "account": {
                  "type": "string"
                },
                "broker": {
                  "type": "string",
                  "description": "The account's broker."
                },
                "gtts": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Gtt"
                  },
                  "description": "Empty when the list could not be read (`error` says why)."
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Why this account's list is missing (others still listed); null\nwhen it was read."
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_ApiKeyView": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "An active API key as its owner sees it (never the secret or its hash).",
              "required": [
                "key_id",
                "name",
                "scopes",
                "ip_allowlist",
                "created_at",
                "last_used_at"
              ],
              "properties": {
                "key_id": {
                  "type": "string",
                  "description": "Public key id (`ck_...`): the part before `:` in\n`Authorization: token <key_id>:<key_secret>`."
                },
                "name": {
                  "type": "string",
                  "description": "The owner's label for the key."
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Scope"
                  },
                  "description": "What the key may do."
                },
                "ip_allowlist": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "IP addresses the key may be used from; empty = any."
                },
                "created_at": {
                  "type": "string",
                  "description": "When the key was created (RFC 3339)."
                },
                "last_used_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "When the key was last used (RFC 3339, updated at most once a\nminute); null when never used."
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_PartnerApp": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A registered partner app.",
              "required": [
                "client_id",
                "owner",
                "name",
                "verified",
                "logo_url",
                "redirect_uris",
                "scopes",
                "created_at",
                "disabled"
              ],
              "properties": {
                "client_id": {
                  "type": "string",
                  "description": "OAuth client id (`cp_...`)."
                },
                "owner": {
                  "type": "string",
                  "description": "Username of the user who registered the app."
                },
                "name": {
                  "type": "string",
                  "description": "Name shown to users on the consent screen."
                },
                "verified": {
                  "type": "boolean",
                  "description": "Whether the operator has confirmed that the app's name belongs to\nits owner; never set through the API. Unverified apps are flagged\non the consent screen."
                },
                "logo_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "HTTPS URL of the app's logo."
                },
                "redirect_uris": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Exact redirect URIs a user may be sent back to."
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Scope"
                  },
                  "description": "The most a user can grant this partner."
                },
                "created_at": {
                  "type": "string",
                  "description": "RFC 3339 time of registration."
                },
                "disabled": {
                  "type": "boolean",
                  "description": "`true` once the owner disabled the app (its tokens stop working)."
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_PartnerConnection": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A partner app the user connected (granted access to).",
              "required": [
                "client_id",
                "app_name",
                "verified",
                "scopes",
                "connected_at",
                "updated_at"
              ],
              "properties": {
                "client_id": {
                  "type": "string",
                  "description": "The partner app's client id."
                },
                "app_name": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The app's name; `null` when the app has since been disabled."
                },
                "verified": {
                  "type": "boolean",
                  "description": "Whether the app is verified (see `PartnerApp.verified`)."
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Scope"
                  },
                  "description": "Scopes the user granted."
                },
                "connected_at": {
                  "type": "string",
                  "description": "RFC 3339 time of the first connection."
                },
                "updated_at": {
                  "type": "string",
                  "description": "RFC 3339 time of the latest grant."
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_SharedGrant": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A share another user granted to the caller.",
              "required": [
                "owner_username",
                "owner_name",
                "scopes",
                "account_scope"
              ],
              "properties": {
                "owner_username": {
                  "type": "string",
                  "description": "Username of the owner (the path segment `{owner}` of the other\nshared routes)."
                },
                "owner_name": {
                  "type": "string",
                  "description": "The owner's display name (their username when none is set)."
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ShareScope"
                  },
                  "description": "What the owner shared."
                },
                "account_scope": {
                  "$ref": "#/components/schemas/ShareAccountScope"
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_SignalUrl": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A live signal URL (never its secret).",
              "required": [
                "endpoint_id",
                "kind",
                "strategy_id",
                "created_at",
                "has_body_secret"
              ],
              "properties": {
                "endpoint_id": {
                  "type": "string",
                  "description": "Public id (`we_...`), kept across rotations."
                },
                "kind": {
                  "$ref": "#/components/schemas/SignalProvider"
                },
                "strategy_id": {
                  "type": "string",
                  "description": "The strategy the URL's signals trade."
                },
                "created_at": {
                  "type": "string",
                  "description": "When this URL (its current secret) was issued (RFC 3339)."
                },
                "has_body_secret": {
                  "type": "boolean",
                  "description": "TradingView: alerts must carry the body secret."
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_TriggerView": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Stop-loss / target protection on a position, with its live levels.",
              "required": [
                "trigger_id",
                "account",
                "instrument_token",
                "name",
                "side",
                "product",
                "quantity",
                "price",
                "order_id",
                "broker_order_id",
                "kind",
                "exits",
                "rules",
                "stop_loss_price",
                "initial_stop_loss_price",
                "target_price",
                "live",
                "status",
                "created_at",
                "updated_at"
              ],
              "properties": {
                "trigger_id": {
                  "type": "string"
                },
                "account": {
                  "type": "string",
                  "description": "Account id (see `/v1/accounts`)."
                },
                "instrument_token": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Instrument id."
                },
                "name": {
                  "type": "string",
                  "description": "Enabled rules: `SL`, `TGT`, `TSL`, joined with ` + `."
                },
                "side": {
                  "type": "string",
                  "description": "Side of the protected entry: `BUY` (a long position, exited by a\nSELL) or `SELL`."
                },
                "product": {
                  "type": "string",
                  "description": "Product of the position (`MIS`, `CARRYFORWARD`, `DELIVERY`, `MTF`)."
                },
                "quantity": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Quantity the exit covers, in units.",
                  "minimum": 0
                },
                "price": {
                  "type": "number",
                  "format": "double",
                  "description": "Entry / average price the levels are measured from."
                },
                "order_id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The protected entry order, when the trigger came with one."
                },
                "broker_order_id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Broker id of the order / GTT holding the legs (broker-held only)."
                },
                "kind": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Where the protection lives: `platform` (a server-side\ntrigger; the server places the exit), `bracket` or `cover` (broker\nbracket / cover order legs), `gtt_oco` or `gtt_single` (broker GTT\nwith two legs or one). Null for triggers created without a kind;\nother values may appear for triggers created elsewhere."
                },
                "exits": {
                  "type": "boolean",
                  "description": "The server (not the broker) places the exit when a level is hit.\n`false`: the broker holds the legs, so change or cancel them at the\nbroker (only delete works here)."
                },
                "rules": {
                  "$ref": "#/components/schemas/TriggerRulesView"
                },
                "stop_loss_price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "format": "double",
                  "description": "Current stop-loss level (moves when trailing); null when disabled."
                },
                "initial_stop_loss_price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "format": "double",
                  "description": "Stop-loss level before any trailing; null when disabled."
                },
                "target_price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "format": "double",
                  "description": "Target level; null when disabled."
                },
                "live": {
                  "type": "boolean",
                  "description": "Protection is armed (the entry filled)."
                },
                "status": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Set once the trigger fired or ended: `sl_hit`, `target_hit`,\n`target_reached`, `invalidated`, `exit`, `cancelled`, ...; null while\nit watches."
                },
                "created_at": {
                  "type": "string",
                  "description": "Creation time (India time, `YYYY-MM-DD HH:MM:SS`)."
                },
                "updated_at": {
                  "type": "string",
                  "description": "Last change (India time, `YYYY-MM-DD HH:MM:SS`)."
                }
              },
              "x-deprecated-aliases": {
                "cirrus_token": "instrument_token",
                "cirrus_exits": "exits"
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_Vec_WebhookView": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "A webhook as its owner sees it (never the secret). Times are RFC 3339.",
              "required": [
                "id",
                "url",
                "events",
                "accounts",
                "description",
                "enabled",
                "disabled_reason",
                "disabled_at",
                "consecutive_failures",
                "last_success_at",
                "last_failure_at",
                "previous_secret_expires_at",
                "secret_rotated_at",
                "created_at",
                "updated_at"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Webhook id."
                },
                "url": {
                  "type": "string",
                  "description": "The receiver: an `https://` URL on a public host."
                },
                "events": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookEventType"
                  },
                  "description": "The events it gets (see the document's `webhooks` section for each\nbody)."
                },
                "accounts": {
                  "type": [
                    "array",
                    "null"
                  ],
                  "items": {
                    "type": "string"
                  },
                  "description": "The accounts whose events it gets; null = every account of the user\n(including ones added later). Events about the user rather than one\naccount go to every webhook subscribed to them."
                },
                "description": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The owner's note."
                },
                "enabled": {
                  "type": "boolean",
                  "description": "Whether deliveries are sent."
                },
                "disabled_reason": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Why it is off: `disabled_by_user`, `too_many_failures` (50 failed\nattempts in a row) or `failing_for_24_hours`; null while enabled."
                },
                "disabled_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "consecutive_failures": {
                  "type": "integer",
                  "format": "int32",
                  "description": "Failed attempts in a row (any success resets it).",
                  "minimum": 0
                },
                "last_success_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "last_failure_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "previous_secret_expires_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "While set, deliveries are also signed with the previous secret\n(for 24 hours after a rotation)."
                },
                "secret_rotated_at": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "created_at": {
                  "type": "string"
                },
                "updated_at": {
                  "type": "string"
                }
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_WebhookDeliveryPage": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "One page of a webhook's delivery attempts, newest first. Doc-only\nmirror of the body `deliveries` builds.",
            "required": [
              "deliveries",
              "next_cursor"
            ],
            "properties": {
              "deliveries": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              },
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Pass as `cursor` for the next page; null on the last page."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_WebhookTestResult": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "The result of a test delivery (one signed `ping`, one attempt, no\nretry; logged like any delivery).",
            "required": [
              "event_id",
              "delivered",
              "status_code",
              "duration_ms",
              "error_kind"
            ],
            "properties": {
              "event_id": {
                "type": "string",
                "description": "The `ping` event's id (its `webhook-id` header)."
              },
              "delivered": {
                "type": "boolean",
                "description": "Whether the receiver answered 2xx."
              },
              "status_code": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int32",
                "description": "The receiver's HTTP status; null when no answer came.",
                "minimum": 0
              },
              "duration_ms": {
                "type": "integer",
                "format": "int64",
                "description": "How long the attempt took.",
                "minimum": 0
              },
              "error_kind": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Why it failed: `timeout`, `connect`, `blocked_address`,\n`http_status`, `redirect`...; null when delivered."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_WebhookView": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A webhook as its owner sees it (never the secret). Times are RFC 3339.",
            "required": [
              "id",
              "url",
              "events",
              "accounts",
              "description",
              "enabled",
              "disabled_reason",
              "disabled_at",
              "consecutive_failures",
              "last_success_at",
              "last_failure_at",
              "previous_secret_expires_at",
              "secret_rotated_at",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Webhook id."
              },
              "url": {
                "type": "string",
                "description": "The receiver: an `https://` URL on a public host."
              },
              "events": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/WebhookEventType"
                },
                "description": "The events it gets (see the document's `webhooks` section for each\nbody)."
              },
              "accounts": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "string"
                },
                "description": "The accounts whose events it gets; null = every account of the user\n(including ones added later). Events about the user rather than one\naccount go to every webhook subscribed to them."
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The owner's note."
              },
              "enabled": {
                "type": "boolean",
                "description": "Whether deliveries are sent."
              },
              "disabled_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Why it is off: `disabled_by_user`, `too_many_failures` (50 failed\nattempts in a row) or `failing_for_24_hours`; null while enabled."
              },
              "disabled_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "consecutive_failures": {
                "type": "integer",
                "format": "int32",
                "description": "Failed attempts in a row (any success resets it).",
                "minimum": 0
              },
              "last_success_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_failure_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "previous_secret_expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "While set, deliveries are also signed with the previous secret\n(for 24 hours after a rotation)."
              },
              "secret_rotated_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "created_at": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "Success_WebhookWithSecret": {
        "type": "object",
        "description": "Successful response: `data` holds the result, `error` is null.",
        "required": [
          "status",
          "data",
          "error"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SuccessStatus"
          },
          "data": {
            "type": "object",
            "description": "A webhook with its signing secret (shown only in this response).\nDoc-only mirror of the body `with_secret` builds. Times are RFC 3339.",
            "required": [
              "id",
              "url",
              "events",
              "accounts",
              "description",
              "enabled",
              "disabled_reason",
              "disabled_at",
              "consecutive_failures",
              "last_success_at",
              "last_failure_at",
              "previous_secret_expires_at",
              "secret_rotated_at",
              "created_at",
              "updated_at",
              "secret",
              "note"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "events": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/WebhookEventType"
                }
              },
              "accounts": {
                "type": [
                  "array",
                  "null"
                ],
                "items": {
                  "type": "string"
                },
                "description": "null = every account."
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "enabled": {
                "type": "boolean"
              },
              "disabled_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "`disabled_by_user`, `too_many_failures` or `failing_for_24_hours`."
              },
              "disabled_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "consecutive_failures": {
                "type": "integer",
                "format": "int32",
                "minimum": 0
              },
              "last_success_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_failure_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "previous_secret_expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "After a rotation: until then deliveries are also signed with the\nprevious secret."
              },
              "secret_rotated_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "created_at": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              },
              "secret": {
                "type": "string",
                "description": "The signing secret (`whsec_...`): verify each delivery's\n`webhook-signature` with it. Store it now: it is never shown again."
              },
              "note": {
                "type": "string",
                "description": "A reminder that the secret is shown only once."
              }
            }
          },
          "error": {
            "type": "null"
          }
        }
      },
      "TimelineEntry": {
        "type": "object",
        "description": "One step in an order's life (from the order journal).",
        "required": [
          "at",
          "account",
          "order_id",
          "state",
          "message",
          "filled_qty",
          "average_price"
        ],
        "properties": {
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "account": {
            "type": "string"
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "description": "`SUBMITTED`, `OPEN`, `FILLED`, `PARTIALLY_FILLED`, `CANCELLED`, ..."
          },
          "message": {
            "type": [
              "string",
              "null"
            ]
          },
          "filled_qty": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Filled so far at this step (when the journal knows).",
            "minimum": 0
          },
          "average_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double"
          }
        }
      },
      "TradeRow": {
        "type": "object",
        "description": "One executed trade (fill) from the broker's trade book (enriched).",
        "required": [
          "account",
          "order_id",
          "instrument_token",
          "tradingsymbol",
          "side",
          "quantity",
          "fill_price",
          "trade_value"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "order_id": {
            "type": "string",
            "description": "Broker order id."
          },
          "instrument_token": {
            "type": "string"
          },
          "tradingsymbol": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "fill_price": {
            "type": "number",
            "format": "double"
          },
          "trade_value": {
            "type": "number",
            "format": "double"
          },
          "filled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lot_size": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Contract lot size (added when the instrument is known).",
            "minimum": 0
          },
          "exchange": {
            "type": [
              "string",
              "null"
            ],
            "description": "Exchange (`NSE`, `NFO`, `BSE`, `BFO`, `MCX`, ...)."
          },
          "instrument_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument type (`EQ`, `FUTIDX`, `OPTIDX`, `OPTSTK`, ...)."
          },
          "symbol": {
            "type": [
              "string",
              "null"
            ],
            "description": "Underlying symbol (the trading symbol for equities)."
          },
          "expiry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date (`YYYY-MM-DD`); empty for non-derivatives."
          },
          "strike": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Strike price; `0` for non-options."
          },
          "option_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "`CE` / `PE`; empty for non-options."
          },
          "instrument_missing": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Present (`true`) only when the instrument is not known; the\ninstrument fields above are then absent."
          },
          "ltp": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Last traded price (added when a quote is available)."
          },
          "prev_close": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Previous close (`0` when unknown), sent with `ltp`."
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "TriggerDeleted": {
        "type": "object",
        "description": "`DELETE /v1/triggers/{id}` result (built with `json!`; documentation\nonly).",
        "required": [
          "trigger_id",
          "deleted"
        ],
        "properties": {
          "trigger_id": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "description": "Always `true`."
          }
        }
      },
      "TriggerRuleView": {
        "type": "object",
        "description": "A rule as served: `type` is snake_case (`percentage`, `points`,\n`price`). The trigger hash keeps the legacy casing (`Percentage`) that\nthe trigger workers read; requests accept either.",
        "required": [
          "enabled",
          "type",
          "value"
        ],
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Off unless `true`."
          },
          "type": {
            "$ref": "#/components/schemas/RuleType"
          },
          "value": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "TriggerRulesView": {
        "type": "object",
        "description": "The trigger's stop-loss, target and trailing stop-loss rules.",
        "required": [
          "target",
          "stop_loss",
          "trail"
        ],
        "properties": {
          "target": {
            "$ref": "#/components/schemas/TriggerRuleView"
          },
          "stop_loss": {
            "$ref": "#/components/schemas/TriggerRuleView"
          },
          "trail": {
            "$ref": "#/components/schemas/TriggerRuleView"
          }
        }
      },
      "TriggerView": {
        "type": "object",
        "description": "Stop-loss / target protection on a position, with its live levels.",
        "required": [
          "trigger_id",
          "account",
          "instrument_token",
          "name",
          "side",
          "product",
          "quantity",
          "price",
          "order_id",
          "broker_order_id",
          "kind",
          "exits",
          "rules",
          "stop_loss_price",
          "initial_stop_loss_price",
          "target_price",
          "live",
          "status",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "trigger_id": {
            "type": "string"
          },
          "account": {
            "type": "string",
            "description": "Account id (see `/v1/accounts`)."
          },
          "instrument_token": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instrument id."
          },
          "name": {
            "type": "string",
            "description": "Enabled rules: `SL`, `TGT`, `TSL`, joined with ` + `."
          },
          "side": {
            "type": "string",
            "description": "Side of the protected entry: `BUY` (a long position, exited by a\nSELL) or `SELL`."
          },
          "product": {
            "type": "string",
            "description": "Product of the position (`MIS`, `CARRYFORWARD`, `DELIVERY`, `MTF`)."
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Quantity the exit covers, in units.",
            "minimum": 0
          },
          "price": {
            "type": "number",
            "format": "double",
            "description": "Entry / average price the levels are measured from."
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The protected entry order, when the trigger came with one."
          },
          "broker_order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker id of the order / GTT holding the legs (broker-held only)."
          },
          "kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the protection lives: `platform` (a server-side\ntrigger; the server places the exit), `bracket` or `cover` (broker\nbracket / cover order legs), `gtt_oco` or `gtt_single` (broker GTT\nwith two legs or one). Null for triggers created without a kind;\nother values may appear for triggers created elsewhere."
          },
          "exits": {
            "type": "boolean",
            "description": "The server (not the broker) places the exit when a level is hit.\n`false`: the broker holds the legs, so change or cancel them at the\nbroker (only delete works here)."
          },
          "rules": {
            "$ref": "#/components/schemas/TriggerRulesView"
          },
          "stop_loss_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Current stop-loss level (moves when trailing); null when disabled."
          },
          "initial_stop_loss_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Stop-loss level before any trailing; null when disabled."
          },
          "target_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Target level; null when disabled."
          },
          "live": {
            "type": "boolean",
            "description": "Protection is armed (the entry filled)."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set once the trigger fired or ended: `sl_hit`, `target_hit`,\n`target_reached`, `invalidated`, `exit`, `cancelled`, ...; null while\nit watches."
          },
          "created_at": {
            "type": "string",
            "description": "Creation time (India time, `YYYY-MM-DD HH:MM:SS`)."
          },
          "updated_at": {
            "type": "string",
            "description": "Last change (India time, `YYYY-MM-DD HH:MM:SS`)."
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token",
          "cirrus_exits": "exits"
        }
      },
      "UserProfile": {
        "type": "object",
        "description": "Who is calling, and with what credential. Never a secret.",
        "required": [
          "username",
          "auth"
        ],
        "properties": {
          "username": {
            "type": "string",
            "description": "The user's id."
          },
          "auth": {
            "$ref": "#/components/schemas/ProfileAuth"
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "description": "One delivery attempt (ids, status and timing only, never the body).",
        "required": [
          "id",
          "event_id",
          "type",
          "attempt",
          "outcome",
          "status_code",
          "duration_ms",
          "error_kind",
          "at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Attempt id (sorts by time)."
          },
          "event_id": {
            "type": "string",
            "description": "The event's id (its `webhook-id` header; the same on every retry)."
          },
          "type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "attempt": {
            "type": "integer",
            "format": "int32",
            "description": "1 for the first attempt, then one more per retry.",
            "minimum": 0
          },
          "outcome": {
            "type": "string",
            "description": "`delivered`, `retrying` (another attempt is scheduled), `failed` (no\nmore attempts) or `dropped`."
          },
          "status_code": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The receiver's HTTP status; null when no answer came.",
            "minimum": 0
          },
          "duration_ms": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          },
          "error_kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it failed: `timeout`, `connect`, `blocked_address`,\n`http_status`, `redirect`...; null when delivered."
          },
          "at": {
            "type": "string",
            "description": "When the attempt was made (RFC 3339)."
          }
        }
      },
      "WebhookDeliveryPage": {
        "type": "object",
        "description": "One page of a webhook's delivery attempts, newest first. Doc-only\nmirror of the body `deliveries` builds.",
        "required": [
          "deliveries",
          "next_cursor"
        ],
        "properties": {
          "deliveries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` for the next page; null on the last page."
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "description": "Event names. A receiver subscribes to any of `order_update` (any\nchange to an order), `trade` (a fill), `account_alert` (something about\nan account that needs the user) and `positions` (an account's positions\nchanged, at most once per second per account). `ping` is sent only by\nthe webhook's test endpoint and cannot be subscribed to.",
        "enum": [
          "order_update",
          "trade",
          "account_alert",
          "positions",
          "ping"
        ]
      },
      "WebhookPatch": {
        "type": "object",
        "description": "Changes to a webhook: only the fields present change.",
        "properties": {
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "A new receiver URL (same rules as on creation)."
          },
          "events": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "A new event list (replaces the old one; at least one)."
          },
          "accounts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "A new account list; `null` goes back to every account."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "A new note; `null` or empty removes it."
          },
          "enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "`false` turns deliveries off; `true` turns them back on (also after\nthe webhook was turned off for failing)."
          }
        },
        "additionalProperties": false
      },
      "WebhookTestResult": {
        "type": "object",
        "description": "The result of a test delivery (one signed `ping`, one attempt, no\nretry; logged like any delivery).",
        "required": [
          "event_id",
          "delivered",
          "status_code",
          "duration_ms",
          "error_kind"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "description": "The `ping` event's id (its `webhook-id` header)."
          },
          "delivered": {
            "type": "boolean",
            "description": "Whether the receiver answered 2xx."
          },
          "status_code": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "The receiver's HTTP status; null when no answer came.",
            "minimum": 0
          },
          "duration_ms": {
            "type": "integer",
            "format": "int64",
            "description": "How long the attempt took.",
            "minimum": 0
          },
          "error_kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it failed: `timeout`, `connect`, `blocked_address`,\n`http_status`, `redirect`...; null when delivered."
          }
        }
      },
      "WebhookView": {
        "type": "object",
        "description": "A webhook as its owner sees it (never the secret). Times are RFC 3339.",
        "required": [
          "id",
          "url",
          "events",
          "accounts",
          "description",
          "enabled",
          "disabled_reason",
          "disabled_at",
          "consecutive_failures",
          "last_success_at",
          "last_failure_at",
          "previous_secret_expires_at",
          "secret_rotated_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Webhook id."
          },
          "url": {
            "type": "string",
            "description": "The receiver: an `https://` URL on a public host."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "The events it gets (see the document's `webhooks` section for each\nbody)."
          },
          "accounts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "The accounts whose events it gets; null = every account of the user\n(including ones added later). Events about the user rather than one\naccount go to every webhook subscribed to them."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The owner's note."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether deliveries are sent."
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it is off: `disabled_by_user`, `too_many_failures` (50 failed\nattempts in a row) or `failing_for_24_hours`; null while enabled."
          },
          "disabled_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "consecutive_failures": {
            "type": "integer",
            "format": "int32",
            "description": "Failed attempts in a row (any success resets it).",
            "minimum": 0
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_failure_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "previous_secret_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "While set, deliveries are also signed with the previous secret\n(for 24 hours after a rotation)."
          },
          "secret_rotated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        }
      },
      "WebhookWithSecret": {
        "type": "object",
        "description": "A webhook with its signing secret (shown only in this response).\nDoc-only mirror of the body `with_secret` builds. Times are RFC 3339.",
        "required": [
          "id",
          "url",
          "events",
          "accounts",
          "description",
          "enabled",
          "disabled_reason",
          "disabled_at",
          "consecutive_failures",
          "last_success_at",
          "last_failure_at",
          "previous_secret_expires_at",
          "secret_rotated_at",
          "created_at",
          "updated_at",
          "secret",
          "note"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "accounts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "null = every account."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "`disabled_by_user`, `too_many_failures` or `failing_for_24_hours`."
          },
          "disabled_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "consecutive_failures": {
            "type": "integer",
            "format": "int32",
            "minimum": 0
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_failure_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "previous_secret_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "After a rotation: until then deliveries are also signed with the\nprevious secret."
          },
          "secret_rotated_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          },
          "secret": {
            "type": "string",
            "description": "The signing secret (`whsec_...`): verify each delivery's\n`webhook-signature` with it. Store it now: it is never shown again."
          },
          "note": {
            "type": "string",
            "description": "A reminder that the secret is shown only once."
          }
        }
      },
      "ChartinkAlert": {
        "type": "object",
        "description": "Chartink scanner alert body, sent by Chartink to\n`POST /v1/hooks/chartink/{secret}`. Chartink cannot sign requests, so\nthe URL secret is the credential. Fields other than these are ignored\n(`scan_url`, `webhook_url`, ...). The same alert (same `triggered_at`,\n`stocks`, `scan_name`, `alert_name`) arriving again within 10 minutes is\ntreated as one.",
        "required": [
          "stocks"
        ],
        "properties": {
          "stocks": {
            "$ref": "#/components/schemas/StringOrList",
            "description": "Stock symbols (NSE, else BSE), at most 50. Unknown symbols are\nskipped; the rest are still traded."
          },
          "trigger_prices": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrList",
                "description": "Trigger price of each stock, in the same order as `stocks`. A\nmissing or zero price skips that stock."
              },
              {
                "type": "null"
              }
            ]
          },
          "triggered_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the scan fired, as Chartink formats it (`\"2:34 pm\"`)."
          },
          "scan_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "alert_name": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "examples": [
          {
            "stocks": "SBIN,RELIANCE",
            "trigger_prices": "523.4,2890",
            "triggered_at": "2:34 pm",
            "scan_name": "Breakouts",
            "alert_name": "Breakouts"
          }
        ]
      },
      "KuberhuntEvent": {
        "type": "object",
        "description": "Kuberhunt event body, sent to `POST /v1/hooks/kuberhunt/{secret}` or\nto the pre-v1 URL `POST /kuberhunt/execute-signal/{token}` (same body,\nsame headers; retired per strategy once its v1 URL has received an\naccepted delivery, and answered with `Deprecation` / `Sunset` headers).\n\nHeaders: `X-Kuberhunt-Timestamp` (Unix seconds, within ±300 s of now)\nand `X-Kuberhunt-Signature: v1=<hex HMAC-SHA256>` over\n`{timestamp}.{raw body}`, keyed with the strategy's Kuberhunt webhook\nsecret. Every refusal is answered 200 (Kuberhunt retries any non-2xx);\nonly a failure worth retrying is answered 503. The same `event_id` is\nhandled once; an `event_seq` not above the last one seen for the\nrecommendation is skipped as stale.",
        "required": [
          "event",
          "event_id",
          "reco"
        ],
        "properties": {
          "event": {
            "$ref": "#/components/schemas/KuberhuntEventName"
          },
          "event_id": {
            "$ref": "#/components/schemas/StringOrNumber",
            "description": "Delivery id (a string or a number); repeats are ignored for 24 h."
          },
          "event_seq": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Per-recommendation sequence (an integer, a whole number, or a\nnumeric string); anything else disables the ordering check."
              },
              {
                "type": "null"
              }
            ]
          },
          "timestamp": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the event was produced (RFC 3339). An entry older than 120 s\nis skipped."
          },
          "reco": {
            "$ref": "#/components/schemas/KuberhuntReco"
          },
          "transition": {
            "description": "Provider detail about the state change; kept in the history, not\nused."
          },
          "meta": {
            "description": "Provider metadata; kept in the history, not used."
          }
        },
        "examples": [
          {
            "event": "reco.activated",
            "event_id": "evt-1",
            "event_seq": 1,
            "timestamp": "2026-09-28T04:05:06.789+00:00",
            "reco": {
              "reco_id": "r1",
              "instrument_token": "CT:1:2:RELIANCE-EQ",
              "action": "BUY",
              "product": "INTRADAY",
              "lower_price": 2490,
              "entry_price": 2500,
              "stop_loss_price": 2450,
              "target_price": 2600
            }
          }
        ]
      },
      "KuberhuntEventName": {
        "type": "string",
        "description": "Kuberhunt event name. `reco.activated` opens a position (entry);\n`reco.sl_hit`, `reco.target_reached` and `reco.exit` close it;\n`reco.invalidated` / `reco.cancelled` close it too; `reco.updated` /\n`reco.trail_updated` move its stop-loss / target; `reco.scheduled`,\n`reco.pending`, `webhook.test` and `reco.t1_reached` ...\n`reco.t5_reached` are acknowledged without action. Any other name is\nacknowledged and ignored.",
        "enum": [
          "reco.activated",
          "reco.scheduled",
          "reco.pending",
          "webhook.test",
          "reco.trail_updated",
          "reco.updated",
          "reco.t1_reached",
          "reco.t2_reached",
          "reco.t3_reached",
          "reco.t4_reached",
          "reco.t5_reached",
          "reco.sl_hit",
          "reco.target_reached",
          "reco.exit",
          "reco.invalidated",
          "reco.cancelled"
        ]
      },
      "KuberhuntReco": {
        "type": "object",
        "description": "The recommendation an event is about. Prices may be numbers or numeric\nstrings. `instrument_token` or its legacy name is accepted; send one\n(both with different values is refused).",
        "required": [
          "reco_id"
        ],
        "properties": {
          "reco_id": {
            "$ref": "#/components/schemas/StringOrNumber",
            "description": "Recommendation id; every later event finds the position by it. An\nentry without one is skipped."
          },
          "instrument_token": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Instrument id to trade (a string, or an integer). An entry without\none is skipped."
              },
              {
                "type": "null"
              }
            ]
          },
          "action": {
            "type": [
              "string",
              "null"
            ],
            "description": "`BUY` or `SELL` (any case); anything else, or none, is `BUY`."
          },
          "product": {
            "type": [
              "string",
              "null"
            ],
            "description": "`INTRADAY` / `MIS` or `CARRYFORWARD` / `CNC`; used when the strategy\nmirrors the recommendation's product."
          },
          "lower_price": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Limit price for strategies entering at the lower price."
              },
              {
                "type": "null"
              }
            ]
          },
          "higher_price": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Limit price for strategies entering at the higher price."
              },
              {
                "type": "null"
              }
            ]
          },
          "entry_price": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Reference price (limit fallback, slippage reference)."
              },
              {
                "type": "null"
              }
            ]
          },
          "stop_loss_price": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Stop-loss price, placed when the strategy asks for it."
              },
              {
                "type": "null"
              }
            ]
          },
          "target_price": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StringOrNumber",
                "description": "Target price, placed when the strategy asks for it."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token"
        }
      },
      "PortfolioData": {
        "anyOf": [
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PositionRow"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HoldingRow"
            }
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TradeRow"
            }
          },
          {
            "$ref": "#/components/schemas/MarginRow"
          }
        ],
        "description": "`positions`, `holdings`, `trades`: a list of rows (may be empty); `margins`: one object."
      },
      "PortfolioKind": {
        "type": "string",
        "description": "Portfolio data kinds kept as per-account snapshots.",
        "enum": [
          "positions",
          "holdings",
          "trades",
          "margins"
        ]
      },
      "SignalAck": {
        "type": "object",
        "description": "Reply with status 200 (see `SignalAckMessage` for every message).",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/SignalAckMessage"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "message": "Webhook received"
          }
        ]
      },
      "SignalAckMessage": {
        "type": "string",
        "description": "Every message a signal URL answers with status 200. The delivery was\nreceived; nothing more is promised (what it came to is in the URL's\ndelivery log and the activity log).\n\n- `Webhook received`: handled (orders placed, closed, updated, or\n  skipped by a strategy rule).\n- `Duplicate`: the same alert arrived twice; the copy was skipped.\n- `Stale`: an older Kuberhunt event arrived after a newer one.\n- `Signal is disabled` / `Strategy paused`: the strategy is paused.\n- `Strategy not found`: the strategy no longer exists.\n- `Invalid Payload` / `Invalid payload` / `Invalid JSON` / `Empty body`:\n  the body could not be read.\n- `Invalid signature`, `Timestamp out of window`, `Webhook secret\n  missing`: Kuberhunt signature checks.\n- `Only entry and exit signals are processed`: TradingView `type` was\n  neither.\n- `Too many stocks in one alert`, `No valid stocks found`, `No accounts\n  configured`: Chartink alerts that could not be traded.\n- `instrument_token ... differ; send one`, `order_tag ... differ; send\n  one`, `exits ... differ; send one`: a field was sent under both its\n  names with different values.\n- `Invalid ID`: the pre-v1 Kuberhunt URL's token is invalid.",
        "enum": [
          "Webhook received",
          "Duplicate",
          "Stale",
          "Signal is disabled",
          "Strategy paused",
          "Strategy not found",
          "Invalid Payload",
          "Invalid payload",
          "Invalid JSON",
          "Empty body",
          "Invalid signature",
          "Timestamp out of window",
          "Webhook secret missing",
          "Only entry and exit signals are processed",
          "Too many stocks in one alert",
          "No valid stocks found",
          "No accounts configured",
          "instrument_token and cirrus_token differ; send one",
          "order_tag and cirrus_tag differ; send one",
          "exits and cirrus_exits differ; send one",
          "Invalid ID"
        ]
      },
      "SignalError": {
        "type": "object",
        "description": "Reply before the URL's strategy is known: 404 `Unknown webhook`\n(unknown, revoked or malformed URL), 429 `rate limited; retry in {n}\nms` (with `Retry-After`, `X-RateLimit-Limit` and\n`X-RateLimit-Remaining` headers), or 503 `temporarily unavailable`.",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/SignalErrorStatus"
          },
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "status": "error",
            "message": "Unknown webhook"
          }
        ]
      },
      "SignalErrorStatus": {
        "type": "string",
        "description": "Always `error`.",
        "enum": [
          "error"
        ]
      },
      "SignalForbidden": {
        "type": "object",
        "description": "Reply with status 403: the TradingView body secret did not match.",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/SignalForbiddenMessage"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "message": "Invalid secret"
          }
        ]
      },
      "SignalForbiddenMessage": {
        "type": "string",
        "description": "Messages answered with 403 (`Invalid secret`: the TradingView body\nsecret is missing or wrong).",
        "enum": [
          "Invalid secret"
        ]
      },
      "SignalRetired": {
        "type": "object",
        "description": "Reply with status 410 from the pre-v1 Kuberhunt URL once it is\nretired (after its sunset date, or once the strategy's v1 URL has\nreceived an accepted delivery): the message says to issue a new URL.",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "message": "This URL has been retired. Issue a new one for the strategy in the app."
          }
        ]
      },
      "SignalRetry": {
        "type": "object",
        "description": "Reply with status 503: send the same delivery again later.",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/SignalRetryMessage"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "message": "Order handling failed; please redeliver"
          }
        ]
      },
      "SignalRetryMessage": {
        "type": "string",
        "description": "Messages answered with 503; the provider should send the delivery\nagain: `temporarily unavailable` (a store is down), `Order handling\nfailed; please redeliver` (a Kuberhunt entry or close failed in a way\nworth retrying; its de-duplication was undone), `signal strategies\nunavailable` (strategies cannot be read on this server).",
        "enum": [
          "temporarily unavailable",
          "Order handling failed; please redeliver",
          "signal strategies unavailable"
        ]
      },
      "SnapshotKind": {
        "type": "string",
        "description": "Snapshot kind: `orders` (today's order book) or a portfolio kind.",
        "enum": [
          "orders",
          "positions",
          "holdings",
          "trades",
          "margins"
        ]
      },
      "StreamAccount": {
        "type": "object",
        "description": "An account the stream covers, with the user's label for it.",
        "required": [
          "account",
          "broker"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "broker": {
            "type": "string",
            "description": "Broker id (`zerodha`, `upstox`, ...)."
          },
          "tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "The user's own label for the account."
          }
        },
        "additionalProperties": false
      },
      "StreamActivity": {
        "type": "object",
        "description": "Live: a new activity-log record.",
        "required": [
          "seq",
          "type",
          "data"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number (see `hello`).",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "activity"
            ]
          },
          "data": {
            "$ref": "#/components/schemas/ActivityRecord"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 6,
            "type": "activity",
            "data": {
              "id": "01K6D8ZQ4XA1B2C3D4E5F6G7H8",
              "username": "alice",
              "at": "2026-09-28T04:05:06.789Z",
              "kind": "place",
              "category": "orders",
              "source": {
                "type": "app",
                "name": null
              },
              "request_id": "req_01K6D8ZQ4X",
              "instrument": {
                "cirrus_token": "CT:1:2:RELIANCE-EQ",
                "tradingsymbol": "RELIANCE-EQ",
                "exchange": "NSE",
                "instrument_token": "CT:1:2:RELIANCE-EQ"
              },
              "side": "BUY",
              "order_type": "LIMIT",
              "product": "MIS",
              "quantity": 10,
              "price": 2500,
              "trigger_price": null,
              "summary": "Buy 10 RELIANCE-EQ at 2500 in 1 account",
              "message": null,
              "outcome": "ok",
              "duration_ms": 84,
              "accounts": [
                {
                  "account": "ZX1234",
                  "broker": "zerodha",
                  "status": "placed",
                  "order_ids": [
                    "250928000123456"
                  ],
                  "message": null,
                  "broker_message": null,
                  "duration_ms": 84
                }
              ]
            }
          }
        ]
      },
      "StreamAuth": {
        "type": "object",
        "description": "Client -> server, the first frame: authenticates the connection. Not\nneeded when the upgrade request already carried a credential (an\n`Authorization` header, or the app's session cookie). Sent later it is\nignored. Without it within 5 s the server closes with 4002; a bad\ncredential closes with 4001.",
        "required": [
          "type",
          "token"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "auth"
            ]
          },
          "token": {
            "type": "string",
            "description": "An API key, access token or app session token (the same\ncredentials `/v1` routes accept); needs the `read` scope."
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "type": "auth",
            "token": "ck_live_4f1d0c9a7b2e"
          }
        ]
      },
      "StreamClientMessage": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/StreamAuth"
          },
          {
            "$ref": "#/components/schemas/StreamResync"
          }
        ],
        "description": "Any message a client sends on `/v1/stream`, told apart by `type`."
      },
      "StreamError": {
        "type": "object",
        "description": "The stream hit a problem it cannot recover from on this connection;\nthe connection ends after it. Reconnect.",
        "required": [
          "seq",
          "type",
          "code",
          "message"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number (see `hello`).",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "error"
            ]
          },
          "code": {
            "$ref": "#/components/schemas/StreamErrorCode"
          },
          "message": {
            "type": "string",
            "description": "Plain-English explanation."
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 7,
            "type": "error",
            "code": "unavailable",
            "message": "live updates unavailable, please reconnect"
          }
        ]
      },
      "StreamErrorCode": {
        "type": "string",
        "description": "Why the stream cannot go on: `unavailable` (live updates could not be\nset up; reconnect).",
        "enum": [
          "unavailable"
        ]
      },
      "StreamHello": {
        "type": "object",
        "description": "First server message after authentication: who is connected and which\naccounts the stream covers. `snapshot` messages follow.",
        "required": [
          "seq",
          "type",
          "user",
          "accounts"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number, from 1, +1 per message. A gap\nmeans messages were lost: send `resync`.",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "hello"
            ]
          },
          "user": {
            "type": "string"
          },
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StreamAccount"
            }
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 1,
            "type": "hello",
            "user": "alice",
            "accounts": [
              {
                "account": "ZX1234",
                "broker": "zerodha",
                "tag": "Main"
              }
            ]
          }
        ]
      },
      "StreamOrderUpdate": {
        "type": "object",
        "description": "Live: an order changed (state, fills, broker id...). Carries the full\norder, never a diff, so a missed message is repaired by the next one\nfor the same order.",
        "required": [
          "seq",
          "type",
          "account",
          "data"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number (see `hello`).",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "order_update"
            ]
          },
          "account": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/OrderData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 4,
            "type": "order_update",
            "account": "ZX1234",
            "data": {
              "cirrus_tag": "01K6D8ZQ4X9V2M3N5P7R8S9T0W",
              "broker_tag": "01K6D8ZQ4X9V2M3N",
              "order_id": "250928000123456",
              "parent_tag": null,
              "username": "alice",
              "account": "ZX1234",
              "broker": "zerodha",
              "cirrus_token": "CT:1:2:RELIANCE-EQ",
              "tradingsymbol": "RELIANCE-EQ",
              "side": "BUY",
              "order_type": "LIMIT",
              "product": "MIS",
              "quantity": 10,
              "price": 2500,
              "trigger_price": null,
              "state": "PARTIALLY_FILLED",
              "filled_qty": 4,
              "average_price": 2499.8,
              "status_message": null,
              "broker_updated_at": "2026-09-28T04:05:07.120Z",
              "created_at": "2026-09-28T04:05:06.789Z",
              "status_history": [
                {
                  "from": "SUBMITTED",
                  "to": "OPEN",
                  "at": "2026-09-28T04:05:06.789Z",
                  "message": null
                },
                {
                  "from": "OPEN",
                  "to": "PARTIALLY_FILLED",
                  "at": "2026-09-28T04:05:07.120Z",
                  "message": null
                }
              ],
              "lot_size": 1,
              "exchange": "NSE",
              "instrument_type": "EQ",
              "symbol": "RELIANCE-EQ",
              "expiry": "",
              "strike": 0,
              "option_type": "",
              "ltp": 2501.5,
              "prev_close": 2490,
              "instrument_token": "CT:1:2:RELIANCE-EQ",
              "order_tag": "01K6D8ZQ4X9V2M3N5P7R8S9T0W"
            }
          }
        ]
      },
      "StreamPortfolio": {
        "type": "object",
        "description": "Live: an account's positions, holdings, trades or margins changed.\nCarries the full current data of that kind, never a diff.",
        "required": [
          "seq",
          "type",
          "account",
          "kind",
          "data"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number (see `hello`).",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "portfolio"
            ]
          },
          "account": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/PortfolioKind"
          },
          "data": {
            "$ref": "#/components/schemas/PortfolioData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 5,
            "type": "portfolio",
            "account": "ZX1234",
            "kind": "margins",
            "data": {
              "account": "ZX1234",
              "opening_balance": 100000,
              "available": 90000.8,
              "utilised": 9999.2
            }
          }
        ]
      },
      "StreamResync": {
        "type": "object",
        "description": "Client -> server: asks for a fresh snapshot (every account's\n`snapshot` messages again, then `snapshot_done`). Use it after a gap\nin `seq`. Any other frame the client sends only counts as activity\nfor the idle timeout.",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "resync"
            ]
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "type": "resync"
          }
        ]
      },
      "StreamServerMessage": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/StreamHello"
          },
          {
            "$ref": "#/components/schemas/StreamSnapshot"
          },
          {
            "$ref": "#/components/schemas/StreamSnapshotDone"
          },
          {
            "$ref": "#/components/schemas/StreamOrderUpdate"
          },
          {
            "$ref": "#/components/schemas/StreamPortfolio"
          },
          {
            "$ref": "#/components/schemas/StreamActivity"
          },
          {
            "$ref": "#/components/schemas/StreamError"
          }
        ],
        "description": "Any message the server sends on `/v1/stream`, told apart by `type`.\n\nOrder: `hello`, one `snapshot` per account and kind, `snapshot_done`,\nthen live `order_update`, `portfolio` and `activity` messages as they\nhappen. Messages carry full state, never diffs; `resync` rebuilds\neverything.\n\nHeartbeat: the server sends a WebSocket ping frame every 15 s and closes\na connection it has heard nothing from (no frame, no pong) for 45 s.\nThe credential is re-checked every 10 s; logout or key revocation\ncloses the stream.\n\nClose codes: 4001 (credential missing, invalid, expired or revoked),\n4002 (no `auth` message within 5 s), 1013 (the client fell too far\nbehind; reconnect for a fresh snapshot), 1000 (idle)."
      },
      "StreamSnapshot": {
        "type": "object",
        "description": "The current state of one account's data kind, sent after `hello` (one\nper account and kind that has data) and again after `resync`. Kinds\nwith no data yet are left out. `snapshot_done` ends the set.",
        "required": [
          "seq",
          "type",
          "account",
          "kind",
          "data"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number (see `hello`).",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "snapshot"
            ]
          },
          "account": {
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/SnapshotKind"
          },
          "data": {
            "$ref": "#/components/schemas/SnapshotData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 2,
            "type": "snapshot",
            "account": "ZX1234",
            "kind": "positions",
            "data": [
              {
                "account": "ZX1234",
                "cirrus_token": "CT:1:2:RELIANCE-EQ",
                "tradingsymbol": "RELIANCE-EQ",
                "product": "MIS",
                "net_qty": 4,
                "buy_qty": 4,
                "sell_qty": 0,
                "buy_value": 9999.2,
                "sell_value": 0,
                "average_price": 2499.8,
                "buy_average_price": 2499.8,
                "sell_average_price": 0,
                "pnl": 6.8,
                "lot_size": 1,
                "exchange": "NSE",
                "instrument_type": "EQ",
                "symbol": "RELIANCE-EQ",
                "expiry": "",
                "strike": 0,
                "option_type": "",
                "ltp": 2501.5,
                "prev_close": 2490,
                "instrument_token": "CT:1:2:RELIANCE-EQ"
              }
            ]
          }
        ]
      },
      "StreamSnapshotDone": {
        "type": "object",
        "description": "Every snapshot has been sent; live messages follow.",
        "required": [
          "seq",
          "type"
        ],
        "properties": {
          "seq": {
            "type": "integer",
            "format": "int64",
            "description": "Per-connection sequence number (see `hello`).",
            "minimum": 0
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "snapshot_done"
            ]
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "seq": 3,
            "type": "snapshot_done"
          }
        ]
      },
      "StringOrList": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StringOrNumber"
            }
          }
        ],
        "description": "A comma-separated string (`\"SBIN,RELIANCE\"`) or a list."
      },
      "StringOrNumber": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "number",
            "format": "double"
          }
        ],
        "description": "A string or a number (both are read the same way)."
      },
      "TradingViewAlert": {
        "type": "object",
        "description": "TradingView alert body, sent to `POST /v1/hooks/tradingview/{secret}`.\nPut it in the alert's \"Message\" box as JSON. The URL secret and the\nbody `secret` must both match. Other fields are ignored. The same alert\narriving twice within 5 s is treated as one.",
        "required": [
          "type",
          "secret"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/TradingViewSignalType"
          },
          "secret": {
            "type": "string",
            "description": "The body secret (`tvs_...`) shown once when the URL was issued. A\nmissing or wrong one is refused with 403."
          }
        },
        "examples": [
          {
            "type": "entry",
            "secret": "tvs_3kq8v1n0x7c2m5z9"
          }
        ]
      },
      "TradingViewSignalType": {
        "type": "string",
        "description": "TradingView alert type: `entry` places the strategy's legs, `exit`\ncloses what the strategy's entries placed. Case and surrounding spaces\nare ignored (`\"Entry \"` works); any other type is acknowledged and\nignored.",
        "enum": [
          "entry",
          "exit"
        ]
      },
      "WebhookAccountAlert": {
        "type": "object",
        "description": "`account_alert`: something about an account that needs the user (see `WebhookAlertKind`).\n\nEvery delivery is an HTTPS `POST` with `Content-Type: application/json` and a body `{id, type, created_at, data}` (all keys snake_case), signed per Standard Webhooks (https://www.standardwebhooks.com):\n- `webhook-id`: the event `id` (same on every retry; de-duplicate on it);\n- `webhook-timestamp`: Unix seconds when this attempt was sent;\n- `webhook-signature`: `v1,<base64 HMAC-SHA256>` over `{webhook-id}.{webhook-timestamp}.{raw body}`, keyed with the base64-decoded part of the webhook's `whsec_...` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated; accept the message when any one matches.\n\nAnswer 2xx within 5 s. 408, 429, 5xx, timeouts and network errors are retried after 30 s, 2 min, 10 min, 30 min, 1 h and 2 h (7 attempts); other 4xx answers are not retried. A webhook that keeps failing (50 failures in a row, or failing for 24 h) is turned off and an `account_alert` (`webhook_disabled`) goes to the user's remaining webhooks that subscribe to `account_alert`.",
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id, `evt_` + 32 hex characters. Deterministic: the same\nevent always has the same id (it is also the `webhook-id`\nheader), so receivers can de-duplicate on it."
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "account_alert"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (RFC 3339, UTC, milliseconds)."
          },
          "data": {
            "$ref": "#/components/schemas/WebhookAccountAlertData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "id": "evt_db006f409e35b14728f9b0bd51a7845d",
            "type": "account_alert",
            "created_at": "2026-09-28T04:05:07.120Z",
            "data": {
              "activity_id": "01K6D8ZR0MA1B2C3D4E5F6G7H8",
              "kind": "session_expired",
              "account": "ZX1234",
              "broker": "zerodha",
              "summary": "Zerodha login expired",
              "message": "Log in to Zerodha again to keep trading from this account",
              "outcome": "failed",
              "at": "2026-09-28T04:05:07.120Z"
            }
          }
        ]
      },
      "WebhookAccountAlertData": {
        "type": "object",
        "description": "Something about an account that needs the user.",
        "required": [
          "activity_id",
          "kind",
          "summary",
          "outcome",
          "at"
        ],
        "properties": {
          "activity_id": {
            "type": "string",
            "description": "Id of the activity-log record this alert comes from."
          },
          "kind": {
            "$ref": "#/components/schemas/WebhookAlertKind"
          },
          "account": {
            "type": [
              "string",
              "null"
            ],
            "description": "The account it is about (`null`: the user as a whole)."
          },
          "broker": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker id of that account."
          },
          "summary": {
            "type": "string",
            "description": "One line in plain English."
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "More detail in plain English, when there is any."
          },
          "outcome": {
            "$ref": "#/components/schemas/ActivityOutcome"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "WebhookAlertKind": {
        "type": "string",
        "description": "Activity kinds sent as `account_alert`: `session_expired` (the broker\nlogin ended; log in again), `relogin_detected` (the account was logged\nin elsewhere), `live_updates_unavailable` / `live_updates_restored`\n(the broker's live order feed dropped / came back),\n`protection_failed` (a stop-loss / target could not be placed or\nkept), `order_rejected`, `account_setup_incomplete` (a field one\nfeature needs is missing) and `webhook_disabled` (one of the user's\nwebhooks was turned off after repeated failures).",
        "enum": [
          "session_expired",
          "relogin_detected",
          "live_updates_unavailable",
          "live_updates_restored",
          "protection_failed",
          "order_rejected",
          "account_setup_incomplete",
          "webhook_disabled"
        ]
      },
      "WebhookEvent": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/WebhookOrderUpdate"
          },
          {
            "$ref": "#/components/schemas/WebhookTrade"
          },
          {
            "$ref": "#/components/schemas/WebhookAccountAlert"
          },
          {
            "$ref": "#/components/schemas/WebhookPositions"
          },
          {
            "$ref": "#/components/schemas/WebhookPing"
          }
        ],
        "description": "Any outbound webhook body, told apart by `type`."
      },
      "WebhookOrderUpdate": {
        "type": "object",
        "description": "`order_update`: any change to an order (state, fills, broker id). `data` is the full order, the same as the stream's `order_update`.\n\nEvery delivery is an HTTPS `POST` with `Content-Type: application/json` and a body `{id, type, created_at, data}` (all keys snake_case), signed per Standard Webhooks (https://www.standardwebhooks.com):\n- `webhook-id`: the event `id` (same on every retry; de-duplicate on it);\n- `webhook-timestamp`: Unix seconds when this attempt was sent;\n- `webhook-signature`: `v1,<base64 HMAC-SHA256>` over `{webhook-id}.{webhook-timestamp}.{raw body}`, keyed with the base64-decoded part of the webhook's `whsec_...` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated; accept the message when any one matches.\n\nAnswer 2xx within 5 s. 408, 429, 5xx, timeouts and network errors are retried after 30 s, 2 min, 10 min, 30 min, 1 h and 2 h (7 attempts); other 4xx answers are not retried. A webhook that keeps failing (50 failures in a row, or failing for 24 h) is turned off and an `account_alert` (`webhook_disabled`) goes to the user's remaining webhooks that subscribe to `account_alert`.",
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id, `evt_` + 32 hex characters. Deterministic: the same\nevent always has the same id (it is also the `webhook-id`\nheader), so receivers can de-duplicate on it."
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "order_update"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (RFC 3339, UTC, milliseconds)."
          },
          "data": {
            "$ref": "#/components/schemas/OrderData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "id": "evt_b9af59b3434f9997a6fc3ece875ca056",
            "type": "order_update",
            "created_at": "2026-09-28T04:05:07.120Z",
            "data": {
              "cirrus_tag": "01K6D8ZQ4X9V2M3N5P7R8S9T0W",
              "broker_tag": "01K6D8ZQ4X9V2M3N",
              "order_id": "250928000123456",
              "parent_tag": null,
              "username": "alice",
              "account": "ZX1234",
              "broker": "zerodha",
              "cirrus_token": "CT:1:2:RELIANCE-EQ",
              "tradingsymbol": "RELIANCE-EQ",
              "side": "BUY",
              "order_type": "LIMIT",
              "product": "MIS",
              "quantity": 10,
              "price": 2500,
              "trigger_price": null,
              "state": "PARTIALLY_FILLED",
              "filled_qty": 4,
              "average_price": 2499.8,
              "status_message": null,
              "broker_updated_at": "2026-09-28T04:05:07.120Z",
              "created_at": "2026-09-28T04:05:06.789Z",
              "status_history": [
                {
                  "from": "SUBMITTED",
                  "to": "OPEN",
                  "at": "2026-09-28T04:05:06.789Z",
                  "message": null
                },
                {
                  "from": "OPEN",
                  "to": "PARTIALLY_FILLED",
                  "at": "2026-09-28T04:05:07.120Z",
                  "message": null
                }
              ],
              "lot_size": 1,
              "exchange": "NSE",
              "instrument_type": "EQ",
              "symbol": "RELIANCE-EQ",
              "expiry": "",
              "strike": 0,
              "option_type": "",
              "ltp": 2501.5,
              "prev_close": 2490,
              "instrument_token": "CT:1:2:RELIANCE-EQ",
              "order_tag": "01K6D8ZQ4X9V2M3N5P7R8S9T0W"
            }
          }
        ]
      },
      "WebhookPing": {
        "type": "object",
        "description": "`ping`: a test delivery, sent only when the user asks for one (a new id every time).\n\nEvery delivery is an HTTPS `POST` with `Content-Type: application/json` and a body `{id, type, created_at, data}` (all keys snake_case), signed per Standard Webhooks (https://www.standardwebhooks.com):\n- `webhook-id`: the event `id` (same on every retry; de-duplicate on it);\n- `webhook-timestamp`: Unix seconds when this attempt was sent;\n- `webhook-signature`: `v1,<base64 HMAC-SHA256>` over `{webhook-id}.{webhook-timestamp}.{raw body}`, keyed with the base64-decoded part of the webhook's `whsec_...` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated; accept the message when any one matches.\n\nAnswer 2xx within 5 s. 408, 429, 5xx, timeouts and network errors are retried after 30 s, 2 min, 10 min, 30 min, 1 h and 2 h (7 attempts); other 4xx answers are not retried. A webhook that keeps failing (50 failures in a row, or failing for 24 h) is turned off and an `account_alert` (`webhook_disabled`) goes to the user's remaining webhooks that subscribe to `account_alert`.",
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id, `evt_` + 32 hex characters. Deterministic: the same\nevent always has the same id (it is also the `webhook-id`\nheader), so receivers can de-duplicate on it."
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "ping"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (RFC 3339, UTC, milliseconds)."
          },
          "data": {
            "$ref": "#/components/schemas/WebhookPingData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "id": "evt_789c8513c48f23ed0d0012dde1f53850",
            "type": "ping",
            "created_at": "2026-09-28T04:05:07.120Z",
            "data": {
              "webhook_id": "pb_01k6d8zq4x9v2m3n5p7r8s9t0w",
              "message": "Test event: your endpoint is reachable."
            }
          }
        ]
      },
      "WebhookPingData": {
        "type": "object",
        "description": "The test delivery's content.",
        "required": [
          "webhook_id",
          "message"
        ],
        "properties": {
          "webhook_id": {
            "type": "string",
            "description": "The webhook being tested."
          },
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "WebhookPositions": {
        "type": "object",
        "description": "`positions`: an account's positions changed (full list; at most one per second per account).\n\nEvery delivery is an HTTPS `POST` with `Content-Type: application/json` and a body `{id, type, created_at, data}` (all keys snake_case), signed per Standard Webhooks (https://www.standardwebhooks.com):\n- `webhook-id`: the event `id` (same on every retry; de-duplicate on it);\n- `webhook-timestamp`: Unix seconds when this attempt was sent;\n- `webhook-signature`: `v1,<base64 HMAC-SHA256>` over `{webhook-id}.{webhook-timestamp}.{raw body}`, keyed with the base64-decoded part of the webhook's `whsec_...` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated; accept the message when any one matches.\n\nAnswer 2xx within 5 s. 408, 429, 5xx, timeouts and network errors are retried after 30 s, 2 min, 10 min, 30 min, 1 h and 2 h (7 attempts); other 4xx answers are not retried. A webhook that keeps failing (50 failures in a row, or failing for 24 h) is turned off and an `account_alert` (`webhook_disabled`) goes to the user's remaining webhooks that subscribe to `account_alert`.",
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id, `evt_` + 32 hex characters. Deterministic: the same\nevent always has the same id (it is also the `webhook-id`\nheader), so receivers can de-duplicate on it."
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "positions"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (RFC 3339, UTC, milliseconds)."
          },
          "data": {
            "$ref": "#/components/schemas/WebhookPositionsData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "id": "evt_014d471054c08189e7d7d67e7673474a",
            "type": "positions",
            "created_at": "2026-09-28T04:05:07.120Z",
            "data": {
              "account": "ZX1234",
              "positions": [
                {
                  "account": "ZX1234",
                  "cirrus_token": "CT:1:2:RELIANCE-EQ",
                  "tradingsymbol": "RELIANCE-EQ",
                  "product": "MIS",
                  "net_qty": 4,
                  "buy_qty": 4,
                  "sell_qty": 0,
                  "buy_value": 9999.2,
                  "sell_value": 0,
                  "average_price": 2499.8,
                  "buy_average_price": 2499.8,
                  "sell_average_price": 0,
                  "pnl": 6.8,
                  "lot_size": 1,
                  "exchange": "NSE",
                  "instrument_type": "EQ",
                  "symbol": "RELIANCE-EQ",
                  "expiry": "",
                  "strike": 0,
                  "option_type": "",
                  "ltp": 2501.5,
                  "prev_close": 2490,
                  "instrument_token": "CT:1:2:RELIANCE-EQ"
                }
              ]
            }
          }
        ]
      },
      "WebhookPositionsData": {
        "type": "object",
        "description": "An account's full positions after a change.",
        "required": [
          "account",
          "positions"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "positions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PositionRow"
            }
          }
        },
        "additionalProperties": false
      },
      "WebhookTrade": {
        "type": "object",
        "description": "`trade`: one fill of an order.\n\nEvery delivery is an HTTPS `POST` with `Content-Type: application/json` and a body `{id, type, created_at, data}` (all keys snake_case), signed per Standard Webhooks (https://www.standardwebhooks.com):\n- `webhook-id`: the event `id` (same on every retry; de-duplicate on it);\n- `webhook-timestamp`: Unix seconds when this attempt was sent;\n- `webhook-signature`: `v1,<base64 HMAC-SHA256>` over `{webhook-id}.{webhook-timestamp}.{raw body}`, keyed with the base64-decoded part of the webhook's `whsec_...` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated; accept the message when any one matches.\n\nAnswer 2xx within 5 s. 408, 429, 5xx, timeouts and network errors are retried after 30 s, 2 min, 10 min, 30 min, 1 h and 2 h (7 attempts); other 4xx answers are not retried. A webhook that keeps failing (50 failures in a row, or failing for 24 h) is turned off and an `account_alert` (`webhook_disabled`) goes to the user's remaining webhooks that subscribe to `account_alert`.",
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Event id, `evt_` + 32 hex characters. Deterministic: the same\nevent always has the same id (it is also the `webhook-id`\nheader), so receivers can de-duplicate on it."
          },
          "type": {
            "type": "string",
            "description": "The message type.",
            "enum": [
              "trade"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened (RFC 3339, UTC, milliseconds)."
          },
          "data": {
            "$ref": "#/components/schemas/WebhookTradeData"
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "id": "evt_ae7b238d8eb79444044e61522187f090",
            "type": "trade",
            "created_at": "2026-09-28T04:05:07.120Z",
            "data": {
              "account": "ZX1234",
              "broker": "zerodha",
              "order_id": "250928000123456",
              "order_tag": "01K6D8ZQ4X9V2M3N5P7R8S9T0W",
              "instrument_token": "CT:1:2:RELIANCE-EQ",
              "tradingsymbol": "RELIANCE-EQ",
              "side": "BUY",
              "product": "MIS",
              "order_type": "LIMIT",
              "quantity": 4,
              "price": 2499.8,
              "filled_qty": 4,
              "order_quantity": 10,
              "average_price": 2499.8,
              "order_state": "PARTIALLY_FILLED",
              "filled_at": "2026-09-28T04:05:07.120Z",
              "cirrus_token": "CT:1:2:RELIANCE-EQ",
              "cirrus_tag": "01K6D8ZQ4X9V2M3N5P7R8S9T0W"
            }
          }
        ]
      },
      "WebhookTradeData": {
        "type": "object",
        "description": "A fill: the quantity an order filled since its previous update, with\nthe order's cumulative state after it.",
        "required": [
          "account",
          "broker",
          "order_tag",
          "instrument_token",
          "tradingsymbol",
          "side",
          "product",
          "order_type",
          "quantity",
          "filled_qty",
          "order_quantity",
          "order_state",
          "filled_at"
        ],
        "properties": {
          "account": {
            "type": "string"
          },
          "broker": {
            "type": "string",
            "description": "Broker id."
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Broker order id."
          },
          "order_tag": {
            "type": "string"
          },
          "instrument_token": {
            "type": "string"
          },
          "tradingsymbol": {
            "type": "string"
          },
          "side": {
            "$ref": "#/components/schemas/Side"
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "order_type": {
            "$ref": "#/components/schemas/OrderType"
          },
          "quantity": {
            "type": "integer",
            "format": "int64",
            "description": "Quantity of this fill.",
            "minimum": 0
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Price of this fill (from the change in the order's average price);\n`null` when the average is unknown."
          },
          "filled_qty": {
            "type": "integer",
            "format": "int64",
            "description": "The order's total filled quantity after this fill.",
            "minimum": 0
          },
          "order_quantity": {
            "type": "integer",
            "format": "int64",
            "description": "The order's total quantity.",
            "minimum": 0
          },
          "average_price": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "The order's average fill price after this fill."
          },
          "order_state": {
            "$ref": "#/components/schemas/OrderState"
          },
          "filled_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false,
        "x-deprecated-aliases": {
          "cirrus_token": "instrument_token",
          "cirrus_tag": "order_tag"
        }
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "The user's API key, created in the app: `Authorization: token <key_id>:<key_secret>`. Carries the scopes chosen at creation (`read`, `orders`, `triggers`)."
      },
      "partner_oauth": {
        "type": "oauth2",
        "description": "OAuth 2.0 for partner apps acting for a user: the authorization code flow with PKCE (`S256`). The user approves the app on the app's consent page; the partner then exchanges the code at the token URL and sends `Authorization: Bearer <access_token>`.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://app.cirrus.trade/oauth/authorize",
            "tokenUrl": "https://api.cirrus.trade/v1/oauth/token",
            "refreshUrl": "https://api.cirrus.trade/v1/oauth/token",
            "scopes": {
              "read": "Read portfolio, orders, triggers, GTT, accounts, instruments, the activity log and the stream.",
              "orders": "Place, modify, cancel and convert orders, bracket / cover orders and GTT.",
              "triggers": "Create, change and remove stop-loss / target triggers."
            }
          }
        }
      },
      "app_session": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "The signed-in app session. Routes tagged `app_session_only` accept nothing else."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "`unauthorized`: no credential, or it is invalid, expired or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`forbidden`: the credential lacks the route's scope, the route is for app sessions only, or the caller's IP is not allowed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`rate_limited`: too many requests for this credential; retry later.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "order_update": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "operationId": "webhook_order_update",
        "summary": "An order changed",
        "description": "Sent to each HTTPS receiver the user registered for this event (see `/v1/postbacks`). Answer any 2xx within 5 s; anything else, or no answer, is retried after 30 s, 2 min, 10 min, 30 min, 1 h, 2 h (then the delivery is dropped, and a receiver that keeps failing is turned off). Deliveries can repeat and arrive out of order: de-duplicate on `webhook-id` (also the body's `id`) and order by `created_at`.\n\nSigned per the Standard Webhooks spec: `webhook-signature` is `v1,<base64(HMAC-SHA256(key, \"{webhook-id}.{webhook-timestamp}.{body}\"))>`, where `key` is the base64-decoded part of the receiver's `whsec_` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated: accept the delivery when any one matches. Reject timestamps far from your clock to stop replays.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "Event id (same as the body's `id`); the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Unix seconds when this attempt was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "Space-separated `v1,<base64>` signatures (see above).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookOrderUpdate"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received. Any other answer is retried."
          }
        }
      }
    },
    "trade": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "operationId": "webhook_trade",
        "summary": "An order filled (fully or partly)",
        "description": "Sent to each HTTPS receiver the user registered for this event (see `/v1/postbacks`). Answer any 2xx within 5 s; anything else, or no answer, is retried after 30 s, 2 min, 10 min, 30 min, 1 h, 2 h (then the delivery is dropped, and a receiver that keeps failing is turned off). Deliveries can repeat and arrive out of order: de-duplicate on `webhook-id` (also the body's `id`) and order by `created_at`.\n\nSigned per the Standard Webhooks spec: `webhook-signature` is `v1,<base64(HMAC-SHA256(key, \"{webhook-id}.{webhook-timestamp}.{body}\"))>`, where `key` is the base64-decoded part of the receiver's `whsec_` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated: accept the delivery when any one matches. Reject timestamps far from your clock to stop replays.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "Event id (same as the body's `id`); the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Unix seconds when this attempt was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "Space-separated `v1,<base64>` signatures (see above).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTrade"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received. Any other answer is retried."
          }
        }
      }
    },
    "account_alert": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "operationId": "webhook_account_alert",
        "summary": "Something about an account needs the user",
        "description": "Sent to each HTTPS receiver the user registered for this event (see `/v1/postbacks`). Answer any 2xx within 5 s; anything else, or no answer, is retried after 30 s, 2 min, 10 min, 30 min, 1 h, 2 h (then the delivery is dropped, and a receiver that keeps failing is turned off). Deliveries can repeat and arrive out of order: de-duplicate on `webhook-id` (also the body's `id`) and order by `created_at`.\n\nSigned per the Standard Webhooks spec: `webhook-signature` is `v1,<base64(HMAC-SHA256(key, \"{webhook-id}.{webhook-timestamp}.{body}\"))>`, where `key` is the base64-decoded part of the receiver's `whsec_` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated: accept the delivery when any one matches. Reject timestamps far from your clock to stop replays.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "Event id (same as the body's `id`); the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Unix seconds when this attempt was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "Space-separated `v1,<base64>` signatures (see above).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookAccountAlert"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received. Any other answer is retried."
          }
        }
      }
    },
    "positions": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "operationId": "webhook_positions",
        "summary": "An account's positions changed",
        "description": "Sent to each HTTPS receiver the user registered for this event (see `/v1/postbacks`). Answer any 2xx within 5 s; anything else, or no answer, is retried after 30 s, 2 min, 10 min, 30 min, 1 h, 2 h (then the delivery is dropped, and a receiver that keeps failing is turned off). Deliveries can repeat and arrive out of order: de-duplicate on `webhook-id` (also the body's `id`) and order by `created_at`.\n\nSigned per the Standard Webhooks spec: `webhook-signature` is `v1,<base64(HMAC-SHA256(key, \"{webhook-id}.{webhook-timestamp}.{body}\"))>`, where `key` is the base64-decoded part of the receiver's `whsec_` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated: accept the delivery when any one matches. Reject timestamps far from your clock to stop replays.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "Event id (same as the body's `id`); the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Unix seconds when this attempt was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "Space-separated `v1,<base64>` signatures (see above).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPositions"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received. Any other answer is retried."
          }
        }
      }
    },
    "ping": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "operationId": "webhook_ping",
        "summary": "Test delivery",
        "description": "Sent to each HTTPS receiver the user registered for this event (see `/v1/postbacks`). Answer any 2xx within 5 s; anything else, or no answer, is retried after 30 s, 2 min, 10 min, 30 min, 1 h, 2 h (then the delivery is dropped, and a receiver that keeps failing is turned off). Deliveries can repeat and arrive out of order: de-duplicate on `webhook-id` (also the body's `id`) and order by `created_at`.\n\nSigned per the Standard Webhooks spec: `webhook-signature` is `v1,<base64(HMAC-SHA256(key, \"{webhook-id}.{webhook-timestamp}.{body}\"))>`, where `key` is the base64-decoded part of the receiver's `whsec_` secret. While a rotated secret is still honoured, one signature per secret is sent, space separated: accept the delivery when any one matches. Reject timestamps far from your clock to stop replays.",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "Event id (same as the body's `id`); the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Unix seconds when this attempt was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "Space-separated `v1,<base64>` signatures (see above).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookPing"
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Received. Any other answer is retried."
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://api.cirrus.trade",
      "description": "Cirrus API"
    }
  ]
}
