1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9531],{9531:(e,t,i)=>{i.r(t),i.d(t,{default:()=>C});var n=i(80069),r=i(20801),a=i(63132);let o={apiTitle:"XStable Trading API",apiVersion:"1.0.0",overviewMarkdown:'REST API for programmatic trading on XStable perpetual contracts.\n\n## Base URL\n\n```\nhttps://api.xstable.ai\nwss://api.xstable.ai\n```\n\ne.g. `/api/v1/account/balance`. Full URL = base URL + path â `https://api.xstable.ai/api/v1/account/balance`.\nThe `wss://` base works the same way for the WebSocket stream â `wss://api.xstable.ai/api/v1/ws` (see **WebSocket** below).\n\n## Authentication (API Key + HMAC-SHA256)\n\nPrivate endpoints require an API key created in the user console. Send these headers on every signed request:\n\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-XSTABLE-API-KEY` | Yes | Public API key |\n| `X-XSTABLE-TIMESTAMP` | Yes | Request time in **milliseconds** (Unix epoch) |\n| `X-XSTABLE-NONCE` | Yes | Unique string per request (UUID recommended) |\n| `X-XSTABLE-SIGNATURE` | Yes | HMAC-SHA256 hex digest (see below) |\n| `X-XSTABLE-RECV-WINDOW` | No | Optional receive window in ms. Defaults to `60000` if omitted; **silently capped at `60000`** if you set a larger value (not an error). Must be a positive integer if set â `0`, negative, non-integer (e.g. a decimal), or non-numeric values are rejected with `errorCode` `"3103"` (`invalid_recv_window`). The window check itself is symmetric â a `TIMESTAMP` more than the effective window in the past **or** the future is rejected (`errorCode` `"3102"`, `invalid_timestamp`). |\n\n**Canonical string** (6 lines, LF-separated):\n\n```\n{METHOD}\\n\n{PATH}\\n\n{CANONICAL_QUERY}\\n\n{BODY_SHA256_HEX}\\n\n{TIMESTAMP}\\n\n{NONCE}\n```\n\n- `METHOD`: uppercase HTTP method (`GET`, `POST`, `DELETE`, â¦)\n- `PATH`: full request path **including** context path, e.g. `/api/v1/account/balance` (use `request.getRequestURI()`, not path-only)\n- `CANONICAL_QUERY`: query string with keys sorted lexicographically, values URL-encoded (`+` â `%20`, `~` unescaped)\n- `BODY_SHA256_HEX`: always `SHA-256(body)` as a lowercase hex digest â run the body through the **same\n hashing step on every request**; this line is never the body itself. Hash the exact bytes you send on\n the wire (UTF-8; do not pretty-print, reorder keys, or re-serialize before hashing).\n When there is no request body (typically `GET`/`DELETE`, or any empty-body request), the input to that\n same hash step is simply the **empty string `""`** â don\'t special-case or hardcode it, just feed `""`\n to your normal hashing routine. For reference, `SHA-256("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`,\n so you can sanity-check your implementation against that value.\n Note an empty body is **not** the same as a `{}` body: `SHA-256("")` â `SHA-256("{}")` â hash exactly what you send.\n- `TIMESTAMP` / `NONCE`: same values as headers\n\n**Signature:** `HMAC_SHA256(api_secret, canonical_string)` â lowercase hex.\n\n**IP whitelist:** If configured on the key, requests from other IPs return `403 forbidden`.\n\n## Response envelope\n\nSuccess and error bodies share the same envelope, but populate different fields.\n\n**Success** â `message`, `errorCode`, and `status` are omitted (the server strips them); only `code`, `data`, and `timestamp` are present:\n\n```json\n{\n "code": 200,\n "data": { },\n "timestamp": 1710000000000\n}\n```\n\n**Error** â HTTP status reflects the category (`400`, `401`, `403`, `409`, `429`, `500`, â¦); `data` is omitted and the body adds `errorCode` and `message`:\n\n```json\n{\n "code": 401,\n "errorCode": "3102",\n "message": "invalid_timestamp",\n "timestamp": 1710000000000\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `code` | HTTP-aligned category code (e.g. `401`, `409`) |\n| `errorCode` | Stable internal error code, returned as a **numeric string** (e.g. `"3102"`, `"3107"`) |\n| `message` | Stable machine-readable key (e.g. `invalid_timestamp`, `client_order_id_conflict`). Canonical English; **not** localized by `Accept-Language` on this endpoint. |\n\nBoth `errorCode` and `message` are stable and safe to branch on; `errorCode` is the numeric code, `message` is its string key.\n\n## Error codes\n\nAuthentication and rate-limit errors apply to all private endpoints. Business errors use the\nsame envelope. Use `errorCode` or `message` to identify an error.\n\n| HTTP `code` | `errorCode` | `message` | When |\n|-------------|-------------|-----------|------|\n| 401 | `"3101"` | `invalid_signature` | Signature mismatch |\n| 401 | `"3102"` | `invalid_timestamp` | Timestamp missing / outside the receive window |\n| 401 | `"3103"` | `invalid_recv_window` | `recvWindow` is `0`, negative, non-integer, or non-numeric. A value above `60000` is **not** an error â it\'s silently capped, see `X-XSTABLE-RECV-WINDOW` above. |\n| 401 | `"3104"` | `invalid_nonce` | Nonce missing or replayed |\n| 409 | `"3107"` | `client_order_id_conflict` | Reused `clientOrderId` with different parameters |\n| 429 | `"429"` | `rate_limit_error` | Rate limit exceeded |\n\nCommon trading errors:\n\n| `errorCode` | `message` | When |\n|-------------|-----------|------|\n| `"8073"` | `max_take_profit_error` | Take-profit exceeds the platform limit |\
1n| `"8099"` | `max_stop_loss_error` | Stop-loss exceeds the applicable limit |\n| `"8107"` | `margin_mode_disabled` | Requested margin mode is disabled |\n| `"8125"` | `symbol_lots_not_supported` | Symbol does not support ordering by lots |\n| `"8126"` | `order_quantity_less_than_error` | Converted quantity is below the minimum |\n| `"8128"` | `order_quantity_greater_than_error` | Converted quantity exceeds the maximum |\n\n## Pagination (cursor)\n\nList endpoints use **cursor** pagination. The response `data` wraps the page:\n\n```json\n{\n "items": [],\n "nextCursor": "12345",\n "hasMore": true\n}\n```\n\n- `nextCursor` is an **opaque server cursor** (an internal record id, returned as a string).\n- To fetch the next page, send the previous response\'s `nextCursor` as the `fromId` query\n parameter, along with `limit` (default 50, max 100). On the **first** request omit `fromId`.\n- When `hasMore` is `false`, stop paging.\n\n## Symbols\n\nCanonical symbol format is `BASE/QUOTE`, e.g. `BTC/USD`. \n\n## Rate limits\n\nTwo independent limiters apply (see deployment config):\n\n- **Public endpoints** (no API key â market data and connectivity) are limited **per client IP**.\n- **Private endpoints** (API key) are limited **per user, per bucket** â a bucket\'s quota is\n **shared across every path listed for it**, not tracked separately per path. For example,\n the `trade-write` bucket\'s 30/min applies to the combined call volume of all of its listed\n paths together, not 30/min to each one individually.\n\n| Bucket | Scope | Methods | Paths | Limit |\n|--------|-------|---------|-------|-------|\n| public market data | per IP | GET | `/api/v1/time`, `/api/v1/markets`, `/api/v1/ticker`, `/api/v1/ohlcv` | 60 / 10s |\n| private-read | per user | GET | `/api/v1/account/balance`, `/api/v1/account/ledger`, `/api/v1/account/risk`, `/api/v1/account/symbol-preferences`, `/api/v1/capital/history`, `/api/v1/positions`, `/api/v1/positions/history`, `/api/v1/orders/open`, `/api/v1/orders/history` | 60/min |\n| trade-write | per user | POST, DELETE | `/api/v1/positions/close`, `/api/v1/positions/close-all`, `/api/v1/positions/trading-stop`, `/api/v1/orders/{orderId}`, `/api/v1/account/symbol-preferences/margin-mode` | 30/min |\n| place order | per user | POST | `/api/v1/orders` | 1/5s |\n\nExceeding limits returns HTTP `429` with `message` `rate_limit_error` (and `errorCode`\n`"429"`). **Private endpoints** (`private-read`, `trade-write`, `place order`) also return a\n`Retry-After` header (seconds until the bucket allows another request); the public market\ndata limiter does not currently send this header.',servers:["https://api.xstable.ai"],endpoints:[{name:"getAccountBalance",method:"GET",url:"/api/v1/account/balance",tag:"Account",summary:"Account balance",description:"Account balance summary â total, available, used margin, and realized PnL.",descriptionMarkdown:"Account balance summary â total, available, used margin, and realized PnL.",security:!0,responseSchema:"BalanceResponse",requestFields:[],responseFields:[{name:"asset",type:"string",required:!1,description:"Settlement asset of the account.",location:"body",enumValues:[]},{name:"totalBalance",type:"string (decimal)",required:!1,description:"Total account balance.",location:"body",enumValues:[]},{name:"availableBalance",type:"string (decimal)",required:!1,description:"Balance available for opening new orders.",location:"body",enumValues:[]},{name:"usedMargin",type:"string (decimal)",required:!1,description:"Margin currently locked by open positions and orders.",location:"body",enumValues:[]},{name:"realizedPnl",type:"string (decimal)",required:!1,description:"Realized profit and loss.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getAccountBalance"},{name:"getAccountLedger",method:"GET",url:"/api/v1/account/ledger",tag:"Account",summary:"Account ledger",description:"Cursor-paged fund flow history.",descriptionMarkdown:"Cursor-paged fund flow history.",security:!0,responseSchema:"CursorPageFundFlow",requestFields:[{name:"fromId",type:"integer (int64)",required:!1,description:"From Id. Format: int64",location:"query",enumValues:[]},{name:"limit",type:"integer",required:!1,description:"Limit. Default: 50. Range: 1 â 100",location:"query",enumValues:[]},{name:"type",type:'"DEPOSIT" | "WITHDRAW" | "OPEN_POSITION" | "CLOSE_POSITION" | "FUNDING_FEE"',required:!1,description:"Type. Allowed values: DEPOSIT, WITHDRAW, OPEN_POSITION, CLOSE_POSITION, FUNDING_FEE",location:"query",enumValues:["DEPOSIT","WITHDRAW","OPEN_POSITION","CLOSE_POSITION","FUNDING_FEE"]},{name:"startTime",type:"integer (int64)",required:!1,description:"Start Time. Format: int64",location:"query",enumValues:[]},{name:"endTime",type:"integer (int64)",required:!1,description:"End Time. Format: int64",location:"query",enumValues:[]}],responseFields:[{name:"items",type:"object[]",required:!1,description:"Fund-flow records in the current page.",location:"body",enumValues:[]},{name:"nextCursor",type:"string",required:!1,description:"Pass it back as the `fromId` query parameter to get the next page; not present in `items`. Null when there is no data.",location:"body",enumValues:[]},{name:"hasMore",type:"boolean",required:!1,description:"Whether more pages are available.",location:"body",enumValues:[]},{name:"items[].id",type:"string",required:!1,description:"Item in page. Fund-flow record ID.",location:"body",enumValues:[]},{name:"items[].timestamp",type:"integer (int64)",required:!1,description:"Item in page. Time of the fund flow in milliseconds.",location:"body",enumValues:[]},{name:"items[].type",type:"string",required:!1,description:"Item in page. Fund-flow type (e.g. deposit, funding fee).",location:"body",enumValues:[]},{name:"items[].amount",type:"string (decimal)",required:!1,description:"Item in page. Positive = inflow, negative = outflow",location:"body",enumValues:[]},{name:"items[].fee",type:"string (decimal)",required:!1,description:"Item in page. Trading fee plus funding fee",location:"body",enumValues:[]},{name:"items[].fundingFee",type:"string (decimal)",required:!1,description:"Item in page. Funding fee component.",location:"body",enumValues:[]},{name:"items[].lpFee",type:"string (decimal)",required:!1,description:"Item in page. Liquidity-provider fee",location:"body",enumValues:[]},{name:"items[].usedMargin",type:"string (decimal)",required:!1,description:"Item in page. Margin in use after this fund flow.",location:"body",enumValues:[]},{name:"items[].availableBalance",type:"string (decimal)",required:!1,description:"Item in page. Available balance after this fund flow.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getAccountLedger"},{name:"getAccountRisk",method:"GET",url:"/api/v1/account/risk",tag:"Account",summary:"Account risk snapshot",description:"Real-time account-level risk snapshot: cross-margin ratio, maintenance margin, equity, and per-position estimated liquidation price.",descriptionMarkdown:"Real-time account-level risk snapshot: cross-margin ratio, maintenance margin, equity, and per-position estimated liquidation price.",security:!0,responseSchema:"AccountRiskResponse",requestFields:[],responseFields:[{name:"riskLevel",type:'"normal" | "high"',required:!1,description:"Indicates the current account risk status. high represents elevated account risk, while normal indicates the account is o
1perating within the normal risk range.",location:"body",enumValues:["normal","high"]},{name:"timestamp",type:"integer (int64)",required:!1,description:"Time the snapshot was computed (ms).",location:"body",enumValues:[]},{name:"totalBalance",type:"string (decimal)",required:!1,description:"Total account balance.",location:"body",enumValues:[]},{name:"equity",type:"string (decimal)",required:!1,description:"Total balance plus unrealized PnL.",location:"body",enumValues:[]},{name:"crossRiskEquity",type:"string (decimal)",required:!1,description:"Equity available to cross-margin positions for risk purposes.",location:"body",enumValues:[]},{name:"unrealizedPnl",type:"string (decimal)",required:!1,description:"Unrealized profit and loss across open positions.",location:"body",enumValues:[]},{name:"usedMargin",type:"string (decimal)",required:!1,description:"Margin currently locked by open positions and orders.",location:"body",enumValues:[]},{name:"maintenanceMargin",type:"string (decimal)",required:!1,description:"Total maintenance margin required across cross-margin positions.",location:"body",enumValues:[]},{name:"crossMarginRatio",type:"string (decimal)",required:!1,description:"`maintenanceMargin / crossRiskEquity`, as a decimal fraction (`1` = 100%). Higher means closer to liquidation.",location:"body",enumValues:[]},{name:"marginLevel",type:"string (decimal)",required:!1,description:'Display-only margin level: `(equity - liquidationFeeMargin) / usedMargin`, where `usedMargin` is the sum of margin used by cross positions, isolated positions, and open-order risk margin across both. Lower means riskier (opposite direction from `crossMarginRatio`); `0` when `usedMargin <= 0` (no margin in use anywhere on the account, not just "no cross positions").',location:"body",enumValues:[]},{name:"crossAvailableBalance",type:"string (decimal)",required:!1,description:"Balance available for opening new cross-margin orders.",location:"body",enumValues:[]},{name:"isolatedAvailableBalance",type:"string (decimal)",required:!1,description:"Balance available for opening new isolated-margin orders.",location:"body",enumValues:[]},{name:"trialFundMap",type:"object",required:!1,description:"Available trial/experience fund balance, keyed by asset.",location:"body",enumValues:[]},{name:"positions",type:"array",required:!1,description:"Per-position risk detail for all open positions.",location:"body",enumValues:[]},{name:"positions[].positionId",type:"string",required:!1,description:"Item in positions array. Server-assigned position ID.",location:"body",enumValues:[]},{name:"positions[].estimatedLiquidationPrice",type:"string (decimal)",required:!1,description:"Item in positions array. Estimated liquidation price. For cross-margin positions this is solved from the account's shared risk pool; for isolated positions it is the position's own liquidation price.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getAccountRisk"},{name:"listSymbolPreferences",method:"GET",url:"/api/v1/account/symbol-preferences",tag:"Account",summary:"Symbol margin / position preferences",description:"Per-symbol `marginMode` and `positionMode`.",descriptionMarkdown:"Per-symbol `marginMode` and `positionMode`.",security:!0,responseSchema:"UserSymbolPreference",requestFields:[],responseFields:[{name:"data[].symbol",type:"string",required:!1,description:"Item in response data array. Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"data[].marginMode",type:'"cross" | "isolated"',required:!1,description:"Item in response data array. Margin mode set for this symbol.",location:"body",enumValues:["cross","isolated"]},{name:"data[].positionMode",type:'"one_way" | "hedge" | "atomic"',required:!1,description:"Item in response data array. Position mode set for this symbol.",location:"body",enumValues:["one_way","hedge","atomic"]}],source:"docs/openapi.yaml#listSymbolPreferences"},{name:"switchMarginMode",method:"POST",url:"/api/v1/account/symbol-preferences/margin-mode",tag:"Account",summary:"Switch margin mode",description:"Switch the margin mode for a symbol with no open positions or orders. Currently only `cross` is supported; `isolated` is rejected.",descriptionMarkdown:"Switch the margin mode for a symbol with no open positions or orders. Currently only `cross` is supported; `isolated` is rejected.",security:!0,requestSchema:"SwitchMarginModeRequest",responseSchema:"UserSymbolPreference",requestFields:[{name:"symbol",type:"string",required:!0,description:"Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"marginMode",type:'"cross" | "isolated"',required:!0,description:"Target margin mode. Currently only `cross` is supported; `isolated` is rejected.",location:"body",enumValues:["cross","isolated"]}],responseFields:[{name:"symbol",type:"string",required:!1,description:"Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"marginMode",type:'"cross" | "isolated"',required:!1,description:"Margin mode set for this symbol.",location:"body",enumValues:["cross","isolated"]},{name:"positionMode",type:'"one_way" | "hedge" | "atomic"',required:!1,description:"Position mode set for this symbol.",location:"body",enumValues:["one_way","hedge","atomic"]}],source:"docs/openapi.yaml#switchMarginMode"},{name:"getCapitalHistory",method:"GET",url:"/api/v1/capital/history",tag:"Capital",summary:"Deposit / withdrawal history",description:"Cursor-paged deposit and withdrawal records, optionally filtered by record type.",descriptionMarkdown:"Cursor-paged deposit and withdrawal records, optionally filtered by record type.",security:!0,responseSchema:"CursorPageDepositWithdraw",requestFields:[{name:"fromId",type:"integer (int64)",required:!1,description:"From Id. Format: int64",location:"query",enumValues:[]},{name:"limit",type:"integer",required:!1,description:"Limit. Default: 50. Range: 1 â 100",location:"query",enumValues:[]},{name:"recordType",type:'"deposit" | "withdraw"',required:!1,description:"Record Type. Allowed values: deposit, withdraw",location:"query",enumValues:["deposit","withdraw"]}],responseFields:[{name:"items",type:"object[]",required:!1,description:"Deposit / withdrawal records in the current page.",location:"body",enumValues:[]},{name:"nextCursor",type:"string",required:!1,description:"Pass it back as the `fromId` query parameter to get the next page; not present in `items`. Null when there is no data.",location:"body",enumValues:[]},{name:"hasMore",type:"boolean",required:!1,description:"Whether more pages are available.",location:"body",enumValues:[]},{name:"items[].id",type:"string",required:!1,description:"Item in page. Record ID.",location:"body",enumValues:[]},{name:"items[].day",type:"integer (int64)",required:!1,description:"Item in page. Business day bucket (yyyyMMdd)",location:"body",enumValues:[]},{name:"items[].network",type:"string",required:!1,description:"Item in page. Blockchain network used.",location:"body",enumValues:[]},{name:"items[].address",type:"string",required:!1,description:"Item in page. On-chain address of the transfer.",location:"body",enumValues:[]},{name:"items[].asset",type:"string",required:!1,description:"Item in page. Asset transferred.",location:"body",enumValues:[]},{name:"items[].amount",type:"string (decimal)",required:!1,description:"Item in page. Net amount (after fee)",location:"body",enumValues:[]},{name:"items[].fee",type:"string (decimal)",required:!1,description:"Item in page. Fee charged for the transfer.",location:"body",enumValues:[]},{name:"items[].grossAmount",type:"string (decimal)",required:!1,description:"Item in page. Gross amount (before fee)",location:"body",enumValues:[]},{name:"items[].recordType",type:'"deposit" | "withdraw"',required:!1,description:"Item in page. Whether the record
1is a deposit or a withdrawal.",location:"body",enumValues:["deposit","withdraw"]},{name:"items[].status",type:'"pending" | "processing" | "success" | "failed"',required:!1,description:"Item in page. Current status of the transfer.",location:"body",enumValues:["pending","processing","success","failed"]},{name:"items[].timestamp",type:"integer (int64)",required:!1,description:"Item in page. Time of the transfer in milliseconds.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getCapitalHistory"},{name:"getServerTime",method:"GET",url:"/api/v1/time",tag:"General",summary:"Server time",description:"Returns current server time in milliseconds. Use to sync local clock before signing requests.",descriptionMarkdown:"Returns current server time in milliseconds. Use to sync local clock before signing requests.",security:!0,responseSchema:"TimeResponse",requestFields:[],responseFields:[{name:"serverTime",type:"integer (int64)",required:!1,description:"Current server time in milliseconds.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getServerTime"},{name:"getMarkets",method:"GET",url:"/api/v1/markets",tag:"Market Data",summary:"Exchange information",description:"Trading rules, symbol list, precision, leverage bounds, and filters.",descriptionMarkdown:"Trading rules, symbol list, precision, leverage bounds, and filters.",security:!0,responseSchema:"ExchangeInfoResponse",requestFields:[],responseFields:[{name:"timezone",type:"string",required:!1,description:"Timezone of `serverTime`. Always `UTC`.",location:"body",enumValues:[]},{name:"serverTime",type:"integer (int64)",required:!1,description:"Server time when the snapshot was produced (ms)",location:"body",enumValues:[]},{name:"symbols",type:"array",required:!1,description:"One entry per listed trading symbol",location:"body",enumValues:[]},{name:"symbols[].symbol",type:"string",required:!1,description:"Item in symbols array. Canonical symbol, `BASE/QUOTE`",location:"body",enumValues:[]},{name:"symbols[].pair",type:"string",required:!1,description:"Item in symbols array. Same as `symbol`",location:"body",enumValues:[]},{name:"symbols[].baseAsset",type:"string",required:!1,description:"Item in symbols array. Base asset (left of the `/`)",location:"body",enumValues:[]},{name:"symbols[].quoteAsset",type:"string",required:!1,description:"Item in symbols array. Quote asset (right of the `/`)",location:"body",enumValues:[]},{name:"symbols[].name",type:"string",required:!1,description:"Item in symbols array. Human-readable instrument name",location:"body",enumValues:[]},{name:"symbols[].contractType",type:"string",required:!1,description:"Item in symbols array. Always `perpetual`",location:"body",enumValues:[]},{name:"symbols[].status",type:'"trading" | "halt"',required:!1,description:"Item in symbols array. `trading` = open for trading, `halt` = suspended",location:"body",enumValues:["trading","halt"]},{name:"symbols[].orderTypes",type:'"limit" | "market"[]',required:!1,description:"Item in symbols array. Supported order types. Always `[limit, market]`.",location:"body",enumValues:[]},{name:"symbols[].timeInForce",type:"string[]",required:!1,description:"Item in symbols array. Supported time-in-force values. Always `[gtc]`.",location:"body",enumValues:[]},{name:"symbols[].marginModes",type:'"cross" | "isolated"[]',required:!1,description:"Item in symbols array. Enabled margin modes, shared across all symbols. Currently returns `[cross]`.",location:"body",enumValues:[]},{name:"symbols[].positionModes",type:'"one_way" | "hedge" | "atomic"[]',required:!1,description:"Item in symbols array. Currently only `atomic` is returned (margin/position-mode switching for other modes is not supported).",location:"body",enumValues:[]},{name:"symbols[].pricePrecision",type:"integer",required:!1,description:"Item in symbols array. Max number of decimal places for price. Equals `-log10(tickSize)`.",location:"body",enumValues:[]},{name:"symbols[].quantityPrecision",type:"integer",required:!1,description:"Item in symbols array. Max number of decimal places for quantity (decimal scale of `stepSize`).",location:"body",enumValues:[]},{name:"symbols[].filters",type:"object[]",required:!1,description:"Item in symbols array. Trading filters; always one `price_filter` and one `lot_size`.",location:"body",enumValues:[]},{name:"symbols[].maxLeverage",type:"integer",required:!1,description:"Item in symbols array. Maximum allowed leverage",location:"body",enumValues:[]},{name:"symbols[].minLeverage",type:"integer",required:!1,description:"Item in symbols array. Minimum allowed leverage",location:"body",enumValues:[]},{name:"symbols[].lotSize",type:"string (decimal)",required:!1,description:"Item in symbols array. Base quantity per lot: `quantity * lotSize` converts lots to base quantity. Zero means lot-based orders are unsupported. The `lot_size` filter defines quantity steps separately.",location:"body",enumValues:[]},{name:"symbols[].minOrderQuantity",type:"string (decimal)",required:!1,description:"Item in symbols array. Minimum base quantity after conversion, for opening or adding to a position; excludes closes. Null means quantity limits are unavailable and opening orders are rejected.",location:"body",enumValues:[]},{name:"symbols[].maxOrderQuantity",type:"string (decimal)",required:!1,description:"Item in symbols array. Maximum base quantity after conversion, for opening or adding to a position; excludes closes. Null means quantity limits are unavailable and opening orders are rejected.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getMarkets"},{name:"getOhlcv",method:"GET",url:"/api/v1/ohlcv",tag:"Market Data",summary:"Candlesticks",description:"OHLCV candlestick data for a symbol over the requested interval and time range.",descriptionMarkdown:"OHLCV candlestick data for a symbol over the requested interval and time range.",security:!0,responseSchema:"KlineResponse",requestFields:[{name:"symbol",type:"string",required:!0,description:"Symbol. Required",location:"query",enumValues:[]},{name:"interval",type:'"1m" | "5m" | "15m" | "1h" | "4h" | "1D" | "1W"',required:!1,description:'Interval. Allowed values: 1m, 5m, 15m, 1h, 4h, 1D, 1W. Default: "1m"',location:"query",enumValues:["1m","5m","15m","1h","4h","1D","1W"]},{name:"startTime",type:"integer (int64)",required:!1,description:"Start Time. Format: int64",location:"query",enumValues:[]},{name:"endTime",type:"integer (int64)",required:!1,description:"End Time. Format: int64",location:"query",enumValues:[]},{name:"limit",type:"integer",required:!1,description:"Limit. Default: 1000. Range: 1 â 1000",location:"query",enumValues:[]}],responseFields:[{name:"data[].timestamp",type:"integer (int64)",required:!1,description:"Item in response data array. Candle open time in milliseconds.",location:"body",enumValues:[]},{name:"data[].open",type:"string (decimal)",required:!1,description:"Item in response data array. Open price of the candle.",location:"body",enumValues:[]},{name:"data[].high",type:"string (decimal)",required:!1,description:"Item in response data array. Candle high, including the open and continuity-adjusted close.",location:"body",enumValues:[]},{name:"data[].low",type:"string (decimal)",required:!1,description:"Item in response data array. Candle low, including the open and continuity-adjusted close.",location:"body",enumValues:[]},{name:"data[].close",type:"string (decimal)",required:!1,description:"Item in response data array. Close price of the candle. Historical candles may be revised to match the next candle open, expanding high or low when needed.",location:"body",enumValues:[]},{name:"data[].volume",type:"string (decimal)",required:!1,description:"Item in response data array. Traded volume during the candle.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getOhlcv"},{name:"getTicker",method:"GET",url:"/api/v1/ticker",tag:"Market Data",summary:"Latest price",description:"Latest price for one symbol.",descriptionMarkdown:"Latest price for one symbol.",security:!0,responseSchema:"TickerPriceResponse",requestFields:[{name:"symbol",type:"string",required:!0,description:"Symbol. Required",location:"query",enumValues:[]}],responseFields:[{name:"symbol",type:"string",required:!1,description:"Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"timestamp",type:"integer (int64)",required:!1,description:"Server time when the price was read (ms)",location:"body",enumValues:[]},{name:"price",type:"string (decimal)",required:!1,description:"Latest price",location:"body",enumValues:[]},{name:"spread",type:"string (decimal)",required:!1,description:"Generic display spread (source spread + default platform spread; not personalized per user). Re-resolve the actual spread for the logged-in user before placing an order.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getTicker"},{name:"placeOrder",method:"POST",url:"/api/v1/orders",tag:"Orders",summary:"Place order",description:"Create a market or limit order. Execution is asynchronous;
1 the immediate response has `status: pending` and contains no fill details. - Market orders: check `GET /api/v1/positions` for a new position or a quantity change. Market fills are not listed in `GET /api/v1/orders/history`. - Limit orders: check `GET /api/v1/orders/open` and `GET /api/v1/orders/history`. An order may fill or be canceled before appearing in the open list. API Key clients have no per-order status or fill-notification endpoint. A missing result does not establish failure; creating another order with a new ID can duplicate the trade. ### Idempotent retries Use a new `clientOrderId` for each new order. Retry uncertain requests with the same ID and identical business parameters, regenerating the timestamp, nonce, and signature. A matching retry returns the original order without executing it again; changed business parameters return HTTP `409` (`client_order_id_conflict`). Deduplication lasts 7 days per account, shared across its API keys; recognition after that window is not guaranteed. For API Key requests, the compared business fields are `symbol`, `side`, `type`, `quantityType`, `quantity`, `leverage`, `price`, `takeProfitRate`, `stopLossRate`, `takeProfitPrice`, `stopLossPrice`, `marginMode`, and `positionMode`.",descriptionMarkdown:"Create a market or limit order. Execution is asynchronous; the immediate response has\n`status: pending` and contains no fill details.\n\n- Market orders: check `GET /api/v1/positions` for a new position or a quantity change.\n Market fills are not listed in `GET /api/v1/orders/history`.\n- Limit orders: check `GET /api/v1/orders/open` and `GET /api/v1/orders/history`.\n An order may fill or be canceled before appearing in the open list.\n\nAPI Key clients have no per-order status or fill-notification endpoint. A missing result\ndoes not establish failure; creating another order with a new ID can duplicate the trade.\n\n### Idempotent retries\n\nUse a new `clientOrderId` for each new order. Retry uncertain requests with the same ID\nand identical business parameters, regenerating the timestamp, nonce, and signature.\nA matching retry returns the original order without executing it again; changed business\nparameters return HTTP `409` (`client_order_id_conflict`). Deduplication lasts 7 days\nper account, shared across its API keys; recognition after that window is not guaranteed.\n\nFor API Key requests, the compared business fields are `symbol`, `side`, `type`,\n`quantityType`, `quantity`, `leverage`, `price`, `takeProfitRate`, `stopLossRate`,\n`takeProfitPrice`, `stopLossPrice`, `marginMode`, and `positionMode`.",security:!0,requestSchema:"PlaceOrderRequest",responseSchema:"PlaceOrderResponse",requestFields:[{name:"symbol",type:"string",required:!0,description:"Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"side",type:'"long" | "short"',required:!0,description:"Order direction â `long` or `short`.",location:"body",enumValues:["long","short"]},{name:"type",type:'"market" | "limit"',required:!0,description:"Order type â `market` or `limit`.",location:"body",enumValues:["market","limit"]},{name:"quantityType",type:'"margin" | "base_quantity" | "order_value" | "lots"',required:!1,description:"Unit of `quantity`: `margin` (margin amount), `base_quantity` (contract quantity), `order_value` (notional value), or `lots` (lot count). Lots require a positive symbol `lotSize`.",location:"body",enumValues:["margin","base_quantity","order_value","lots"]},{name:"quantity",type:"string (decimal)",required:!0,description:"Order size in the selected `quantityType`. Converted base quantity must be within the symbol's `minOrderQuantity` and `maxOrderQuantity` from `GET /api/v1/markets`.",location:"body",enumValues:[]},{name:"leverage",type:"integer",required:!0,description:"Leverage multiplier for the order.",location:"body",enumValues:[]},{name:"takeProfitRate",type:"string (decimal)",required:!1,description:"Take-profit ROI on margin, excluding fees (`1` = 100%). Must be positive if supplied and within any configured platform limit. Takes precedence over `takeProfitPrice`. Omit both fields for no take-profit.",location:"body",enumValues:[]},{name:"stopLossRate",type:"string (decimal)",required:!1,description:"Stop-loss ROI on margin, excluding fees (`1` = 100% margin loss). Must be non-negative. A positive value takes precedence over `stopLossPrice`; zero is treated as omitted. Without a positive rate or a supplied price, no stop-loss is set. For isolated margin, the maximum is `1` or a lower configured limit. Cross margin has no rate ceiling, but the resulting trigger price must be positive.",location:"body",enumValues:[]},{name:"takeProfitPrice",type:"string (decimal)",required:!1,description:"Take-profit trigger price. Must be positive if supplied, even when `takeProfitRate` takes precedence. Used when `takeProfitRate` is omitted.",location:"body",enumValues:[]},{name:"stopLossPrice",type:"string (decimal)",required:!1,description:"Stop-loss trigger price. Must be positive if supplied, even when `stopLossRate` takes precedence. Used when `stopLossRate` is omitted or zero.",location:"body",enumValues:[]},{name:"price",type:"string (decimal)",required:!1,description:"Required when `t
1ype` is `limit` (limit orders).",location:"body",enumValues:[]},{name:"clientOrderId",type:"string",required:!0,description:"Client-generated order ID, unique within your account. Reuse it with identical business parameters for retries within 7 days; see Idempotent retries above.",location:"body",enumValues:[]},{name:"marginMode",type:'"cross" | "isolated"',required:!0,description:"Margin mode for the order. Currently only `cross` is supported. Read the current symbol preference from `GET /api/v1/account/symbol-preferences`.",location:"body",enumValues:["cross","isolated"]},{name:"positionMode",type:'"atomic"',required:!1,description:"Position mode for the order. Obtain the symbol's current value from `GET /api/v1/account/symbol-preferences`.",location:"body",enumValues:["atomic"]}],responseFields:[],source:"docs/openapi.yaml#placeOrder"},{name:"cancelOrderById",method:"DELETE",url:"/api/v1/orders/{orderId}",tag:"Orders",summary:"Cancel an open order",description:'Cancel a working **limit** order that has not been filled yet, identified by its server `orderId` (the `orderId` returned by `GET /api/v1/orders/open`). On success, returns the `canceled` shape (`#/components/schemas/PlaceOrderResponseCanceled`). **Behavior change (2026-09-07):** this endpoint previously returned `status: "open"` on a successful cancel (a bug â the order was not, in fact, still open). It now correctly returns `status: "canceled"`. A client that branched on the literal string `"open"` to confirm a successful cancel will need to check for `"canceled"` instead.',descriptionMarkdown:'Cancel a working **limit** order that has not been filled yet, identified by its server `orderId` (the `orderId` returned by `GET /api/v1/orders/open`). On success, returns the `canceled` shape (`#/components/schemas/PlaceOrderResponseCanceled`).\n**Behavior change (2026-09-07):** this endpoint previously returned `status: "open"` on a successful cancel (a bug â the order was not, in fact, still open). It now correctly returns `status: "canceled"`. A client that branched on the literal string `"open"` to confirm a successful cancel will need to check for `"canceled"` instead.',security:!0,responseSchema:"PlaceOrderResponse",requestFields:[{name:"orderId",type:"string",required:!0,description:"Order Id. Required",location:"path",enumValues:[]}],responseFields:[],source:"docs/openapi.yaml#cancelOrderById"},{name:"getOrderHistory",method:"GET",url:"/api/v1/orders/history",tag:"Orders",summary:"Order history",description:"Filled or canceled limit/conditional orders. **Does not include market order fills** â to check the outcome of a market order (which may return `status: pending`), poll `GET /api/v1/positions` instead.",descriptionMarkdown:"Filled or canceled limit/conditional orders. **Does not include market order fills** â to check the outcome of a market order (which may return `status: pending`), poll `GET /api/v1/positions` instead.",security:!0,responseSchema:"CursorPageOrderHistory",requestFields:[{name:"fromId",type:"integer (int64)",required:!1,description:"From Id. Format: int64",location:"query",enumValues:[]},{name:"limit",type:"integer",required:!1,description:"Limit. Default: 50. Range: 1 â 100",location:"query",enumValues:[]}],responseFields:[{name:"items",type:"object[]",required:!1,description:"Historical orders in the current page.",location:"body",enumValues:[]},{name:"nextCursor",type:"string",required:!1,description:"Pass it back as the `fromId` query parameter to get the next page; not present in `items`. Null when there is no data.",location:"body",enumValues:[]},{name:"hasMore",type:"boolean",required:!1,description:"Whether more pages are available.",location:"body",enumValues:[]},{name:"items[].orderId",type:"string",required:!1,description:"Item in page. Server-assigned order ID.",location:"body",enumValues:[]},{name:"items[].clientOrderId",type:"string",required:!1,description:"Item in page. Client-supplied order ID.",location:"body",enumValues:[]},{name:"items[].positionId",type:"string",required:!1,description:"Item in page. ID of the position this order belongs to.",location:"body",enumValues:[]},{name:"items[].symbol",type:"string",required:!1,description:"Item in page. Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"items[].side",type:"string",required:!1,description:"Item in page. Order direction â `long` or `short`.",location:"body",enumValues:[]},{name:"items[].type",type:"string",required:!1,description:"Item in page. Order type â `market` or `limit`.",location:"body",enumValues:[]},{name:"items[].status",type:'"filled" | "canceled" | "rejected"',required:!1,description:"Item in page. Final order status.",location:"body",enumValues:["filled","canceled","rejected"]},{name:"items[].orderTypeDetail",type:"string",required:!1,description:"Item in page. Detailed order classification.",location:"body",enumValues:[]},{name:"items[].reduceOnly",type:"boolean",required:!1,description:"Item in page. Whether the order only reduces an existing position.",location:"body",enumValues:[]},{name:"items[].quantityType",type:'"margin" | "base_quantity" | "order_value" | "lots"',required:!1,description:"Item in page. How `quantity` was interpreted.",location:"body",enumValues:["margin","base_quantity","order_value","lots"]},{name:"items[].quantity",type:"string (decimal)",required:!1,description:"Item in page. Order quantity in contracts.",location:"body",enumValues:[]},{name:"items[].filled",type:"string (decimal)",required:!1,description:"Item in page. Quantity filled.",location:"body",enumValues:[]},{name:"items[].remaining",type:"string (decimal)",required:!1,description:"Item in page. Quantity not filled.",location:"body",enumValues:[]},{name:"items[].price",type:"string (decimal)",required:!1,description:"Item in page. Order price.",location:"body",enumValues:[]},{name:"items[].triggerPrice",type:"string (decimal)",required:!1,description:"Item in page. Trigger price for conditional orders.",location:"body",enumValues:[]},{name:"items[].leverage",type:"integer",required:!1,description:"Item in page. Leverage multiplier of the order.",location:"body",enumValues:[]},{name:"items[].margin",type:"string (decimal)",required:!1,description:"Item in page. Margin allocated to the order.",location:"body",enumValues:[]},{name:"items[].marginMode",type:"string",required:!1,description:"Item in page. Margin mode of the order.",location:"body",enumValues:[]},{name:"items[].positionMode",type:"string",required:!1,description:"Item in page. Position mode of the order.",location:"body",enumValues:[]},{name:"items[].takeProfitRate",type:"string (decimal)",required:!1,description:"Item in page. Take-profit as a decimal fraction (`1` = 100%).",location:"body",enumValues:[]},{name:"items[].stopLossRate",type:"string (decimal)",required:!1,description:"Item in page. Stop-loss as a decimal fraction (`1` = 100%).",location:"body",enumValues:[]},{name:"items[].timestamp",type:"integer (int64)",required:!1,description:"Item in page. Order creation time in milliseconds.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getOrderHistory"},{name:"getOpenOrders",method:"GET",url:"/api/v1/orders/open",tag:"Orders",summary:"Open orders",description:"Current pending orders",descriptionMarkdown:"Current pending orders",security:!0,responseSchema:"CursorPageOpenOrder",requestFields:[{name:"fromId",type:"integer (int64)",required:!1,description:"From Id. Format: int64",location:"query",enumValues:[]},{name:"limit",type:"integer",required:!1,description:"Limit. Default: 50. Range: 1 â 100",location:"query",enumValues:[]}],responseFields:[{name:"items",type:"object[]",required:!1,description:"Open orders in the current page.",location:"body",enumValues:[]},{name:"nextCursor",type:"string",required:!1,description:"Pass it back as the `fromId` query parameter to get the next page; not present in `items`. Null when there is no data.",location:"body",enumValues:[]},{name:"hasMore",type:"boolean",required:!1,description:"Whether more pages are available.",location:"body",enumValues:[]},{name:"items[].orderId",type:"string",required:!1,description:"Item in page. Server-assigned order ID.",location:"body",enumValues:[]},{name:"items[].clientOrderId",type:"string",required:!1,description:"Item in page. Client-supplied order ID.",location:"body",enumValues:[]},{name:"items[].symbol",type:"string",required:!1,description:"Item in page. Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"items[].side",type:"string",required:!1,description:"Item in page. Order direction â `long` or `short`.",location:"body",enumValues:[]},{name:"items[].type",type:"string",required:!1,description:"Item in page. Order type â `market` or `limit`.",location:"body",enumValues:[]},{name:"items[].status",type:"string",required:!1,description:"Item in page. Current order status.",location:"body",enumValues:[]},{name:"items[].orderTypeDetail",type:"string",required:!1,description:"Item in page. Detailed order classification.",location:"body",enumValues:[]},{name:"items[].reduceOnly",type:"boolean",required:!1,description:"Item in page. Whether the order only reduces an existing position.",location:"body",enumValues:[]},{name:"items[].quantityType",type:"string",required:!1,description:"Item in page. How `quantity` is interpreted.",location:"body",enumValues:[]},{name:"items[].quantity",type:"string (decimal)",required:!1,description:"Item in page. Order quantity in contracts.",location:"body",enumValues:[]},{name:"items[].filled",type:"string (decimal)",required:!1,description:"Item in page. Quantity already filled.",location:"body",enumValues:[]},{name:"items[].remaining",type:"string (decimal)",required:!1,description:"Item in page. Quantity not yet filled.",location:"body",enumValues:[]},{name:"items[].price",type:"string (decimal)",required:!1,description:"Item in page. Order price.",location:"body",enumValues:[]},{name:"items[].triggerPrice",type:"string (decimal)",required:!1,description:"Item in page. Trigger price for conditional orders.",location:"body",enumValues:[]},{name:"items[].marketPrice",type:"string (decimal)",required:!1,description:"Item in page. Current market price.",location:"body",enumValues:[]},{name:"items[].leverage",type:"integer",required:!1,description:"Item in page. Leverage multiplier of the order.",location:"body",enumValues:[]},{name:"items[].margin",type:"string (decimal)",required:!1,description:"Item in page. Margin allocated to the order.",location:"body",enumValues:[]},{name:"items[].marginMode",type:"string",required:!1,description:"Item in page. Margin mode of the order.",location:"body",enumValues:[]},{name:"items[].positionMode",type:"string",required:!1,description:"Item in page. Position mode of the order.",location:"body",enumValues:[]},{name:"items[].takeProfitRate",type:"string (decimal)",required:!1,description:"Item in page. Take-profit as a decimal fraction (`1` = 100%).",location:"body",enumValues:[]},{name:"items[].stopLossRate",type:"string (decimal)",required:!1,description:"Item in page. Stop-loss as a decimal fraction (`1` = 100%).",location:"body",enumValues:[]},{name:"items[].timestamp",type:"integer (int64)",required:!1,description:"Item in page. Order creation time in milliseconds.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getOpenOrders"},{name:"getPositions",method:"GET",url:"/api/v1/positions",tag:"Positions",summary:"Open positions",description:"All currently open positions for the account, including attached TP/SL. This is also the endpoint to poll after placing a market order that returned `status: pending` â check for the expected position to appear (or an existing one's quantity to change) to confirm it filled.",descriptionMarkdown:"All currently open positions for the account, including attached TP/SL. This is also the endpoint to poll after placing a market order that returned `status: pending` â check for the expected position to appear (or an existing one's quantity to change) to confirm it filled.",security:!0,responseSchema:"UserPosition",requestFields:[],responseFields:[{name:"data[].positionId",type:"string",required:!1,description:"Item in response data array. Server-assigned position ID.",location:"body",enumValues:[]},{name:"data[].symbol",type:"string",required:!1,description:"Item in response data array. Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"data[].quantity",type:"string (decimal)",required:!1,description:"Item in response data array. Position size in contracts.",location:"body",enumValues:[]},{name:"data[].positionSide",type:'"long" | "short"',required:!1,description:"Item in response data array. Direction of the position â `long` or `short`.",location:"body",enumValues:["long","short"]},{name:"data[].leverage",type:"integer",required:!1,description:"Item in response data array. Leverage multiplier of the position.",location:"body",enumValues:[]},{name:"data[].notionalValue",type:"string (decimal)",required:!1,description:"Item in response data array. Current notional value, computed as `quantity * internal
1closable price` (spread/slippage-adjusted), not `quantity * marketPrice`.",location:"body",enumValues:[]},{name:"data[].entryPrice",type:"string (decimal)",required:!1,description:"Item in response data array. Average entry price.",location:"body",enumValues:[]},{name:"data[].marketPrice",type:"string (decimal)",required:!1,description:"Item in response data array. Current market price.",location:"body",enumValues:[]},{name:"data[].liquidationPrice",type:"string (decimal)",required:!1,description:"Item in response data array. Estimated liquidation price.",location:"body",enumValues:[]},{name:"data[].margin",type:"string (decimal)",required:!1,description:"Item in response data array. Margin allocated to the position.",location:"body",enumValues:[]},{name:"data[].fundingFee",type:"string (decimal)",required:!1,description:"Item in response data array. Accumulated funding fee.",location:"body",enumValues:[]},{name:"data[].openFee",type:"string (decimal)",required:!1,description:"Item in response data array. Fee charged when opening the position.",location:"body",enumValues:[]},{name:"data[].unrealizedPnl",type:"string (decimal)",required:!1,description:"Item in response data array. Unrealized profit and loss, computed from the internal closable price (spread/slippage-adjusted), not from `marketPrice`.",location:"body",enumValues:[]},{name:"data[].returnRate",type:"string (decimal)",required:!1,description:"Item in response data array. Return rate as a percentage value, not a fraction (`100` = 100%, i.e. `unrealizedPnl / margin * 100`).",location:"body",enumValues:[]},{name:"data[].takeProfitStopLossOrders",type:"object[]",required:!1,description:"Item in response data array. Attached TP/SL conditional orders",location:"body",enumValues:[]},{name:"data[].closeLimitOrders",type:"object[]",required:!1,description:"Item in response data array. Attached close limit orders",location:"body",enumValues:[]},{name:"data[].marginMode",type:"string",required:!1,description:"Item in response data array. Margin mode of the position.",location:"body",enumValues:[]},{name:"data[].positionMode",type:"string",required:!1,description:"Item in response data array. Position mode of the position.",location:"body",enumValues:[]},{name:"data[].timestamp",type:"integer (int64)",required:!1,description:"Item in response data array. Position open time in milliseconds.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getPositions"},{name:"closePosition",method:"POST",url:"/api/v1/positions/close",tag:"Positions",summary:"Close position",description:"Market-close a single position.",descriptionMarkdown:"Market-close a single position.",security:!0,requestSchema:"ClosePositionRequest",responseSchema:"PlaceOrderResponse",requestFields:[{name:"positionId",type:"string",required:!0,description:"ID of the position to close.",location:"body",enumValues:[]}],responseFields:[],source:"docs/openapi.yaml#closePosition"},{name:"closeAllPositions",method:"POST",url:"/api/v1/positions/close-all",tag:"Positions",summary:"Close all positions",description:"Market-close all positions.",descriptionMarkdown:"Market-close all positions.",security:!0,responseSchema:"CloseAllPositionsResponse",requestFields:[],responseFields:[{name:"total",type:"integer",required:!1,description:"Total number of positions attempted to close.",location:"body",enumValues:[]},{name:"successCount",type:"integer",required:!1,description:"Number of positions closed successfully.",location:"body",enumValues:[]},{name:"failedCount",type:"integer",required:!1,description:"Number of positions that failed to close.",location:"body",enumValues:[]},{name:"failedReasons",type:"array",required:!1,description:"Reasons for each failed close.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#closeAllPositions"},{name:"getPositionHistory",method:"GET",url:"/api/v1/positions/history",tag:"Positions",summary:"Position / trade history",description:"Historical fills and position events.",descriptionMarkdown:"Historical fills and position events.",security:!0,responseSchema:"CursorPageTrade",requestFields:[{name:"symbol",type:"string",required:!1,description:"Symbol",location:"query",enumValues:[]},{name:"fromId",type:"integer (int64)",required:!1,description:"From Id. Format: int64",location:"query",enumValues:[]},{name:"limit",type:"integer",required:!1,description:"Limit. Default: 50. Range: 1 â 100",location:"query",enumValues:[]},{name:"startTime",type:"integer (int64)",required:!1,description:"Start Time. Format: int64",location:"query",enumValues:[]},{name:"endTime",type:"integer (int64)",required:!1,description:"End Time. Format: int64",location:"query",enumValues:[]}],responseFields:[{name:"items",type:"object[]",required:!1,description:"Trades in the current page.",location:"body",enumValues:[]},{name:"nextCursor",type:"string",required:!1,description:"Pass it back as the `fromId` query parameter to get the next page; not present in `items`. Null when there is no data.",location:"body",enumValues:[]},{name:"hasMore",type:"boolean",required:!1,description:"Whether more pages are available.",location:"body",enumValues:[]},{name:"items[].id",type:"string",required:!1,description:"Item in page. Trade ID.",location:"body",enumValues:[]},{name:"items[].orderId",type:"string",required:!1,description:"Item in page. ID of the order that produced this trade.",location:"body",enumValues:[]},{name:"items[].positionId",type:"string",required:!1,description:"Item in page. ID of the related position.",location:"body",enumValues:[]},{name:"items[].symbol",type:"string",required:!1,description:"Item in page. Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"items[].side",type:"string",required:!1,description:"Item in page. Trade direction â `long` or `short`.",location:"body",enumValues:[]},{name:"items[].positionSide",type:"string",required:!1,description:"Item in page. Side of the related position â `long` or `short`.",location:"body",enumValues:[]},{name:"items[].tradeType",type:'"open" | "close"',required:!1,description:"Item in page. Whether the trade opened or closed a position.",location:"body",enumValues:["open","close"]},{name:"items[].orderTypeDetail",type:"string",required:!1,description:"Item in page. Detailed order classification.",location:"body",enumValues:[]},{name:"items[].takerOrMaker",type:"string",required:!1,description:"Item in page. Always `taker` (no order book matching)",location:"body",enumValues:[]},{name:"items[].quantity",type:"string (decimal)",required:!1,description:"Item in page. Trade quantity in contracts.",location:"body",enumValues:[]},{name:"items[].price",type:"string (decimal)",required:!1,description:"Item in page. Execution price.",location:"body",enumValues:[]},{name:"items[].entryPrice",type:"string (decimal)",required:!1,description:"Item in page. Position entry price.",location:"body",enumValues:[]},{name:"items[].cost",type:"string (decimal)",required:!1,description:"Item in page. Notional = quantity * price",location:"body",enumValues:[]},{name:"items[].leverage",type:"integer",required:!1,description:"Item in page. Leverage multiplier of the trade.",location:"body",enumValues:[]},{name:"items[].margin",type:"string (decimal)",required:!1,description:"Item in page. Margin associated with the trade.",location:"body",enumValues:[]},{name:"items[].marginMode",type:"string",required:!1,description:"Item in page. Margin mode of the trade.",location:"body",enumValues:[]},{name:"items[].fee",type:"string (decimal)",required:!1,description:"Item in page. Trading fee charged.",location:"body",enumValues:[]},{name:"items[].fundingFee",type:"string (decimal)",required:!1,description:"Item in page. Funding fee settled with the trade.",location:"body",enumValues:[]},{name:"items[].lpFee",type:"string (decimal)",required:!1,description:"Item in page. Liquidity-provider fee",location:"body",enumValues:[]},{name:"items[].realizedPnl",type:"string (decimal)",required:!1,description:"Item in page. Net realized P&L for this trade",location:"body",enumValues:[]},{name:"items[].positionPnl",type:"string (decimal)",required:!1,description:"Item in page. Position P&L from price movement",location:"body",enumValues:[]},{name:"items[].txHash",type:"string",required:!1,description:"Item in page. On-chain transaction hash, when applicable.",location:"body",enumValues:[]},{name:"items[].timestamp",type:"integer (int64)",required:!1,description:"Item in page. Trade execution time in milliseconds.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#getPositionHistory"},{name:"updateTradingStop",method:"POST",url:"/api/v1/positions/trading-stop",tag:"Positions",summary:"Update position TP/SL",description:"Replace take-profit and stop-loss settings on an open position.",descriptionMarkdown:"Replace take-profit and stop-loss settings on an open position.",security:!0,requestSchema:"UpdateTriggerPriceRequest",responseSchema:"TradingStopResponse",requestFields:[{name:"positionId",type:"string",required:!0,description:"ID of the position to update. Each request replaces both TP/SL settings; re-submit any side you want to retain. Sending only `positionId` clears both sides.",location:"body",enumValues:[]},{name:"takeProfitRate",type:"string (decimal)",required:!1,description:"Take-profit ROI on margin, excluding fees (`1` = 100%). Must be non-negative. A positive value overrides `takeProfitPrice`; zero clears the take-profit regardless of price. If null or omitted, a positive `takeProfitPrice` sets the take-profit; otherwise it is cleared. Positive rates must be within any configured platform limit.",location:"body",enumValues:[]},{name:"stopLossRate",type:"string (decimal)",required:!1,description:"Stop-loss ROI on margin, excluding fees (`1` = 100% margin loss). Must be non-negative. A positive value overrides `stopLossPrice`; zero clears the stop-loss regardless of price. If null or omitted, a positive `stopLossPrice` sets the stop-loss; otherwise it is cleared. For isolated margin, the maximum is `1` or a lower configured limit. Cross margin has no rate ceiling, but the resulting trigger price must be positive.",location:"body",enumValues:[]},{name:"takeProfitPrice",type:"string (decimal)",required:!1,description:"Take-profit trigger price. Used when `takeProfitRate` is null or omitted: a positive price sets the take-profit; null, omitted, or zero clears it. Negative prices are rejected even when a rate is supplied.",location:"body",enumValues:[]},{name:"stopLossPrice",type:"string (decimal)",required:!1,description:"Stop-loss trigger price. Used when `stopLossRate` is null or omitted: a positive price sets the stop-loss; null, omitted, or zero clears it. Negative prices are rejected even when a rate is supplied.",location:"body",enumValues:[]}],responseFields:[{name:"positionId",type:"string",required:!1,description:"ID of the updated position.",location:"body",enumValues:[]},{name:"symbol",type:"string",required:!1,description:"Trading symbol, `BASE/QUOTE` (e.g. `BTC/USD`).",location:"body",enumValues:[]},{name:"positionSide",type:"string",required:!1,description:"Direction of the position â `long` or `short`.",location:"body",enumValues:[]},{name:"takeProfitRate",type:"string (decimal)",required:!1,description:"Take-profit as a decimal fraction (`1` = 100%).",location:"body",enumValues:[]},{name:"stopLossRate",type:"string (decimal)",required:!1,description:"Stop-loss as a decimal fraction (`1` = 100%).",location:"body",enumValues:[]},{name:"takeProfitPrice",type:"string (decimal)",required:!1,description:"Take-profit trigger price.",location:"body",enumValues:[]},{name:"stopLossPrice",type:"string (decimal)",required:!1,description:"Stop-loss trigger price.",location:"body",enumValues:[]}],source:"docs/openapi.yaml#updateTradingStop"},{name:"webSocketConnect",method:"GET",url:"/api/v1/ws",tag:"WebSocket",summary:"WebSocket endpoint",description:'Public market-data stream. No authentication is required. **URL:** `/api/v1/ws` ### Client â server messages | `op` | Description | |------|-------------| | `ping` | Heartbeat; server replies `pong` | | `subscribe` | Subscribe to the `ticker` channel | | `unsubscribe` | Unsubscribe | **Subscribe example:** ```json { "id": "2", "op": "subscribe", "args": [ { "channel": "ticker", "symbol": "BTC/USD" } ] } ``` ### Heartbeat (ping / pong) The client drives the heartbeat: send a `ping` **once per minute** and the server replies with a `pong` event echoing your `id` and the server time (`data.time`, ms). Use it to keep the connection alive and to detect a dead link. Request: ```json { "id": "1", "op": "ping" } ``` Response: ```json { "event": "pong", "id": "1", "success": true, "data": { "time": 1710000000000 }, "timestamp": 1710000000000 } ``` ### Server â client envelope There are two distinct message shapes. **Do not assume every message has an `event` field** â
1check for `channel` first to tell them apart: - **Control messages** (connection/auth/subscription/heartbeat/error) carry `event` (one of the values below), plus `id`, `success`, and (for errors) `code` / `errorCode` / `message`. - **Channel push messages** (business data, e.g. `ticker`) carry **no `event` field at all** â only `channel`, `data`, and `timestamp`. A real example: ```json { "channel": "ticker", "data": { "symbol": "NAS/USD", "timestamp": 1788852272272, "price": "29589.72", "spread": "0.20" }, "timestamp": 1788852272834 } ``` `data` has the same shape as `TickerPriceResponse` (`GET /api/v1/ticker`). | `event` (control messages only) | Meaning | |---------|---------| | `connected` | Connection established | | `subscribed` / `unsubscribed` | Subscription ack | | `pong` | Ping response | | `error` | Error | | `reconnect` | Server is about to close the socket (e.g. max connection age); reconnect | **Channels:** `ticker`. ### Connection lifetime A connection is automatically closed after about **24 hours**. Just before closing, the server sends a `reconnect` event.',descriptionMarkdown:'Public market-data stream. No authentication is required.\n\n**URL:** `/api/v1/ws`\n\n### Client â server messages\n\n| `op` | Description |\n|------|-------------|\n| `ping` | Heartbeat; server replies `pong` |\n| `subscribe` | Subscribe to the `ticker` channel |\n| `unsubscribe` | Unsubscribe |\n\n**Subscribe example:**\n\n```json\n{\n "id": "2",\n "op": "subscribe",\n "args": [\n { "channel": "ticker", "symbol": "BTC/USD" }\n ]\n}\n```\n\n### Heartbeat (ping / pong)\n\nThe client drives the heartbeat: send a `ping` **once per minute** and the server replies\nwith a `pong` event echoing your `id` and the server time (`data.time`, ms). Use it to keep\nthe connection alive and to detect a dead link.\n\nRequest:\n\n```json\n{ "id": "1", "op": "ping" }\n```\n\nResponse:\n\n```json\n{ "event": "pong", "id": "1", "success": true, "data": { "time": 1710000000000 }, "timestamp": 1710000000000 }\n```\n\n### Server â client envelope\n\nThere are two distinct message shapes. **Do not assume every message has an `event`\nfield** â check for `channel` first to tell them apart:\n\n- **Control messages** (connection/auth/subscription/heartbeat/error) carry `event`\n (one of the values below), plus `id`, `success`, and (for errors) `code` /\n `errorCode` / `message`.\n- **Channel push messages** (business data, e.g. `ticker`) carry **no `event` field at\n all** â only `channel`, `data`, and `timestamp`. A real example:\n\n ```json\n {\n "channel": "ticker",\n "data": { "symbol": "NAS/USD", "timestamp": 1788852272272, "price": "29589.72", "spread": "0.20" },\n "timestamp": 1788852272834\n }\n ```\n\n `data` has the same shape as `TickerPriceResponse` (`GET /api/v1/ticker`).\n\n| `event` (control messages only) | Meaning |\n|---------|---------|\n| `connected` | Connection established |\n| `subscribed` / `unsubscribed` | Subscription ack |\n| `pong` | Ping response |\n| `error` | Error |\n| `reconnect` | Server is about to close the socket (e.g. max connection age); reconnect |\n\n**Channels:** `ticker`.\n\n### Connection lifetime\n\nA connection is automatically closed after about **24 hours**. Just before closing, the server sends a `reconnect` event.',security:!0,requestFields:[],responseFields:[],source:"docs/openapi.yaml#webSocketConnect"}]},s={page:"w-full h-full overflow-hidden bg-main-background text-text-dark flex flex-col",header:"shrink-0 border-b border-panel-border-color bg-main-background",headerInner:"mx-auto flex h-14 max-w-[1300px] items-center px-4 md:px-8",headerBack:"text-sm font-medium text-text-light transition hover:text-text-dark cursor-pointer",shell:"api-docs-shell grid grid-cols-1 gap-8 px-4 md:px-8 flex-1 min-h-0 lg:grid-cols-[240px_minmax(0,1fr)] lg:items-stretch lg:px-8",sidebar:"hidden lg:block lg:h-full lg:self-stretch lg:overflow-hidden",sidebarInner:"custom-scrollbar api-docs-sidebar-scroll h-full overflow-x-hidden overflow-y-auto border-r border-panel-border-color pr-3",sidebarContent:"my-5",sidebarTitle:"text-xs font-semibold uppercase tracking-[0.18em] text-text-light",navPageButton:"block w-full rounded-[8px] px-3 py-2 text-left text-sm text-text-light transition hover:bg-token-list-item-hover-color hover:text-text-dark",navPageButtonActive:"bg-token-list-item-hover-color text-text-dark font-medium",sidebarDivider:"my-5 border-t border-panel-border-color",sidebarSearch:"h-10 w-full rounded-[10px] border border-panel-border-color bg-transparent px-3 text-sm text-text-dark outline-none placeholder:text-text-light focus:border-main-color",navGroup:"mt-4",navGroupTitle:"mb-2 text-sm font-semibold uppercase tracking-[0.14em] text-text-dark",endpointButton:"block w-full rounded-[8px] px-3 py-2 text-left text-sm text-text-light transition hover:bg-token-list-item-hover-color hover:text-text-dark",endpointButtonActive:"bg-token-list-item-hover-color text-text-dark",endpointButtonRow:"flex min-w-0 items-center justify-between gap-2",endpointButtonName:"min-w-0 truncate font-mono text-sm",endpointMethodBadge:"shrink-0 rounded px-1.5 py-0.5 text-[10px] font-semibold leading-none",main:"min-w-0 h-full lg:overflow-hidden",article:"w-full h-full lg:overflow-y-auto",eyebrow:"text-sm font-medium text-main-color",title:"text-[34px] font-semibold leading-tight text-text-dark md:text-[48px]",pageContent:"my-5",sectionSubtitle:"mt-3 text-sm leading-7 text-text-light",endpointDescription:"mt-6 rounded-[12px] border border-panel-border-color bg-panel-background p-4 md:p-5",endpointDescriptionCode:"mt-4 overflow-x-auto rounded-[10px] border border-panel-border-color bg-block-background p-4 font-mono text-xs leading-6 text-[#1A91F3]",endpointDescriptionHeading:"mt-8 mb-3 text-base font-semibold text-text-dark first:mt-0",endpointDescriptionStrong:"mt-4 text-sm font-semibold text-text-dark first:mt-0",codeBlock:"mt-4 overflow-x-auto rounded-[12px] border border-panel-border-color bg-block-background p-4 font-mono text-xs leading-6 text-text-dark",methodIndexGrid:"mt-5 grid grid-cols-1 gap-6 md:grid-cols-2",methodIndexTitle:"text-sm font-semibold text-text-dark",methodIndexList:"mt-3 space-y-2",methodIndexItem:"block rounded-[8px] p-2 transition hover:bg-token-list-item-hover-color",paramTable:"mt-4 overflow-hidden rounded-[12px] border border-panel-border-color",paramTableHead:"grid grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)_72px_minmax(0,1.6fr)] gap-3 border-b border-panel-border-color bg-block-background px-4 py-3 text-xs font-semibold uppercase tracking-[0.12em] text-text-light",paramRow:"grid grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)_72px_minmax(0,1.6fr)] gap-3 border-b border-panel-border-color px-4 py-3 last:border-b-0",paramNameCell:"flex min-w-0 flex-wrap items-center gap-2",paramName:"font-mono text-sm text-text-dark",paramRequired:"rounded bg-[#E43C5A33] px-1.5 py-0.5 text-[10px] font-medium text-[#E43C5A]",paramType:"self-start font-mono text-xs text-main-color",paramLocation:"self-start text-xs text-text-light",paramDescription:"text-sm leading-6 text-text-light",apiPathRow:"mt-4 inline-flex max-w-full flex-wrap items-center gap-2 rounded-[8px] bg-block-background px-3 py-2",apiPath:"break-all font-mono text-xs leading-6 text-[#1A91F3] md:text-sm",methodBadgeGet:"bg-[#EDBE1833] text-main-color",methodBadgePost:"bg-[#2EBD8533] text-[#2EBD85]",methodBadgeDefault:"bg-[#FFFFFF1A] text-text-light",pill:"rounded-full bg-block-background px-3 py-1 text-xs text-text-light",mobileNavBar:"sticky top-0 z-[110] -mx-4 mb-4 flex items-center gap-3 border-b border-panel-border-color bg-main-background px-4 py-3 lg:static lg:mx-0 lg:hidden",mobileMenuButton:"inline-flex h-10 shrink-0 items-center gap-2 rounded-[10px] border border-panel-border-color bg-panel-background px-3 text-sm font-medium text-text-dark transition hover:border-main-color",mobileNavLabel:"min-w-0 truncate text-sm text-text-light",mobileDrawerOverlay:"fixed inset-0 z-[120] bg-black/50 lg:hidden",mobileDrawerPanel:"custom-scrollbar api-docs-sidebar-scroll fixed inset-y-0 left-0 z-[121] flex w-[min(320px,85vw)] flex-col border-r border-panel-border-color bg-main-background shadow-xl transition-transform duration-300 ease-out lg:hidden",mobileDrawerPanelOpen:"translate-x-0",mobileDrawerHeader:"flex items-center justify-between border-b border-panel-border-color px-4 py-3",mobileDrawerTitle:"text-sm font-semibold text-text-dark",mobileDrawerClose:"inline-flex h-8 w-8 items-center justify-center rounded-[8px] text-text-light transition hover:bg-token-list-item-hover-color hover:text-text-dark",mobileDrawerBody:"flex-1 overflow-y-auto px-4 py-4",empty:"rounded-[14px] border border-panel-border-color bg-panel-background p-8 text-center text-sm text-text-light",mdParagraph:"mt-4 text-sm leading-7 text-text-light first:mt-0",mdStrongLine:"mt-4 text-sm font-semibold text-text-dark",mdList:"mt-4 list-disc space-y-2 pl-5 text-sm leading-7 text-text-light",mdTableWrap:"mt-4 overflow-x-auto rounded-[12px] border border-panel-border-color",mdTable:"w-full min-w-[480px] border-collapse text-left text-sm",mdTableHead:"border-b border-panel-border-color bg-block-background text-xs uppercase tracking-[0.1em] text-text-light",mdTableCell:"border-b border-panel-border-color px-4 py-3 text-text-light",mdTableHeadCell:"border-b border-panel-border-color px-4 py-3 font-medium text-text-dark",tryItButton:"ml-4 inline-flex items-center gap-2 rounded-lg px-4 py-2 bg-main-color text-white hover:opacity-90 transition cursor-pointer",drawerOverlay:"fixed inset-0 z-[130] bg-black/50",drawerPanel:"fixed right-0 top-0 bottom-0 z-[131] w-full max-w-lg bg-main-background shadow-xl transition-transform",drawerPanelClosed:"translate-x-full",drawerPanelOpen:"translate-x-0",drawerHeader:"flex items-center justify-between border-b border-panel-border-color px-6 py-4",drawerTitle:"text-lg font-semibold text-text-dark",drawerClose:"p-2 hover:bg-panel-background rounded transition cursor-pointer text-text-light hover:text-text-dark",drawerBody:"p-6 overflow-y-auto custom-scrollbar max-h-[calc(100vh-80px)]",credentialSection:"space-y-4 mb-6",inputField:"w-full rounded border border-panel-border-color bg-panel-background px-3 py-2 text-sm text-text-dark outline-none focus:border-main-color transition",inputLabel:"block text-sm font-medium text-text-dark mb-1",buttonPrimary:"w-full rounded-lg px-4 py-2 bg-main-color text-white font-medium hover:opacity-90 transition cursor-pointer",responseSection:"mt-6",responseViewer:"rounded-lg bg-block-background p-4 font-mono text-xs overflow-x-auto whitespace-pre-wrap break-all",responseSuccess:"text-green-500",responseError:"text-red-500",responseLoading:"text-text-light animate-pulse",statusBadge:"inl
1ine-flex items-center rounded px-2 py-1 text-xs font-medium",statusSuccess:"bg-green-500/20 text-green-500",statusError:"bg-red-500/20 text-red-500"};function d(e){return encodeURIComponent(e).replace(/~/g,e=>e)}async function l(e){let t=new TextEncoder().encode(e);return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256",t))).map(e=>e.toString(16).padStart(2,"0")).join("")}async function c(e,t){let i=new TextEncoder,n=i.encode(e),r=i.encode(t),a=await crypto.subtle.importKey("raw",n,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return Array.from(new Uint8Array(await crypto.subtle.sign("HMAC",a,r))).map(e=>e.toString(16).padStart(2,"0")).join("")}async function m(e,t,i,n,r,a){var o;let s=i.method,m="https://api.xstable.ai/".replace(/\/$/,""),p="".concat(m).concat(i.url),u=new Map,y=a||{};if(r)for(let e of r){if(!e.value)continue;let t=i.requestFields.find(t=>t.name===e.name);t&&"query"===t.location&&u.set(e.name,e.value)}let g=Array.from(u.entries()).sort((e,t)=>{let[i]=e,[n]=t;return i.localeCompare(n)}),h=g.map(e=>{let[t,i]=e;return"".concat(d(t),"=").concat(d(i))}).join("&"),b=new URLSearchParams;for(let[e,t]of g)b.append(e,t);let f=new URL(p+(b.toString()?"?".concat(b.toString()):"")).pathname,x="",v="";Object.keys(y).length>0&&(x=JSON.stringify(y)),v=await l(x);let q=Date.now(),w=crypto.randomUUID(),k=(o=v,[s.toUpperCase(),f,h,o,String(q),w].join("\n")),I=await c(t,k),T={"X-XSTABLE-API-KEY":e,"X-XSTABLE-TIMESTAMP":String(q),"X-XSTABLE-NONCE":w,"X-XSTABLE-SIGNATURE":I};return Object.keys(y).length>0&&(T["Content-Type"]="application/json"),T}var p=i(34733);function u(e){let{open:t,onClose:i,endpoint:o}=e,[d,l]=(0,r.useState)(""),[c,u]=(0,r.useState)(""),[y,g]=(0,r.useState)([]),[h,b]=(0,r.useState)(!1),[f,x]=(0,r.useState)(null),[v,q]=(0,r.useState)(null),[w,k]=(0,r.useState)(t);(0,r.useEffect)(()=>{k(t)},[t]),(0,r.useEffect)(()=>{w&&g(o.requestFields.map(e=>({name:e.name,value:""})))},[w,o]),(0,r.useEffect)(()=>{w||(l(""),u(""),x(null),q(null))},[w]),(0,r.useEffect)(()=>{if(!t)return;let e=e=>{"Escape"===e.key&&i()};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[t,i]);let I="https://api.xstable.ai/",T=async()=>{if(!d||!c)return void q("Please enter your API credentials");for(let e of o.requestFields.filter(e=>e.required)){let t=y.find(t=>t.name===e.name);if(!(null==t?void 0:t.value))return void q("Missing required parameter: ".concat(e.name))}b(!0),q(null),x(null);try{let e=new URLSearchParams,t={};for(let i of y){if(!i.value)continue;let n=o.requestFields.find(e=>e.name===i.name);if(n){if("query"===n.location)e.set(i.name,i.value);else if("body"===n.location){let e=Number(i.value);t[i.name]=Number.isNaN(e)?i.value:e}}}let i=await m(d,c,o,I,y,t),n=I.replace(/\/$/,""),r={method:o.method,url:o.url,baseURL:n,headers:i};e.toString()&&(r.params=e),Object.keys(t).length>0&&(r.data=t);let s=(await (0,a.A)(r)).data;"object"==typeof s?x(JSON.stringify(s,null,2)):x(String(s))}catch(i){if(a.A.isAxiosError(i)){var e,t;let n=null==(e=i.response)?void 0:e.status,r=null==(t=i.response)?void 0:t.data;if(r){let e="object"==typeof r?JSON.stringify(r,null,2):String(r);q("HTTP ".concat(n,": ").concat(e))}else q(i.message)}else q(i instanceof Error?i.message:"Unknown error occurred")}finally{b(!1)}},S=(e,t)=>{g(i=>i.map(i=>i.name===e?{...i,value:t}:i))};return t?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("div",{className:s.drawerOverlay,onClick:i}),(0,n.jsxs)("aside",{className:(0,p.cn)(s.drawerPanel,t?s.drawerPanelOpen:s.drawerPanelClosed),children:[(0,n.jsxs)("div",{className:s.drawerHeader,children:[(0,n.jsxs)("h2",{className:s.drawerTitle,children:["Try it:"," ",o.method," ",o.url]}
1),(0,n.jsx)("button",{className:s.drawerClose,onClick:i,"aria-label":"Close",children:"\xd7"})]}),(0,n.jsxs)("div",{className:s.drawerBody,children:[(0,n.jsxs)("div",{className:s.credentialSection,children:[(0,n.jsx)("h3",{className:s.methodIndexTitle,children:"API Credentials"}),(0,n.jsx)("p",{className:s.sectionSubtitle,children:"Enter your API key and secret to sign requests."}),(0,n.jsxs)("div",{children:[(0,n.jsx)("label",{htmlFor:"apiKey",className:s.inputLabel,children:"API Key"}),(0,n.jsx)("input",{id:"apiKey",type:"text",className:s.inputField,placeholder:"Enter your API key",value:d,onChange:e=>l(e.target.value)})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("label",{htmlFor:"apiSecret",className:s.inputLabel,children:"API Secret"}),(0,n.jsx)("input",{id:"apiSecret",type:"password",className:s.inputField,placeholder:"Enter your API secret",value:c,onChange:e=>u(e.target.value)})]})]}),o.requestFields.length>0&&(0,n.jsxs)("div",{className:s.credentialSection,children:[(0,n.jsx)("h3",{className:s.methodIndexTitle,children:"Request Parameters"}),(0,n.jsx)("p",{className:s.sectionSubtitle,children:"Fill in the required parameters for this request."}),o.requestFields.map(e=>{var t,i,r,a;let o=function(e){if(e.match(/^"([^"]+)"(?:\s*\|\s*"([^"]+)")*$/)){let t=[];for(let i of e.split(/\s*\|\s*/)){let e=i.match(/^"([^"]+)"$/);e&&t.push(e[1])}return t.length>0?t:null}return null}(e.type);return(0,n.jsxs)("div",{children:[(0,n.jsxs)("label",{htmlFor:"param-".concat(e.name),className:s.inputLabel,children:[e.name,e.required&&(0,n.jsx)("span",{className:"text-red-500 ml-1",children:"*"}),(0,n.jsxs)("span",{className:"text-text-light ml-2",children:["(",e.location,")"]})]}),o?(0,n.jsxs)("select",{id:"param-".concat(e.name),className:s.inputField,value:null!=(r=null==(t=y.find(t=>t.name===e.name))?void 0:t.value)?r:"",onChange:t=>S(e.name,t.target.value),children:[(0,n.jsxs)("option",{value:"",children:["Select",e.name,"..."]}),o.map(e=>(0,n.jsx)("option",{value:e,children:e},e))]}):(0,n.jsx)("input",{id:"param-".concat(e.name),type:"text",className:s.inputField,placeholder:e.description||"Enter ".concat(e.name),value:null!=(a=null==(i=y.find(t=>t.name===e.name))?void 0:i.value)?a:"",onChange:t=>S(e.name,t.target.value)}),(0,n.jsx)("p",{className:"text-xs text-text-light mt-1",children:e.description})]},e.name)})]}),(0,n.jsx)("button",{className:(0,p.cn)(s.buttonPrimary,"mt-3"),disabled:h,onClick:T,children:h?"Sending...":"Send Request"}),f&&(0,n.jsxs)("div",{className:s.responseSection,children:[(0,n.jsx)("div",{className:"flex items-center justify-between mb-2",children:(0,n.jsx)("span",{className:(0,p.cn)(s.statusBadge,s.statusSuccess),children:"200 OK"})}),(0,n.jsx)("pre",{className:(0,p.cn)(s.responseViewer,s.responseSuccess),children:f})]}),v&&(0,n.jsxs)("div",{className:s.responseSection,children:[(0,n.jsx)("div",{className:"flex items-center justify-between mb-2",children:(0,n.jsx)("span",{className:(0,p.cn)(s.statusBadge,s.statusError),children:"Error"})}),(0,n.jsx)("pre",{className:(0,p.cn)(s.responseViewer,s.responseError),children:v})]}),h&&(0,n.jsx)("div",{className:s.responseSection,children:(0,n.jsx)("span",{className:(0,p.cn)(s.statusBadge,s.responseLoading),children:"Loading..."})})]})]})]}):null}let y=[{id:"overview",label:"Overview"},{id:"method-index",label:"Method index"}],g={body:"Body",header:"Header",path:"Path",query:"Query"};function h(e){return y.some(t=>t.id===e)}function b(e){return e.split(/(`[^`]+`|\*\*[^*]+\*\*)/g).filter(Boolean).map((e,t)=>e.startsWith("`")&&e.endsWith("`")?(0,n.jsx)("code",{className:"rounded bg-block-background px-1.5 py-0.5 font-mono text-xs text-text-dark",children:e.slice(1,-1)},t):e.startsWith("**")&&e.endsWith("**")?(0,n.jsx)("strong",{className:"font-semibold text-text-dark",children:e.slice(2,-2)},t):(0,n.jsx)("span",{children:e},t))}function f(e){return e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(e=>e.trim())}function x(e){let{markdown:t,variant:i="overview"}=e,r=function(e){let t=e.split("\n"),i=[],n=0;for(;n<t.length;){let e=t[n].trim();if(!e){n++;continue}if(e.startsWith("```")){n++;let e=[];for(;n<t.length&&!t[n].trim().startsWith("```");)e.push(t[n]),n++;n<t.length&&n++,i.push({type:"code",text:e.join("\n")});continue}if(e.startsWith("|")){let e=[];for(;n<t.length&&t[n].trim().startsWith("|");)e.push(t[n]),n++;let r=e.map(f).filter(e=>!e.every(e=>/^-+$/.test(e.replace(/\s/g,""))));r.length>0&&i.push({type:"table",headers:r[0],rows:r.slice(1)});continue}if(e.startsWith("### ")){i.push({type:"heading",level:3,text:e.slice(4).trim()}),n++;continue}if(e.startsWith("## ")){i.push({type:"heading",level:2,text:e.slice(3).trim()}),n++;continue}if(e.startsWith("- ")){let e=[];for(;n<t.length&&t[n].trim().startsWith("- ");)e.push(t[n].trim().slice(2)),n++;i.push({type:"list",items:e});continue}if(e.startsWith("**")&&e.endsWith("**")){i.push({type:"strong",text:e.slice(2,-2)}),n++;continue}let r=[];for(;n<t.length;){let e=t[n].trim();if(!e||e.startsWith("```")||e.startsWith("|")||e.startsWith("- ")||e.startsWith("## ")||e.startsWith("### ")||e.startsWith("**")&&e.endsWith("**")&&r.length>0)break;r.push(t[n]),n++}r.length>0&&i.push({type:"paragraph",text:r.join(" ").trim()})}return i}(t),a="endpoint"===i?s.endpointDescriptionCode:s.codeBlock,o="endpoint"===i?s.endpointDescriptionHeading:(0,p.cn)(s.methodIndexTitle,"mt-8 mb-3"),d="endpoint"===i?s.endpointDescriptionStrong:s.mdStrongLine,l=s.mdParagraph;return(0,n.jsx)("div",{children:r.map((e,t)=>"code"===e.type?(0,n.jsx)("pre",{className:a,children:e.text},t):"table"===e.type?(0,n.jsx)("div",{className:s.mdTableWrap,children:(0,n.jsxs)("table",{className:s.mdTable,children:[(0,n.jsx)("thead",{className:s.mdTableHead,children:(0,n.jsx)("tr",{children:e.headers.map(e=>(0,n.jsx)("th",{className:s.mdTableHeadCell,children:b(e)},e))})}),(0,n.jsx)("tbody",{children:e.rows.map((e,t)=>(0,n.jsx)("tr",{children:e.map((e,t)=>(0,n.jsx)("td",{className:s.mdTableCell,children:b(e)},t))},t))})]})},t):"list"===e.type?(0,n.jsx)("ul",{className:s.mdList,children:e.items.map(e=>(0,n.jsx)("li",{children:b(e)},e))},t):"strong"===e.type?(0,n.jsx)("p",{className:d,children:e.text},t):"heading"===e.type?3===e.level?(0,n.jsx)("h3",{className:o,children:e.text},t):(0,n.jsx)("h2",{className:o,children:e.text},t):(0,n.jsx)("p",{className:l,children:b(e.text)},t))})}function v(e){return"GET"===e||"WS"===e?s.methodBadgeGet:"POST"===e?s.methodBadgePost:"DELETE"===e?"bg-[#E43C5A33] text-[#E43C5A]":s.methodBadgeDefault}function q(e){let{method:t,url:i,onTryClick:r}=e;return(0,n.jsxs)("div",{className:s.apiPathRow,children:[(0,n.jsx)("span",{className:(0,p.cn)(s.endpointMethodBadge,v(t)),children:t}),(0,n.jsx)("span",{className:s.apiPath,children:i}),r&&(0,n.jsx)("button",{className:s.tryItButton,onClick:r,children:"Try it"})]})}function w(e){let{title:t,fields:i,emptyText:r}=e;return i.length<=0?(0,n.jsxs)("div",{className:"mt-6",children:[(0,n.jsx)("h3",{className:s.methodIndexTitle,children:t}),(0,n.jsx)("p",{className:s.sectionSubtitle,children:r})]}):(0,n.jsxs)("div",{className:"mt-8",children:[(0,n.jsx)("h3",{className:s.methodIndexTitle,children:t}),(0,n.jsxs)("div",{className:s.paramTable,children:[(0,n.jsxs)("div",{className:s.paramTableHead,children:[(0,n.jsx)("span",{children:"Name"}),(0,n.jsx)("span",{children:"Type"}),(0,n.jsx)("span",{children:"In"}),(0,n.jsx)("span",{children:"Description"})]}),i.map(e=>(0,n.jsxs)("div",{className:s.paramRow,children:[(0,n.jsxs)("div",{className:s.paramNameCell,children:[(0,n.jsx)("span",{className:s.paramName,children:e.name}),e.required&&(0,n.jsx)("span",{className:s.paramRequired,children:"required"})]}),(0,n.jsx)("code",{className:s.paramType,children:e.type}),(0,n.jsx)("span",{className:s.paramLocation,children:g[e.location]}),(0,n.jsx)("p",{className:s.paramDescription,children:e.description})]},"".concat(e.location,"-").concat(e.name)))]})]})}function k(e){let{activeView:t,onSelectPage:i}=e;return(0,n.jsx)("nav",{children:y.map(e=>(0,n.jsx)("button",{type:"button",className:(0,p.cn)(s.navPageButton,t===e.id&&s.navPageButtonActive),onClick:()=>i(e.id),children:e.label},e.id))})}function I(e){let{groupedEndpoints:t,activeView:i,onSelectEndpoint:r}=e;return t.length<=0?(0,n.jsx)("div",{className:s.empty,children:"No endpoints match your search."}):(0,n.jsx)(n.Fragment,{children:t.map(e=>
1{let[t,a]=e;return(0,n.jsxs)("div",{className:s.navGroup,children:[(0,n.jsx)("div",{className:s.navGroupTitle,children:t}),a.map(e=>{var t;return(0,n.jsx)("button",{type:"button",className:(0,p.cn)(s.endpointButton,i===e.name&&s.endpointButtonActive),onClick:()=>r(e.name),children:(0,n.jsxs)("div",{className:s.endpointButtonRow,children:[(0,n.jsx)("span",{className:s.endpointButtonName,children:null!=(t=e.summary)?t:e.name}),(0,n.jsx)("span",{className:(0,p.cn)(s.endpointMethodBadge,v(e.method)),children:e.method})]})},e.name)})]},t)})})}function T(e){let{groupedEndpoints:t,onSelectEndpoint:i}=e;return(0,n.jsx)("div",{className:s.methodIndexGrid,children:t.map(e=>{let[t,r]=e;return(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:s.methodIndexTitle,children:t}),(0,n.jsx)("div",{className:s.methodIndexList,children:r.map(e=>{var t;return(0,n.jsxs)("button",{type:"button",className:(0,p.cn)(s.methodIndexItem,"flex w-full flex-col items-stretch gap-2 text-left"),onClick:()=>i(e.name),children:[(0,n.jsx)("span",{className:"min-w-0 truncate text-text-dark",children:null!=(t=e.summary)?t:e.name}),(0,n.jsx)(q,{method:e.method,url:e.url})]},e.name)})})]},t)})})}function S(){return(0,n.jsxs)("div",{className:s.pageContent,children:[(0,n.jsxs)("div",{className:s.eyebrow,children:["OpenAPI"," ",o.apiVersion]}),(0,n.jsx)("h1",{className:s.title,children:o.apiTitle}),o.overviewMarkdown&&(0,n.jsx)(x,{markdown:o.overviewMarkdown})]})}function V(e){let{groupedEndpoints:t,onSelectEndpoint:i}=e;return(0,n.jsxs)("div",{className:s.pageContent,children:[(0,n.jsx)("h1",{className:s.title,children:"Method index"}),(0,n.jsx)("p",{className:s.sectionSubtitle,children:"Select an operation to view request parameters, response fields, and English descriptions."}),(0,n.jsx)(T,{groupedEndpoints:t,onSelectEndpoint:i})]})}function P(e){var t,i;let{endpoint:r,onTryClick:a}=e;if(!r)return(0,n.jsx)("div",{className:s.empty,children:"No endpoint selected."});let d="WebSocket"===r.tag,l=null!=(t=r.descriptionMarkdown)?t:r.description,c=d&&o.servers[0]?function(e,t){var i;let n=t.startsWith("/")?t:"/".concat(t),r=e.match(/^https?:\/\/([^/]+)(\/.*)?$/);if(!r)return"wss://{host}".concat(n);let a=(null!=(i=r[2])?i:"").replace(/\/$/,"");return"wss://".concat(r[1]).concat(a).concat(n)}(o.servers[0],r.url):r.url,m=d?"WS":r.method;return(0,n.jsxs)("div",{className:s.pageContent,children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("span",{className:s.pill,children:r.tag}),d&&(0,n.jsx)("span",{className:s.pill,children:"101 Switching Protocols"}),r.permission&&(0,n.jsxs)("span",{className:s.pill,children:["permission:",r.permission]}),!r.security&&(0,n.jsx)("span",{className:s.pill,children:"public"})]}),(0,n.jsx)("h1",{className:(0,p.cn)(s.title,"mt-4"),children:null!=(i=r.summary)?i:r.name}),(0,n.jsx)(q,{method:m,url:c}),!d&&(0,n.jsx)("button",{className:(0,p.cn)(s.tryItButton,"mt-4"),onClick:()=>null==a?void 0:a(r),children:"Try it"}),l&&(0,n.jsx)("div",{className:s.endpointDescription,children:(0,n.jsx)(x,{markdown:l,variant:"endpoint"})}),r.requestFields.length>0&&(0,n.jsx)(w,{title:"Request parameters",fields:r.requestFields,emptyText:"This endpoint has no request parameters."}),r.responseFields.length>0&&(0,n.jsx)(w,{title:"Response parameters (data)",fields:r.responseFields,emptyText:"No response body fields documented for this endpoint."})]})}function j(e){let{query:t,activeView:i,groupedEndpoints:r,onQueryChange:a,onSelectPage:o,onSelectEndpoint:d,onNavigate:l}=e;return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("input",{className:s.sidebarSearch,placeholder:"Search APIs...",value:t,onChange:e=>a(e.target.value)}),(0,n.jsx)("div",{className:(0,p.cn)(s.sidebarTitle,"mt-5"),children:"API Reference"}),(0,n.jsx)(k,{activeView:i,onSelectPage:e=>{o(e),null==l||l()}}),(0,n.jsx)("div",{className:s.sidebarDivider}),(0,n.jsx)("div",{className:s.sidebarTitle,children:"Endpoints"}),(0,n.jsx)(I,{groupedEndpoints:r,activeView:i,onSelectEndpoint:e=>{d(e),null==l||l()}})]})}function N(e){let{open:t,activeLabel:i,query:a,activeView:o,groupedEndpoints:d,onOpen:l,onClose:c,onQueryChange:m,onSelectPage:u,onSelectEndpoint:y}=e;return(0,r.useEffect)(()=>
1{if(!t)return;let e=e=>{"Escape"===e.key&&c()};return document.addEventListener("keydown",e),document.body.style.overflow="hidden",()=>{document.removeEventListener("keydown",e),document.body.style.overflow=""}},[t,c]),(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)("div",{className:s.mobileNavBar,children:[(0,n.jsxs)("button",{type:"button",className:s.mobileMenuButton,onClick:l,"aria-label":"Open API navigation","aria-expanded":t,children:[(0,n.jsxs)("span",{className:"flex flex-col gap-1",children:[(0,n.jsx)("span",{className:"block h-0.5 w-4 rounded-full bg-text-dark"}),(0,n.jsx)("span",{className:"block h-0.5 w-4 rounded-full bg-text-dark"}),(0,n.jsx)("span",{className:"block h-0.5 w-4 rounded-full bg-text-dark"})]}),(0,n.jsx)("span",{children:"Menu"})]}),(0,n.jsx)("span",{className:s.mobileNavLabel,children:i})]}),t&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("button",{type:"button",className:s.mobileDrawerOverlay,"aria-label":"Close API navigation",onClick:c}),(0,n.jsxs)("aside",{className:(0,p.cn)(s.mobileDrawerPanel,s.mobileDrawerPanelOpen),children:[(0,n.jsxs)("div",{className:s.mobileDrawerHeader,children:[(0,n.jsx)("span",{className:s.mobileDrawerTitle,children:"API Navigation"}),(0,n.jsx)("button",{type:"button",className:s.mobileDrawerClose,"aria-label":"Close navigation",onClick:c,children:"\xd7"})]}),(0,n.jsx)("div",{className:s.mobileDrawerBody,children:(0,n.jsx)(j,{query:a,activeView:o,groupedEndpoints:d,onQueryChange:m,onSelectPage:u,onSelectEndpoint:y,onNavigate:c})})]})]})]})}function C(){var e;let[t,i]=(0,r.useState)(""),[a,d]=(0,r.useState)("overview"),[l,c]=(0,r.useState)(!1),[m,p]=(0,r.useState)(null),g=(0,r.useMemo)(()=>{let e=t.trim().toLowerCase();return o.endpoints.filter(t=>{var i,n,r,a,o,s,d,l,c,m;return!e||t.name.toLowerCase().includes(e)||t.url.toLowerCase().includes(e)||t.method.toLowerCase().includes(e)||t.tag.toLowerCase().includes(e)||null!=(s=null==(i=t.summary)?void 0:i.toLowerCase().includes(e))&&s||null!=(d=null==(n=t.description)?void 0:n.toLowerCase().includes(e))&&d||null!=(l=null==(r=t.descriptionMarkdown)?void 0:r.toLowerCase().includes(e))&&l||null!=(c=null==(a=t.requestSchema)?void 0:a.toLowerCase().includes(e))&&c||null!=(m=null==(o=t.responseSchema)?void 0:o.toLowerCase().includes(e))&&m})},[t]),b=(0,r.useMemo)(()=>{let e=new Map;for(let i of g){var t;e.set(i.tag,[...null!=(t=e.get(i.tag))?t:[],i])}return[...e.entries()]},[g]),f=h(a)?void 0:null!=(e=g.find(e=>e.name===a))?e:o.endpoints.find(e=>e.name===a),x=e=>{d(e)},v=e=>{d(e)},q=(0,r.useMemo)(()=>{var e,t,i,n;if(h(a))return null!=(t=null==(e=y.find(e=>e.id===a))?void 0:e.label)?t:a;let r=o.endpoints.find(e=>e.name===a);return null!=(n=null!=(i=null==r?void 0:r.summary)?i:null==r?void 0:r.name)?n:a},[a]);return(0,n.jsxs)("div",{className:s.page,children:[(0,n.jsx)("header",{className:s.header,children:(0,n.jsx)("div",{className:s.headerInner,children:(0,n.jsx)("a",{href:"/trade",target:"_blank",rel:"noopener noreferrer",className:s.headerBack,children:"â Back to Platform"})})}),(0,n.jsxs)("div",{className:s.shell,children:[(0,n.jsx)("aside",{className:s.sidebar,children:(0,n.jsx)("div",{className:s.sidebarInner,children:(0,n.jsx)("div",{className:s.sidebarContent,children:(0,n.jsx)(j,{query:t,activeView:a,groupedEndpoints:b,onQueryChange:i,onSelectPage:x,onSelectEndpoint:v})})})}),(0,n.jsx)("main",{className:s.main,children:(0,n.jsxs)("article",{className:s.article,children:[(0,n.jsx)(N,{open:l,activeLabel:q,query:t,activeView:a,groupedEndpoints:b,onOpen:()=>c(!0),onClose:()=>c(!1),onQueryChange:i,onSelectPage:x,onSelectEndpoint:v}),"overview"===a?(0,n.jsx)(S,{}):"method-index"===a?(0,n.jsx)(V,{groupedEndpoints:b,onSelectEndpoint:v}):(0,n.jsx)(P,{endpoint:f,onTryClick:p})]})})]}),m&&(0,n.jsx)(u,{open:!!m,onClose:()=>p(null),endpoint:m})]})}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.