{
  "openapi": "3.0.3",
  "info": {
    "title": "Starbase REST API",
    "version": "2.0",
    "description": "Portfolio-scoped REST API for the Starbase direct-access trading platform."
  },
  "servers": [
    {
      "url": "http://195.138.37.5:4410",
      "description": "Production — Gateway A (rest-order)"
    },
    {
      "url": "http://195.138.37.6:4410",
      "description": "Production — Gateway B (rest-order)"
    },
    {
      "url": "http://195.138.37.137:4410",
      "description": "Test — Gateway A (rest-order)"
    },
    {
      "url": "http://195.138.37.138:4410",
      "description": "Test — Gateway B (rest-order)"
    }
  ],
  "tags": [
    {
      "name": "Portfolio Management",
      "description": "Endpoints that operate on the authenticated portfolio."
    },
    {
      "name": "Trading",
      "description": "Authenticated trading endpoints scoped to the caller's portfolio."
    },
    {
      "name": "Market Data",
      "description": "Unauthenticated Starbase reference and market data endpoints. No API credentials are required, but the Starbase REST gateway is reachable only through private Starbase connectivity."
    }
  ],
  "paths": {
    "/api/v2/public/get_instruments": {
      "get": {
        "operationId": "get_instruments",
        "summary": "List Instruments",
        "description": "Returns the list of tradeable instruments, including `index_id` and `product_group`, optionally filtered by base currency, instrument kind, and expiration status.\n\nThis endpoint requires no authentication, but it is served by the Starbase REST gateway and is reachable only through hosted colocation, a cross-connect, or AWS Private Link. The standard internet-accessible JSON-RPC `public/get_instruments` method also documents `index_id` and `product_group`; backend rollout of those fields may temporarily differ between the two endpoints.\n\nFilter semantics:\n- `currency` filters by the **base** currency of the instrument's currency pair (case-insensitive match).\n- `kind` filters by instrument type (case-insensitive match against the `kind` value enum).\n- `expired = true` returns only instruments whose `expiration_timestamp` is in the past; `expired = false` returns only non-expired instruments. Omit the parameter to get both.",
        "tags": ["Market Data"],
        "security": [],
        "parameters": [
          {
            "name": "currency",
            "in": "query",
            "required": false,
            "description": "Filter by the base currency of the instrument's currency pair (e.g. `BTC`, `ETH`, `AVAX`). Case-insensitive.",
            "schema": {
              "type": "string"
            },
            "example": "BTC"
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "Filter by instrument kind. Case-insensitive.",
            "schema": {
              "type": "string",
              "enum": [
                "perp_future",
                "option",
                "spot",
                "future_combo",
                "option_combo",
                "dated_future"
              ]
            },
            "example": "perp_future"
          },
          {
            "name": "expired",
            "in": "query",
            "required": false,
            "description": "When `true`, return only expired instruments. When `false`, return only currently-active (non-expired) instruments. Omit to return both.",
            "schema": {
              "type": "boolean"
            },
            "example": false
          }
        ],
        "responses": {
          "200": {
            "description": "List of instruments matching the supplied filters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetInstrumentsResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": [
                    {
                      "instrument_id": 124942,
                      "instrument_name": "ETH-PERPETUAL",
                      "kind": "perp_future",
                      "product_group": "ETH",
                      "base_currency": "ETH",
                      "quote_currency": "USDC",
                      "settlement_currency": "USDC",
                      "tick_size": 0.01,
                      "qty_tick_size": 1,
                      "is_active": true,
                      "creation_timestamp": 1747500000000
                    },
                    {
                      "instrument_id": 200001,
                      "instrument_name": "BTC-30MAY26-70000-C",
                      "kind": "option",
                      "product_group": "BTC",
                      "base_currency": "BTC",
                      "quote_currency": "USDC",
                      "settlement_currency": "USDC",
                      "tick_size": 0.5,
                      "qty_tick_size": 0.1,
                      "strike": 70000,
                      "option_type": "call",
                      "is_active": true,
                      "expiration_timestamp": 1779148800000,
                      "creation_timestamp": 1748400000000
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Internal server error while building the instrument list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/private/get_open_orders": {
      "get": {
        "operationId": "get_open_orders",
        "summary": "Get Open Orders",
        "description": "Returns all currently-open orders belonging to the authenticated portfolio. Orders are returned regardless of instrument or order type; filtering by instrument kind and order type is not currently supported.\n\nEach order includes `post_only`, `reject_post_only`, and `reduce_only` flags. `post_only` and `reject_post_only` correspond to the SBE `postOnly` and `postOnlyReject` bits and are mutually exclusive. `reduce_only` reflects per-order reduce-only from JSON-RPC or FIX (it cannot be set per order in SBE).\n\nThe portfolio is resolved from the authenticated session — there is no parameter to query another portfolio's orders. MMP-flagged orders are visible via this endpoint. Orders placed via Mass Quote (MassQuoteRequest) are not currently returned.\n\nThis endpoint is rate-limited per portfolio. Exceeding the limit returns HTTP 429.",
        "tags": ["Trading"],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of open orders for the authenticated portfolio. May be empty.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetOpenOrdersResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": [
                    {
                      "order_id": "1cc1c718-49e0-4ea5-8902-f3f22968c350",
                      "instrument_name": "TREE-USD",
                      "side": "sell",
                      "price": 0.0717,
                      "amount": 83698,
                      "filled_amount": 0,
                      "average_price": 0,
                      "order_state": "open",
                      "order_type": "limit",
                      "post_only": true,
                      "reject_post_only": false,
                      "reduce_only": false,
                      "creation_timestamp": 1778270370643,
                      "last_update_timestamp": 1778270370643
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `Authorization` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "429": {
            "description": "Per-portfolio rate limit for this endpoint exceeded. Configured via `portfolio-rate-limit.get_open_orders`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error while reading the active-order set.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/private/cancel_all": {
      "get": {
        "operationId": "cancel_all",
        "summary": "Mass Cancel",
        "description": "Cancels all open orders and quotes belonging to the authenticated portfolio. No filter parameters are accepted — the cancel applies to every instrument and every side.",
        "tags": ["Portfolio Management"],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "All open orders and quotes cancelled successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelAllResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": 42
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/private/lock_portfolio": {
      "get": {
        "operationId": "lock_portfolio",
        "summary": "Lock Portfolio",
        "description": "Locks the authenticated portfolio. All currently open `DIRECT_ACCESS` orders and quotes for this portfolio are cancelled immediately. New `DIRECT_ACCESS` orders and quotes are rejected until the portfolio is unlocked.\n\nREST-submitted orders are not affected by the lock state.",
        "tags": ["Portfolio Management"],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Portfolio locked successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OkResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": "ok"
                }
              }
            }
          }
        }
      }
    },
    "/api/v2/private/unlock_portfolio": {
      "get": {
        "operationId": "unlock_portfolio",
        "summary": "Unlock Portfolio",
        "description": "Unlocks the authenticated portfolio, resuming normal acceptance of `DIRECT_ACCESS` orders and quotes.\n\nUnlocking the portfolio does **not** restore any previously cancelled orders.",
        "tags": ["Portfolio Management"],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Portfolio unlocked successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OkResponse"
                },
                "example": {
                  "jsonrpc": "2.0",
                  "id": 1,
                  "result": "ok"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "OkResponse": {
        "type": "object",
        "required": ["jsonrpc", "result"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"],
            "description": "The JSON-RPC version (2.0)"
          },
          "id": {
            "type": "integer",
            "description": "The id that was sent in the request"
          },
          "result": {
            "type": "string",
            "enum": ["ok"],
            "description": "Result of method execution. `ok` in case of success"
          }
        }
      },
      "CancelAllResponse": {
        "type": "object",
        "required": ["jsonrpc", "result"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"],
            "description": "The JSON-RPC version (2.0)"
          },
          "id": {
            "type": "integer",
            "description": "The id that was sent in the request"
          },
          "result": {
            "type": "number",
            "example": 7,
            "description": "Total number of successfully cancelled orders"
          }
        }
      },
      "GetInstrumentsResponse": {
        "type": "object",
        "required": ["jsonrpc", "result"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"],
            "description": "The JSON-RPC version (2.0)"
          },
          "id": {
            "type": "integer",
            "description": "The id that was sent in the request"
          },
          "result": {
            "type": "array",
            "description": "Array of instruments matching the supplied filters. May be empty.",
            "items": {
              "$ref": "#/components/schemas/Instrument"
            }
          }
        }
      },
      "GetOpenOrdersResponse": {
        "type": "object",
        "required": ["jsonrpc", "result"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"],
            "description": "The JSON-RPC version (2.0)"
          },
          "id": {
            "type": "integer",
            "description": "The id that was sent in the request"
          },
          "result": {
            "type": "array",
            "description": "Array of open orders for the authenticated portfolio. May be empty.",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          }
        }
      },
      "Instrument": {
        "type": "object",
        "description": "A tradeable instrument's reference data.",
        "required": [
          "instrument_id",
          "instrument_name",
          "kind",
          "is_active"
        ],
        "properties": {
          "instrument_id": {
            "type": "integer",
            "format": "int64",
            "description": "Stable numeric identifier for the instrument.",
            "example": 124942
          },
          "instrument_name": {
            "type": "string",
            "description": "Human-readable instrument symbol (e.g. `ETH-PERPETUAL`, `BTC-30MAY26-70000-C`).",
            "example": "ETH-PERPETUAL"
          },
          "kind": {
            "type": "string",
            "enum": [
              "perp_future",
              "option",
              "spot",
              "future_combo",
              "option_combo",
              "dated_future"
            ],
            "description": "Instrument category."
          },
          "index_id": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Numeric identifier for the index associated with the instrument."
          },
          "product_group": {
            "type": "string",
            "nullable": true,
            "description": "Starbase routing group resolved from the base symbol of the instrument's currency pair (for example `BTC`, `ETH`, `TIER_2`, or `TIER_3`).",
            "example": "ETH"
          },
          "base_currency": {
            "type": "string",
            "nullable": true,
            "description": "Base currency of the instrument's currency pair.",
            "example": "ETH"
          },
          "quote_currency": {
            "type": "string",
            "nullable": true,
            "description": "Quote currency of the instrument's currency pair.",
            "example": "USDC"
          },
          "settlement_currency": {
            "type": "string",
            "nullable": true,
            "description": "Settlement currency for the instrument. Currently equal to `quote_currency`.",
            "example": "USDC"
          },
          "tick_size": {
            "type": "number",
            "description": "Minimum price increment for the instrument.",
            "example": 0.01
          },
          "qty_tick_size": {
            "type": "number",
            "description": "Minimum quantity increment (step size) for order amounts on this instrument, expressed in the instrument's amount units. This is the same value the SBE `InstrumentDefinition` (10) message carries as `minOrderQuantity × 10^quantityExponent` — for example `qty_tick_size = 0.1` corresponds to `minOrderQuantity = 1` with `quantityExponent = -1`.",
            "example": 0.1
          },
          "strike": {
            "type": "number",
            "nullable": true,
            "description": "Strike price (options only). `null` for non-option instruments.",
            "example": 70000
          },
          "option_type": {
            "type": "string",
            "enum": ["call", "put"],
            "nullable": true,
            "description": "Option type (options only). `null` for non-option instruments."
          },
          "is_active": {
            "type": "boolean",
            "description": "Whether the instrument is currently enabled for trading."
          },
          "expiration_timestamp": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Instrument expiration time in milliseconds since the Unix epoch. `null` for perpetuals and other non-expiring instruments.",
            "example": 1779148800000
          },
          "creation_timestamp": {
            "type": "integer",
            "format": "int64",
            "nullable": true,
            "description": "Instrument creation/listing time in milliseconds since the Unix epoch.",
            "example": 1747500000000
          },
          "min_trade_amount": {
            "type": "number",
            "nullable": true,
            "description": "Minimum allowed order quantity. May be `null` if not yet populated."
          },
          "contract_size": {
            "type": "number",
            "nullable": true,
            "description": "Contract size for the instrument. May be `null` if not yet populated."
          },
          "settlement_period": {
            "type": "string",
            "nullable": true,
            "description": "Settlement period descriptor. May be `null` if not yet populated."
          },
          "maker_commission": {
            "type": "number",
            "nullable": true,
            "description": "Maker commission rate. May be `null` if not yet populated."
          },
          "taker_commission": {
            "type": "number",
            "nullable": true,
            "description": "Taker commission rate. May be `null` if not yet populated."
          },
          "block_trade_commission": {
            "type": "number",
            "nullable": true,
            "description": "Block trade commission rate. May be `null` if not yet populated."
          }
        }
      },
      "Order": {
        "type": "object",
        "description": "A single open order from the authenticated portfolio.",
        "required": [
          "order_id",
          "instrument_name",
          "side",
          "price",
          "amount",
          "filled_amount",
          "order_state",
          "order_type"
        ],
        "properties": {
          "order_id": {
            "type": "string",
            "description": "Exchange-assigned order identifier (UUID-style string). Stable for the lifetime of the order.",
            "example": "1cc1c718-49e0-4ea5-8902-f3f22968c350"
          },
          "instrument_name": {
            "type": "string",
            "description": "Human-readable instrument symbol the order was placed against.",
            "example": "TREE-USD"
          },
          "side": {
            "type": "string",
            "enum": ["buy", "sell"],
            "description": "Order side."
          },
          "price": {
            "type": "number",
            "description": "Limit price of the order (in quote-currency units).",
            "example": 0.0717
          },
          "amount": {
            "type": "number",
            "description": "Original order quantity, in base-currency units.",
            "example": 83698
          },
          "filled_amount": {
            "type": "number",
            "description": "Quantity filled so far, in base-currency units.",
            "example": 0
          },
          "average_price": {
            "type": "number",
            "description": "Volume-weighted average fill price across all executions on this order. Zero if the order has no fills yet.",
            "example": 0
          },
          "order_state": {
            "type": "string",
            "enum": ["open"],
            "description": "Order state. Currently always `open` for entries returned by this endpoint, since only open orders are listed."
          },
          "order_type": {
            "type": "string",
            "enum": ["limit", "market"],
            "description": "Order type, derived from the price field."
          },
          "time_in_force": {
            "type": "string",
            "nullable": true,
            "enum": ["GTC", "IOC", "FOK", "GTD"],
            "description": "Time-in-force policy."
          },
          "post_only": {
            "type": "boolean",
            "description": "Whether the order was submitted as post-only: if it would take liquidity, the price is amended to the best bid/ask instead of rejecting. Corresponds to SBE `postOnly`. Mutually exclusive with `reject_post_only`."
          },
          "reject_post_only": {
            "type": "boolean",
            "description": "Whether the order was submitted as post-only reject: if it would take liquidity, the order is rejected rather than price-amended. Corresponds to SBE `postOnlyReject`. Mutually exclusive with `post_only`."
          },
          "reduce_only": {
            "type": "boolean",
            "description": "Whether the order is reduce-only (intended only to reduce an existing position). Per-order reduce-only originates from JSON-RPC or FIX; it cannot be set per order in SBE."
          },
          "creation_timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Order submission time in milliseconds since the Unix epoch.",
            "example": 1778270370643
          },
          "last_update_timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Time of the most recent change to the order, in milliseconds since the Unix epoch.",
            "example": 1778270370643
          },
          "label": {
            "type": "string",
            "nullable": true,
            "description": "Client-supplied label for the order, if any."
          },
          "api": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the order was placed via API."
          },
          "max_show": {
            "type": "number",
            "nullable": true,
            "description": "Iceberg display quantity, if applicable."
          },
          "profit_loss": {
            "type": "number",
            "nullable": true,
            "description": "Realised profit/loss attributable to this order, if any."
          },
          "commission": {
            "type": "number",
            "nullable": true,
            "description": "Commission accrued by this order so far, if any."
          }
        }
      },
      "JsonRpcError": {
        "type": "object",
        "required": ["jsonrpc", "error"],
        "description": "JSON-RPC 2.0 error envelope returned for failed requests.",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"]
          },
          "id": {
            "type": "integer",
            "nullable": true,
            "description": "The id that was sent in the request, if any."
          },
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "integer",
                "description": "Numeric JSON-RPC error code."
              },
              "message": {
                "type": "string",
                "description": "Human-readable error description."
              },
              "data": {
                "description": "Optional additional error details."
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key passed as a Bearer token. The authenticated session determines the portfolio that operations are applied to."
      }
    }
  }
}
