{
  "openapi": "3.1.0",
  "info": {
    "title": "RealTime Exchange API",
    "version": "backend@522c974",
    "description": "Public REST API of RealTime Exchange (Arc Testnet). Generated from the backend's route table and reviewed annotations. Trading on Arc Mainnet coming soon.",
    "x-networks": {
      "testnet": "live",
      "mainnet": "chain-live"
    }
  },
  "servers": [
    {
      "url": "https://arc-testnet-api.realtime.exchange",
      "description": "Testnet"
    }
  ],
  "externalDocs": {
    "description": "Reference",
    "url": "https://docs.realtime.exchange/developers/rest-api"
  },
  "tags": [
    {
      "name": "Market data",
      "description": "Public, no authentication. Values are read from the indexer, the chain and the price oracle."
    },
    {
      "name": "Candles and charting",
      "description": "Candles are built from this venue's own fills. Only periods that traded are returned (no forward-fill)."
    },
    {
      "name": "Account",
      "description": "Requires your account identity. Authenticate with an API key (see Authentication)."
    },
    {
      "name": "Registration"
    },
    {
      "name": "Notifications",
      "description": "Requires authentication. Notifications are stored per chain."
    },
    {
      "name": "Service"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "operationId": "get_health",
        "summary": "Liveness. Always HTTP 200; reports whether Redis is degraded.",
        "description": "Response: `{status, degraded, degradedDependencies, dependencies: {redis}, timestamp, environment, version}`\n\nServed at the root, never under the API prefix.",
        "tags": [
          "Service"
        ],
        "responses": {
          "200": {
            "description": "{status, degraded, degradedDependencies, dependencies: {redis}, timestamp, environment, version}"
          }
        },
        "security": []
      }
    },
    "/ready": {
      "get": {
        "operationId": "get_ready",
        "summary": "Readiness. HTTP 200 only when Redis, the RPC and the indexer all answer; otherwise 503.",
        "description": "Response: `{status: \"ready\"|\"not_ready\", checks: {redis, rpc, indexer}, timestamp}`. Each check is `{ok, error?}` plus extra fields (`rpc.head`; `indexer.lag: \"unknown\"` when the indexer has no `/ready` and only reachability was checked). `error` is a fixed word such as `timeout`, `unreachable`, `no_head` or `http_503`.\n\nServed at the root, never under the API prefix, and not rate limited.\n\nThe indexer check uses the indexer’s own `/ready`, which compares its last synced block with the chain head.\n\nThe report is cached for 2 seconds by default and concurrent requests share one probe, so polling faster than that returns the same result.",
        "tags": [
          "Service"
        ],
        "responses": {
          "200": {
            "description": "{status: \"ready\"|\"not_ready\", checks: {redis, rpc, indexer}, timestamp}. Each check is {ok, error?} plus extra fields (rpc.head; indexer.lag: \"unknown\" when the indexer has no /ready and only reachability was checked). error is a fixed word such as timeout, unreachable, no_head or http_503."
          }
        },
        "security": []
      }
    },
    "/version": {
      "get": {
        "operationId": "get_version",
        "summary": "Backend version and runtime.",
        "description": "Response: `{version, node, environment}`\n\nServed at the root, never under the API prefix.",
        "tags": [
          "Service"
        ],
        "responses": {
          "200": {
            "description": "{version, node, environment}"
          }
        },
        "security": []
      }
    },
    "/time": {
      "get": {
        "operationId": "get_time",
        "summary": "Server time.",
        "description": "Response: `{time}` — nanoseconds, as a string.",
        "tags": [
          "Service"
        ],
        "responses": {
          "200": {
            "description": "{time} — nanoseconds, as a string."
          }
        },
        "security": []
      }
    },
    "/markets": {
      "get": {
        "operationId": "get_markets",
        "summary": "All listed markets (spot and perpetual) with their trading rules. Check is_active.",
        "description": "Response: A JSON array. Each market includes `instrument_id`, `instrument_name`, `instrument_type`, `underlying_asset`, `quote_asset`, `price_step` (tick size), `amount_step`, `min_order_value`, `max_order_value`, `max_notional_value`, `max_leverage` (perpetuals, omitted when unknown), `mark_price` and `index_price` (null when unavailable), `funding_rate`, `open_interest`, `volume_24h`, `maker_fee` / `taker_fee` (perpetuals only; null when unknown) and `base_decimals` / `quote_decimals` (18 for perpetuals).\n\nCached for 30 seconds.\n\n`volume_24h` is a rolling 24 hours: the hourly candles from the start of the hour 23 hours ago through the current, partial hour.\n\nIf the indexer is unavailable, spot markets can be missing from the list for a few seconds.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "SPOT or PERPETUAL. Case-sensitive; any other value returns an empty list.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "Underlying asset, case-insensitive.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A JSON array. Each market includes instrument_id, instrument_name, instrument_type, underlying_asset, quote_asset, price_step (tick size), amount_step, min_order_value, max_order_value, max_notional_value, max_leverage (perpetuals, omitted when unknown), mark_price and index_price (null when unavailable), funding_rate, open_interest, volume_24h, maker_fee / taker_fee (perpetuals only; null when unknown) and base_decimals / quote_decimals (18 for perpetuals)."
          }
        },
        "security": []
      }
    },
    "/markets/{instrument_id}": {
      "get": {
        "operationId": "get_markets_instrument_id",
        "summary": "One market. Same object as an item of GET /markets.",
        "description": "Response: A market object, or 404 `Instrument not found`.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_id",
            "in": "path",
            "required": true,
            "description": "Instrument name (e.g. BTC-PERP) or instrument id. Exact, case-sensitive match.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A market object, or 404 Instrument not found."
          }
        },
        "security": []
      }
    },
    "/instrument/{instrument_name}": {
      "get": {
        "operationId": "get_instrument_instrument_name",
        "summary": "Alias of GET /markets/{instrument_id}.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "path",
            "required": true,
            "description": "Instrument name or id (exact match).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/markets/{instrument_id}/orderbook": {
      "get": {
        "operationId": "get_markets_instrument_id_orderbook",
        "summary": "Alias of GET /orderbook/{instrument_name}.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_id",
            "in": "path",
            "required": true,
            "description": "Instrument name or id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/orderbook/{instrument_name}": {
      "get": {
        "operationId": "get_orderbook_instrument_name",
        "summary": "Aggregated order book (open and partially filled orders).",
        "description": "Response: `{bids: [{price, amount, orders}], asks: [...], last_updated_timestamp, checksum}`\n\n`price` and `amount` are raw on-chain integers as strings. Divide `price` by 10^`quote_decimals` and `amount` by 10^`base_decimals` from `GET /markets` to get human values.\n\nAt most 500 orders per side are read before aggregation.\n\n`checksum` is the server time in hex, not a checksum of the book. `last_updated_timestamp` is the response time in milliseconds.\n\nUnknown instrument → 404.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "path",
            "required": true,
            "description": "Instrument name, e.g. BTC-PERP, or its 0x id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{bids: [{price, amount, orders}], asks: [...], last_updated_timestamp, checksum}"
          }
        },
        "security": []
      }
    },
    "/orderbook": {
      "get": {
        "operationId": "get_orderbook",
        "summary": "Same as GET /orderbook/{instrument_name}, with the instrument as a query parameter.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "query",
            "required": true,
            "description": "Instrument name or id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/markets/{instrument_id}/trades": {
      "get": {
        "operationId": "get_markets_instrument_id_trades",
        "summary": "Recent trades for a market.",
        "description": "Response: A JSON array, newest first, of `{trade_id, tx_hash, created_timestamp, instrument_name, is_buyer_taker, price, amount, side, trade_type, fees}` with decimal prices. `created_timestamp` is Unix **seconds**; `fees` is always `\"0\"`.\n\nAn unknown instrument returns an empty array.\n\n`offset` is accepted but ignored.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_id",
            "in": "path",
            "required": true,
            "description": "Instrument name or 0x id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default 100. At most 1000 are returned.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A JSON array, newest first, of {trade_id, tx_hash, created_timestamp, instrument_name, is_buyer_taker, price, amount, side, trade_type, fees} with decimal prices. created_timestamp is Unix **seconds**; fees is always \"0\"."
          }
        },
        "security": []
      }
    },
    "/instrument/{instrument_name}/trade-history": {
      "get": {
        "operationId": "get_instrument_instrument_name_trade_history",
        "summary": "Recent trades for a market, wrapped with a count.",
        "description": "Response: `{count, trade_history: [{trade_id, tx_hash, instrument_id, instrument_name, instrument_type, side, price, amount, created_timestamp}]}` (timestamps in nanoseconds).",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "path",
            "required": true,
            "description": "Instrument name.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default 100. At most 1000 are returned.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{count, trade_history: [{trade_id, tx_hash, instrument_id, instrument_name, instrument_type, side, price, amount, created_timestamp}]} (timestamps in nanoseconds)."
          }
        },
        "security": []
      }
    },
    "/statistics/{asset}/{instrument_type}": {
      "get": {
        "operationId": "get_statistics_asset_instrument_type",
        "summary": "24-hour statistics for a market.",
        "description": "Response: `{asset, daily_volume, daily_buy_volume, daily_trades, open_interest: {total, long, short}, index_price, mark_price, mark_price_24h_ago, mark_daily_change, mark_daily_change_pct, funding_rate, funding_daily_avg, next_funding_rate_timestamp, funding_interval_seconds, ...}`\n\nAn unknown market returns 200 with null prices, not 404.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "asset",
            "in": "path",
            "required": true,
            "description": "e.g. BTC.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument_type",
            "in": "path",
            "required": true,
            "description": "PERPETUAL (→ BTC-PERP) or SPOT (→ BTC-USDC).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{asset, daily_volume, daily_buy_volume, daily_trades, open_interest: {total, long, short}, index_price, mark_price, mark_price_24h_ago, mark_daily_change, mark_daily_change_pct, funding_rate, funding_daily_avg, next_funding_rate_timestamp, funding_interval_seconds, ...}"
          }
        },
        "security": []
      }
    },
    "/statistics": {
      "get": {
        "operationId": "get_statistics",
        "summary": "Same as above with query parameters.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "query",
            "required": false,
            "description": "e.g. BTC-PERP. Or pass asset + instrument_type.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/funding/{instrument_name}": {
      "get": {
        "operationId": "get_funding_instrument_name",
        "summary": "Current funding rate of a perpetual market (per hour).",
        "description": "Response: `{funding_rate, estimated_rate, protocol_funding_rate, next_funding_time, funding_interval_seconds, funding_accrual, funding_update_interval_seconds}`\n\nFunding accrues continuously; the rate is quoted per hour (`funding_interval_seconds: 3600`).\n\n`next_funding_time` is Unix milliseconds.\n\nThe `-PERP` suffix is case-sensitive: a non-perpetual or lower-case name returns 200 with `funding_rate: \"0\"`.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "path",
            "required": true,
            "description": "e.g. BTC-PERP.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{funding_rate, estimated_rate, protocol_funding_rate, next_funding_time, funding_interval_seconds, funding_accrual, funding_update_interval_seconds}"
          }
        },
        "security": []
      }
    },
    "/funding": {
      "get": {
        "operationId": "get_funding",
        "summary": "Same as above with instrument_name as a query parameter.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "query",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/funding-history/{instrument_name}": {
      "get": {
        "operationId": "get_funding_history_instrument_name",
        "summary": "Recent hourly funding rates of a perpetual market.",
        "description": "Response: `{funding_history: [[instrument_name, time_ns, rate, mark_price], ...]}`, oldest first.\n\nOne row per settled funding hour, stored in the backend database, so history survives restarts.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "path",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default 50. Values outside 1–500 are clamped.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": false,
            "description": "Earliest settlement time, in seconds, milliseconds or nanoseconds (the unit is inferred from the size).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "Latest settlement time, in the same units as start_time.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{funding_history: [[instrument_name, time_ns, rate, mark_price], ...]}, oldest first."
          }
        },
        "security": []
      }
    },
    "/funding-history": {
      "get": {
        "operationId": "get_funding_history",
        "summary": "Same as above with instrument_name as a query parameter.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "query",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/index/{asset}": {
      "get": {
        "operationId": "get_index_asset",
        "summary": "Index (oracle) price of an asset.",
        "description": "Response: An array `[{asset, price, timestamp}]`.\n\nAn unknown asset returns price `\"0\"`, not 404.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "asset",
            "in": "path",
            "required": true,
            "description": "Case-insensitive, e.g. BTC.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An array [{asset, price, timestamp}]."
          }
        },
        "security": []
      }
    },
    "/index": {
      "get": {
        "operationId": "get_index",
        "summary": "Index prices for every token the indexer knows (see GET /assets), or one asset via ?asset=. For a perpetual underlying that is not a token, use GET /index/{asset}.",
        "tags": [
          "Market data"
        ],
        "parameters": [
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/assets": {
      "get": {
        "operationId": "get_assets",
        "summary": "Tokens known to the indexer.",
        "description": "Response: An array of `{asset_id, asset_name, symbol, address, decimals}`.",
        "tags": [
          "Market data"
        ],
        "responses": {
          "200": {
            "description": "An array of {asset_id, asset_name, symbol, address, decimals}."
          }
        },
        "security": []
      }
    },
    "/markets-summary": {
      "get": {
        "operationId": "get_markets_summary",
        "summary": "Per-asset summary of spot and perpetual prices and volumes.",
        "description": "Response: `{summaries: [{asset, index_price, spot_info?, perpetual_info?}]}`",
        "tags": [
          "Market data"
        ],
        "responses": {
          "200": {
            "description": "{summaries: [{asset, index_price, spot_info?, perpetual_info?}]}"
          }
        },
        "security": []
      }
    },
    "/candles": {
      "get": {
        "operationId": "get_candles",
        "summary": "OHLCV candles built from this venue's fills.",
        "description": "Response: An array, oldest first, of `{time, close_time, open, high, low, close, volume, quote_volume, trades, average, taker_buy_volume}`. Money values are exact decimal strings.\n\nAt most 5000 bars per request.\n\nOnly periods with trades are returned (no forward-fill).\n\nTo get the most recent bars, send `countback` (or a `from` close to `to`). Without either, you get up to 5000 bars from the start of the market's history.\n\nInstrument names are case-insensitive. A missing or unknown instrument returns 404.\n\nUnsupported resolution → 400; unknown instrument → 404.",
        "tags": [
          "Candles and charting"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "query",
            "required": true,
            "description": "e.g. BTC-PERP (or symbol).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "resolution",
            "in": "query",
            "required": true,
            "description": "One of the supported resolutions (below). 1M is one MONTH; one minute is 1.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Unix seconds.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Unix seconds, default now.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "countback",
            "in": "query",
            "required": false,
            "description": "Number of bars; overrides from.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An array, oldest first, of {time, close_time, open, high, low, close, volume, quote_volume, trades, average, taker_buy_volume}. Money values are exact decimal strings."
          }
        },
        "security": []
      }
    },
    "/last-traded-tradingview/history": {
      "get": {
        "operationId": "get_last_traded_tradingview_history",
        "summary": "The same candles in TradingView UDF format.",
        "description": "Response: `{s: \"ok\", t, o, h, l, c, v}`, or `{s: \"no_data\"}` (also for an unknown symbol; may include `nextTime`). Other errors are returned as HTTP 200 `{s: \"error\", errmsg}` (UDF convention); an unsupported resolution is a 400.",
        "tags": [
          "Candles and charting"
        ],
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "description": "Instrument name. instrument_name is accepted as an alias.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "resolution",
            "in": "query",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "countback",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{s: \"ok\", t, o, h, l, c, v}, or {s: \"no_data\"} (also for an unknown symbol; may include nextTime). Other errors are returned as HTTP 200 {s: \"error\", errmsg} (UDF convention); an unsupported resolution is a 400."
          }
        },
        "security": []
      }
    },
    "/last-traded-tradingview/config": {
      "get": {
        "operationId": "get_last_traded_tradingview_config",
        "summary": "TradingView UDF datafeed configuration (supported resolutions).",
        "tags": [
          "Candles and charting"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": []
      }
    },
    "/account": {
      "get": {
        "operationId": "get_account",
        "summary": "Account overview — balances, equity, margin, positions, fee structures.",
        "description": "Response: An account object including `account`, `equity`, `available_balance`, `balance`, `collaterals`, `positions`, `fee_structures`, `initial_margin`, `maintenance_margin`, `in_liquidation`, `liquidatable`, `leverages`, `realized_pnl`, `unrealized_pnl`.\n\nCached for 2 seconds.\n\n`in_liquidation` is always `false`. Use `liquidatable` (`true`, `false` or `null` when unknown) for the liquidation verdict.\n\n`equity`, the margin fields and `unrealized_pnl` can be `null` when a value could not be read.",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "An account object including account, equity, available_balance, balance, collaterals, positions, fee_structures, initial_margin, maintenance_margin, in_liquidation, liquidatable, leverages, realized_pnl, unrealized_pnl."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/positions": {
      "get": {
        "operationId": "get_positions",
        "summary": "Open positions, cursor-paginated.",
        "description": "Response: `{positions: [...], pagination: {next_cursor, prev_cursor, has_next, has_prev, limit, total_count, total_pages}}`",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "SPOT or PERPETUAL (case-insensitive).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–1000, default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "From pagination.next_cursor / prev_cursor.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "next (default) or prev.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{positions: [...], pagination: {next_cursor, prev_cursor, has_next, has_prev, limit, total_count, total_pages}}"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/open-orders": {
      "get": {
        "operationId": "get_open_orders",
        "summary": "Open and partially filled orders, cursor-paginated.",
        "description": "Response: `{orders: [...], pagination}`",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument_name",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "asc or desc.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–1000, default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{orders: [...], pagination}"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/orders": {
      "get": {
        "operationId": "get_orders",
        "summary": "Your open and partially filled orders, unpaginated (at most the 200 most recent).",
        "description": "Response: A JSON array of orders.\n\nUse `GET /open-orders` for paging and filters.",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "SPOT or PERPETUAL.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A JSON array of orders."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/orders/{order_id}": {
      "get": {
        "operationId": "get_orders_order_id",
        "summary": "One of your open orders.",
        "description": "Searches only your open and partially filled orders (the 200 most recent); anything else is 404 `Order not found`.",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/trade-history": {
      "get": {
        "operationId": "get_trade_history",
        "summary": "Your fills, cursor-paginated.",
        "description": "Response: `{trade_history: [...], pagination}`\n\nWith `trade_types=funding` the endpoint returns funding settlements instead, paginated with `offset` and with a `count` field. That view reads only your 500 most recent position events and ignores the time, sort and cursor filters.",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument_name",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": false,
            "description": "Seconds, milliseconds or nanoseconds.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–1000, default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{trade_history: [...], pagination}"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/order-history": {
      "get": {
        "operationId": "get_order_history",
        "summary": "Filled, partially filled and cancelled orders, cursor-paginated.",
        "description": "Response: `{order_history: [...], pagination}`",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "instrument_type",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instrument_name",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{order_history: [...], pagination}"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/position-history": {
      "get": {
        "operationId": "get_position_history",
        "summary": "Closed perpetual positions (one row per position cycle), cursor-paginated.",
        "description": "Response: `{position_history: [...], pagination}`",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "instrument_name",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{position_history: [...], pagination}"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/transaction-history": {
      "get": {
        "operationId": "get_transaction_history",
        "summary": "Deposits, withdrawals and transfers.",
        "description": "Response: `{transaction_history: [...], count}`\n\n`count` is a string: the number of rows in the fetched window (`limit + offset`), not the total available.",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "tx_type",
            "in": "query",
            "required": false,
            "description": "deposit, withdraw, send or receive.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Default 0.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "tx_status",
            "in": "query",
            "required": false,
            "description": "Only finalized returns rows.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "ASC; anything else is newest first.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{transaction_history: [...], count}"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/account/accumulated-fundings": {
      "get": {
        "operationId": "get_account_accumulated_fundings",
        "summary": "Funding accumulated on your open perpetual positions.",
        "description": "Response: `{account, accumulated_fundings: [{instrument_id, accumulated_funding, pending_funding_fee, total_funding_fee}]}` — positive `accumulated_funding` is in your favour.",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "{account, accumulated_fundings: [{instrument_id, accumulated_funding, pending_funding_fee, total_funding_fee}]} — positive accumulated_funding is in your favour."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/balance-history": {
      "get": {
        "operationId": "get_balance_history",
        "summary": "Your recorded account equity over time (the portfolio chart).",
        "description": "Response: `{history: [[unix_seconds, equity], ...]}`, oldest first.\n\n`start_time` after `end_time` returns 400.\n\nRequires a real API key — the account header alone is rejected.\n\nHistory starts when the server began recording snapshots for your account. Snapshots are taken only while the account has a live API key or an open private WebSocket.\n\nPoints older than 8 days are thinned to hourly; points older than 400 days are deleted (server defaults).",
        "tags": [
          "Account"
        ],
        "parameters": [
          {
            "name": "start_time",
            "in": "query",
            "required": true,
            "description": "Unix time (s, ms or ns).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "end_time",
            "in": "query",
            "required": false,
            "description": "Default now.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "resolution",
            "in": "query",
            "required": false,
            "description": "Seconds per point, default 3600. Clamped to 60–604800, then coarsened so the response has at most 2000 points (operator-configurable).",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{history: [[unix_seconds, equity], ...]}, oldest first."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/register": {
      "post": {
        "operationId": "post_register",
        "summary": "Register a signing key for your wallet and receive an API key + secret.",
        "description": "Response: 201 `{api_key, api_secret, account, signing_key}`\n\nBoth signatures are required. A missing or invalid `account_signature` or `signing_key_signature` is rejected with 401.\n\nKeys expire. The TTL is derived from `expiry` and capped at 30 days by default.\n\nAn account keeps at most 5 live API keys by default. A new registration adds a key; when that goes over the cap, the oldest key is revoked.\n\nTo revoke a key yourself, call `DELETE /api-key`.",
        "tags": [
          "Registration"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account": {
                    "type": "string",
                    "description": "Your wallet address."
                  },
                  "signing_key": {
                    "type": "string",
                    "description": "Address of the signing key you generated."
                  },
                  "expiry": {
                    "type": "integer",
                    "description": "Unix seconds, signed in Register. The key lives until expiry, capped by the server; a past value gives a 60-second key."
                  },
                  "account_signature": {
                    "type": "string",
                    "description": "EIP-712 Register signature by your wallet."
                  },
                  "signing_key_signature": {
                    "type": "string",
                    "description": "EIP-712 SignKey signature by the signing key."
                  },
                  "referral_code": {
                    "type": "string",
                    "description": "Optional."
                  },
                  "invite_code": {
                    "type": "string",
                    "description": "Only when the deployment is invite-only."
                  },
                  "no_api_key": {
                    "type": "boolean",
                    "description": "Update the signing key without issuing a new API key (when one exists). The response then omits api_key / api_secret."
                  }
                },
                "required": [
                  "account",
                  "signing_key",
                  "expiry",
                  "account_signature",
                  "signing_key_signature"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "201 {api_key, api_secret, account, signing_key}"
          }
        },
        "security": []
      }
    },
    "/api-key": {
      "delete": {
        "operationId": "delete_api_key",
        "summary": "Revoke an API key of your account, or all of them.",
        "description": "Response: `{success: true}`; with `all: true`, `{success: true, revoked}`. 404 when the key is not found.\n\nWebSocket connections authenticated with a revoked key lose their identity at once.",
        "tags": [
          "Registration"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "api_key": {
                    "type": "string",
                    "description": "The key to revoke. Defaults to the key this request authenticates with. Only keys of your own account can be revoked."
                  },
                  "all": {
                    "type": "boolean",
                    "description": "true revokes every key of your account."
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{success: true}; with all: true, {success: true, revoked}. 404 when the key is not found."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/notifications": {
      "get": {
        "operationId": "get_notifications",
        "summary": "Your notifications, newest first.",
        "description": "Response: A JSON array of `{id, account, chain_id, notification_type, created_timestamp, is_read, metadata}`. `created_timestamp` is Unix nanoseconds, as a string.",
        "tags": [
          "Notifications"
        ],
        "parameters": [
          {
            "name": "unread",
            "in": "query",
            "required": false,
            "description": "true to return unread only.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default and maximum 100.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A JSON array of {id, account, chain_id, notification_type, created_timestamp, is_read, metadata}. created_timestamp is Unix nanoseconds, as a string."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/mark-as-read": {
      "post": {
        "operationId": "post_mark_as_read",
        "summary": "Mark all notifications as read. Returns the refreshed list.",
        "tags": [
          "Notifications"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/notifications/clear": {
      "post": {
        "operationId": "post_notifications_clear",
        "summary": "Clear the list (older notifications are hidden, not deleted).",
        "tags": [
          "Notifications"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/notifications/{id}/read": {
      "post": {
        "operationId": "post_notifications_id_read",
        "summary": "Mark one notification as read.",
        "description": "Response: The updated notification, or `{success: true}` when it is not in the current list.",
        "tags": [
          "Notifications"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The updated notification, or {success: true} when it is not in the current list."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/notifications/{id}": {
      "delete": {
        "operationId": "delete_notifications_id",
        "summary": "Delete one notification. Always returns {success: true}.",
        "tags": [
          "Notifications"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    },
    "/notification-preferences": {
      "get": {
        "operationId": "get_notification_preferences",
        "summary": "Your notification preferences.",
        "description": "Response: `{muted_types, sound_enabled, browser_push_enabled, updated_at}` (a legacy `cleared_at` field may also appear; it is not updated by `POST /notifications/clear`).",
        "tags": [
          "Notifications"
        ],
        "responses": {
          "200": {
            "description": "{muted_types, sound_enabled, browser_push_enabled, updated_at} (a legacy cleared_at field may also appear; it is not updated by POST /notifications/clear)."
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      },
      "put": {
        "operationId": "put_notification_preferences",
        "summary": "Update notification preferences. Values of the wrong type are ignored.",
        "tags": [
          "Notifications"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "muted_types": {
                    "type": "string",
                    "description": "Notification types to mute, e.g. fill, deposit_finalized, withdrawal_finalized, send_initiated, send_finalized, receive, referral, tpsl_executed, tpsl_rejected. Unknown values are dropped silently. Liquidation notifications cannot be muted."
                  },
                  "sound_enabled": {
                    "type": "boolean",
                    "description": ""
                  },
                  "browser_push_enabled": {
                    "type": "boolean",
                    "description": ""
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success"
          }
        },
        "security": [
          {
            "ApiKey": [],
            "ApiSecret": []
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "API-KEY"
      },
      "ApiSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "API-SECRET"
      }
    }
  }
}
