> For the complete documentation index, see [llms.txt](https://dev.strixlab.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev.strixlab.io/http-and-websocket-api/rest.md).

# REST Endpoints

**Base URL:** `https://api.strixlab.io/api` · testnet `https://api-staging.strixlab.io/api`

Endpoints marked **Public** need no credentials. The rest require [HMAC authentication](/http-and-websocket-api/authentication.md) — and remember that the signed path **excludes** the `/api` prefix.

### The response envelope

Every response, success or failure, uses the same wrapper:

{% tabs %}
{% tab title="Success" %}

```json
{
  "success": true,
  "data": { }
}
```

{% endtab %}

{% tab title="Failure" %}

```json
{
  "success": false,
  "code": "insufficient_balance",
  "message": "Insufficient USDC balance. Required: $62.00, available after holds: $20.00"
}
```

Branch on `code`, never on `message`. See [Errors & Rate Limits](/typescript-sdk/errors-and-rate-limits.md#error-codes) for the full taxonomy.
{% endtab %}
{% endtabs %}

***

## Health

<table><thead><tr><th width="290">Endpoint</th><th width="90"></th><th>Returns</th></tr></thead><tbody><tr><td><code>GET /ok</code></td><td>Public</td><td>Liveness check.</td></tr><tr><td><code>GET /time</code></td><td>Public</td><td><code>{ serverTime }</code> — Unix seconds. Use it to check clock drift.</td></tr></tbody></table>

***

## Markets

### `GET /events` · Public

<table><thead><tr><th width="160">Param</th><th width="140">Type</th><th>Notes</th></tr></thead><tbody><tr><td><code>status</code></td><td>string</td><td><code>open</code>, <code>closed</code>, <code>resolved</code></td></tr><tr><td><code>category</code></td><td>string</td><td>Category slug — <code>crypto</code>, <code>sports</code>, <code>politics</code>, …</td></tr><tr><td><code>tag</code></td><td>string</td><td>Tag slug.</td></tr><tr><td><code>search</code></td><td>string</td><td>Title search.</td></tr><tr><td><code>limit</code> / <code>offset</code></td><td>number</td><td>1–100 (default 20) / default 0.</td></tr><tr><td><code>includeTotal</code></td><td>boolean</td><td><code>false</code> skips the count query.</td></tr></tbody></table>

```json
{
  "success": true,
  "data": {
    "items": [{
      "id": "clxabc123",
      "slug": "will-btc-close-above-100k-in-2026",
      "title": "Will BTC close above $100k in 2026?",
      "category": "crypto",
      "marketType": "CTF",
      "status": "open",
      "tickSize": "0.01",
      "expiryTime": "2026-12-31T23:59:59.000Z",
      "markets": [{
        "id": "mkt_abc",
        "title": null,
        "status": "open",
        "enableOrderBook": true,
        "volume": "184320.50",
        "outcomes": [
          { "id": "out_no",  "name": "No",  "tokenId": "0x3c4d…", "outcomeIndex": 0, "lastPrice": "0.38" },
          { "id": "out_yes", "name": "Yes", "tokenId": "0x1a2b…", "outcomeIndex": 1, "lastPrice": "0.62" }
        ]
      }]
    }],
    "total": 148, "limit": 20, "offset": 0
  }
}
```

{% hint style="info" %}
`outcome.tokenId` is the identifier for orders, order books and WebSocket subscriptions — **not** `outcome.id`. YES is `outcomeIndex: 1`, NO is `0`; never rely on array order. `tickSize` lives on the **event** and applies to every market inside it.
{% endhint %}

### Other market reads · Public

<table><thead><tr><th width="330">Endpoint</th><th>Returns</th></tr></thead><tbody><tr><td><code>GET /events/:idOrSlug</code></td><td>One event with its markets and outcomes.</td></tr><tr><td><code>GET /events/:id/resolution</code></td><td>On-chain resolution status and timeline. <code>?marketId=</code> scopes multi-outcome events.</td></tr><tr><td><code>GET /markets/:id</code></td><td>One binary market.</td></tr><tr><td><code>GET /categories</code></td><td>Category list for filtering.</td></tr></tbody></table>

***

## Order book · Public

<table><thead><tr><th width="360">Endpoint</th><th>Returns</th></tr></thead><tbody><tr><td><code>GET /orderbook/:tokenId?depth=50</code></td><td>Aggregated book. Depth ≤ 200, default 50.</td></tr><tr><td><code>GET /midpoint/:tokenId</code></td><td><code>{ mid }</code>. <strong>404</strong> when either side is empty.</td></tr><tr><td><code>GET /price/:tokenId/:side</code></td><td><code>side</code> is <code>buy</code> (best ask) or <code>sell</code> (best bid).</td></tr></tbody></table>

```json
{
  "success": true,
  "data": {
    "bids": [{ "price": 0.62, "size": 500 }, { "price": 0.61, "size": 300 }],
    "asks": [{ "price": 0.63, "size": 200 }, { "price": 0.64, "size": 450 }]
  }
}
```

`bids` are highest-first, `asks` lowest-first, `size` is total shares resting at that price. For live data use the [WebSocket book channel](/http-and-websocket-api/websocket.md#order-book-channel) rather than polling.

***

## Orders · Auth

### `POST /orders` — place a limit order

```json
{ "tokenId": "0x1a2b…", "side": "BUY", "price": 0.62, "quantity": 100, "orderType": "GTC" }
```

<table><thead><tr><th width="150">Field</th><th width="180">Type</th><th width="70">Req</th><th>Notes</th></tr></thead><tbody><tr><td><code>tokenId</code></td><td>string</td><td>✓</td><td>Outcome token.</td></tr><tr><td><code>side</code></td><td><code>BUY</code> | <code>SELL</code></td><td>✓</td><td></td></tr><tr><td><code>price</code></td><td>number</td><td>✓</td><td>Multiple of <code>tickSize</code>; <code>0.0001</code>–<code>0.9999</code>.</td></tr><tr><td><code>quantity</code></td><td>number</td><td>✓</td><td>Shares. <code>price × quantity ≥ 1.0</code>.</td></tr><tr><td><code>orderType</code></td><td>string</td><td>–</td><td><code>GTC</code> (default), <code>GTD</code>, <code>FOK</code>, <code>FAK</code>.</td></tr><tr><td><code>expiredAt</code></td><td>ISO datetime</td><td>GTD</td><td>At least 1 minute in the future.</td></tr></tbody></table>

```json
{
  "success": true,
  "data": {
    "id": "ord_abc", "orderHash": "0xdeadbeef…", "tokenId": "0x1a2b…",
    "side": "BUY", "price": "0.62", "quantity": "100",
    "filledQuantity": "0", "holdQuantity": "0",
    "status": "OPEN", "timeInForce": "GTC",
    "expiredAt": null, "createdAt": "2026-08-22T10:00:00.000Z"
  }
}
```

{% hint style="warning" %}
**This is an acknowledgement, not a fill report.** Matching and settlement are asynchronous (\~15–20 s), so a crossing order still returns `OPEN` / `filledQuantity: "0"`. Watch the [user channel](/http-and-websocket-api/websocket.md#user-channel) for the outcome. Keep `orderHash` — it is the cancel handle.
{% endhint %}

### `POST /orders/market` — place a market order

Sizing differs by side: a BUY names the USDC it may spend, a SELL the shares it sells.

{% tabs %}
{% tab title="BUY" %}

```json
{ "tokenId": "0x1a2b…", "side": "BUY", "maxSpend": "100", "timeInForce": "FOK" }
```

{% endtab %}

{% tab title="SELL" %}

```json
{ "tokenId": "0x1a2b…", "side": "SELL", "quantity": "50", "timeInForce": "FAK", "maxSlippageBps": 50 }
```

{% endtab %}
{% endtabs %}

<table><thead><tr><th width="190">Field</th><th>Notes</th></tr></thead><tbody><tr><td><code>maxSpend</code></td><td>BUY only. Maximum USDC, decimal string, up to 6 places.</td></tr><tr><td><code>quantity</code></td><td>SELL only. Shares, decimal string, up to 6 places.</td></tr><tr><td><code>timeInForce</code></td><td><code>FOK</code> (default) or <code>FAK</code>.</td></tr><tr><td><code>maxSlippageBps</code></td><td>Optional. Reject if the sweep's average is worse than this many bps from the touch.</td></tr></tbody></table>

```json
{
  "success": true,
  "data": {
    "order": { "id": "ord_abc", "status": "OPEN", "…": "…" },
    "executionPlan": {
      "requestedMaxSpend": "100",
      "submittedQuantity": "153.846154",
      "limitPrice": "0.66",
      "estimatedAveragePrice": "0.6534",
      "estimatedQuoteAmount": "99.998",
      "bookTimestamp": "2026-08-22T10:00:00.000Z"
    }
  }
}
```

{% hint style="danger" %}
A market **BUY** only sweeps resting **asks on the same token** — it does not cross into the sibling outcome's bids, so a bid-only book returns `no_liquidity`. A market **SELL**'s computed price can land off-tick on a coarse-tick market. In both cases a tick-aligned crossing limit order with `orderType: "FAK"` is the reliable pattern.
{% endhint %}

### `POST /orders/batch` — up to 15 orders

```json
{ "orders": [
  { "tokenId": "0x1a2b…", "side": "BUY",  "price": 0.60, "quantity": 100, "orderType": "GTC" },
  { "tokenId": "0x1a2b…", "side": "SELL", "price": 0.64, "quantity": 100, "orderType": "GTC" }
] }
```

Each item is validated independently; one failure does not roll back the others.

```json
{ "success": true, "data": [
  { "index": 0, "success": true,  "order": { "orderHash": "0xaaa…" } },
  { "index": 1, "success": false, "error": "Minimum order value is $1.00 (got $0.64)" }
] }
```

The whole batch counts as **one** order-write against the rate limit.

### Cancelling

<table><thead><tr><th width="320">Endpoint</th><th width="140">Rate limited</th><th>Scope</th></tr></thead><tbody><tr><td><code>DELETE /orders/:orderHash</code></td><td><strong>Yes</strong></td><td>One order.</td></tr><tr><td><code>POST /orders/batch-cancel</code></td><td>No</td><td><code>{ "orderHashes": [...] }</code> — up to 100.</td></tr><tr><td><code>DELETE /orders</code></td><td>No</td><td>Everything, or <code>?tokenId=</code> / <code>?marketId=</code>.</td></tr></tbody></table>

```json
{ "success": true, "data": { "cancelled": 12, "failed": 0 } }
```

{% hint style="danger" %}
**`DELETE /orders` is the most important endpoint for a bot.** It is exempt from rate limiting so it always works as a kill-switch. Fire it on any connectivity problem, model failure, or shutdown.
{% endhint %}

Only `OPEN` orders can be cancelled — anything matched or settling is committed. `failed` counts orders skipped for that reason; a failed cancel means **the order is still live**.

### `GET /orders` — your open orders

Returns your `OPEN` and `PARTIALLY_FILLED` orders; `?marketId=` scopes it. Always caller-scoped — for aggregated depth use the public order-book endpoints.

***

## Portfolio · Auth

<table><thead><tr><th width="330">Endpoint</th><th>Returns</th></tr></thead><tbody><tr><td><code>GET /portfolio/balances</code></td><td>Cash, available, on-hold, and share counts per token. <strong>The cheap one</strong> — use it in loops.</td></tr><tr><td><code>GET /portfolio/summary</code></td><td>Adds P&#x26;L, cost basis and account return. Replays the trade ledger.</td></tr><tr><td><code>GET /portfolio/positions</code></td><td>All open positions.</td></tr><tr><td><code>GET /portfolio/market/:marketId</code></td><td>Positions in one market.</td></tr><tr><td><code>GET /portfolio/trades?limit=</code></td><td>Settled trade history.</td></tr><tr><td><code>GET /portfolio/deposits?limit=</code></td><td>Deposit history.</td></tr><tr><td><code>GET /portfolio/withdrawals?limit=</code></td><td>Withdrawal history.</td></tr></tbody></table>

```json
{
  "success": true,
  "data": {
    "cashBalance": "1000.00",
    "availableBalance": "842.15",
    "usdcOnHold": "157.85",
    "positions": [
      { "tokenId": "0x1a2b…", "marketId": "mkt_abc", "outcomeId": "out_yes",
        "shareAmount": "250", "onHoldShareAmount": "0" }
    ]
  }
}
```

{% hint style="info" %}
Match positions by **`tokenId`**. `outcomeId` is a database id, not the ERC-1155 token. Positions are indexed from chain state and lag a fill by \~30 s–2 min; the WebSocket `position.update` event bridges that gap optimistically.
{% endhint %}

***

## Conditional tokens · Auth

<table><thead><tr><th width="290">Endpoint</th><th>Body</th><th>Effect</th></tr></thead><tbody><tr><td><code>POST /positions/split</code></td><td><code>{ eventId, marketId?, amount }</code></td><td>USDC → one share of every outcome.</td></tr><tr><td><code>POST /positions/merge</code></td><td><code>{ eventId, marketId?, amount }</code></td><td>A full outcome set → USDC.</td></tr><tr><td><code>POST /positions/redeem</code></td><td><code>{ marketId }</code></td><td>Winning shares → $1.00 each, after resolution.</td></tr><tr><td><code>GET /positions/claimable</code></td><td>—</td><td>Resolved markets with unredeemed winnings.</td></tr></tbody></table>

Each returns `{ "txHash": "0x…" }`. `marketId` is required for multi-outcome events and optional for binary ones.

***

## Price history & feeds · Public

<table><thead><tr><th width="330">Endpoint</th><th>Notes</th></tr></thead><tbody><tr><td><code>GET /kline</code></td><td><code>?outcomeId=&#x26;interval=&#x26;from=&#x26;to=</code> — intervals <code>m1 m5 m15 h1 h4 d1</code>.</td></tr><tr><td><code>GET /activity</code></td><td>Platform-wide settled trades, paginated.</td></tr><tr><td><code>GET /leaderboard</code></td><td><code>?period=today|weekly|monthly|all</code>.</td></tr></tbody></table>

```json
{ "success": true, "data": [
  { "timestamp": "2026-08-22T10:00:00.000Z", "open": "0.60", "high": "0.64", "low": "0.59", "close": "0.62", "volume": "1200" }
] }
```

***

## Rate limits

<table><thead><tr><th width="270">Bucket</th><th width="200">API-key limit</th><th>Endpoints</th></tr></thead><tbody><tr><td>Order writes</td><td>300 per 10 s (≈30/s)</td><td><code>POST /orders</code>, <code>/orders/market</code>, <code>/orders/batch</code>, <code>DELETE /orders/:hash</code></td></tr><tr><td>Reads</td><td>500 per second</td><td>Everything else.</td></tr><tr><td>Bulk cancels</td><td><strong>Exempt</strong></td><td><code>DELETE /orders</code>, <code>POST /orders/batch-cancel</code></td></tr></tbody></table>

A `429` carries a `Retry-After` header in seconds. Browser-session (Bearer) traffic gets a much smaller budget than API keys — another reason to use HMAC for bots.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://dev.strixlab.io/http-and-websocket-api/rest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
