> 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/get-started/concepts.md).

# Core Concepts

### The hierarchy

Everything in the API hangs off three nested objects:

```
Event            "2026 World Cup winner"          ← what people are betting on
 └─ Market       "Will Brazil win?"               ← one binary question
     └─ Outcome  YES / NO                         ← what you actually trade
         └─ tokenId  0x1a2b…                      ← the identifier you pass everywhere
```

* An **event** is the container. A simple yes/no event holds exactly one market. A multi-outcome event (an election, a tournament) holds one binary market per candidate.
* A **market** is a single binary question with exactly two outcomes.
* An **outcome** is one side of that question, and it carries the `tokenId`.

{% hint style="info" %}
**`tokenId` is the only identifier that matters at trade time.** Orders, order-book queries, WebSocket subscriptions and positions are all keyed by it. `eventId` and `marketId` are for filtering and reporting.
{% endhint %}

{% code title="Walking the hierarchy" %}

```ts
const event  = await client.events.get('will-brazil-win-the-2026-world-cup');
const market = event.markets[0];
const yes    = market.outcomes.find((o) => o.outcomeIndex === 1)!;

console.log(yes.tokenId);   // ← trade with this
```

{% endcode %}

### YES is index 1, NO is index 0

Outcome order in the array is not guaranteed. The reliable mapping is `outcomeIndex`: **`1` is YES, `0` is NO**. Rather than re-deriving that everywhere, use the helper — it is the single source of truth the SDK, the reference bot and the frontend all share:

```ts
import { getTokenIds } from 'strix-sdk';

const { yesTokenId, noTokenId, yesOutcome, noOutcome } = getTokenIds(market);
```

{% hint style="warning" %}
On multi-outcome (`NEG_RISK`) events the displayed `outcomeName` can read the opposite way round from these labels. That is cosmetic — **trust `outcomeIndex`, not the display name**. The `tokenId` returned by `getTokenIds()` is always the correct one to trade.
{% endhint %}

### A share is a dollar-if-right

Each outcome token pays **$1.00** if that outcome happens and **$0.00** if it doesn't. So a price of `0.65` means 65¢ per share — the market's collective estimate of a 65% chance.

* Prices are decimals in `[0.0001, 0.9999]` — never exactly 0 or 1, which would break the YES↔NO complement math.
* `tickSize` is `0.01` or `0.001` depending on the market, and it lives on the **event** (`event.tickSize`). Every order price must be an exact multiple of it, on top of the platform-wide 0.0001 precision floor.
* Quantities are share counts, carried as decimal strings with up to 6 fractional digits.
* Minimum order value is **$1.00**. For a resting order that is `price × quantity`; for a market order it is the value actually swept.

### YES and NO are the same book, mirrored

Buying YES at 40¢ and selling NO at 60¢ are economically identical, so the two books are complements:

```
bid YES @ P   ≡   ask NO @ (1 − P)
```

The SDK exposes this directly. Subscribe to the YES token and you get both prices:

```ts
client.ws.orderbook.subscribe([yesTokenId], {
  onMid: ({ yesMid, noMid }) => console.log(`YES ${yesMid} · NO ${noMid}`),
});
```

This mirroring is also why a **market buy behaves the way it does**: it only sweeps resting *asks on the same token*. It will not cross into the sibling outcome's bids. On a book with bids but no asks, a market buy fails with `no_liquidity` — to take a resting bid on the other leg, place a crossing limit buy on the sibling token at `1 − bidPrice` instead. See [Orders](/typescript-sdk/orders.md#market-orders).

### Orders settle asynchronously

This is the single biggest difference from a conventional exchange API, and the most common source of bugs:

{% stepper %}
{% step %}

#### You place an order

`POST /orders` validates it, reserves your balance, and returns `status: "OPEN"` with `filledQuantity: "0"` — **even if it crosses the spread and will fill immediately.**
{% endstep %}

{% step %}

#### The engine matches it

Milliseconds later, the matching engine locks the matched size. The order-book delta goes out to every subscriber, and your order's matched quantity moves into `holdQuantity`.
{% endstep %}

{% step %}

#### The trade settles on-chain

Roughly 15–20 seconds later the settlement transaction confirms. Now `status` becomes `FILLED` or `PARTIALLY_FILLED`, and `trade.settled` fires on your user channel with the transaction hash.
{% endstep %}
{% endstepper %}

Two practical consequences:

1. **Don't treat the placement response as a fill report.** Observe fills via `order.update` / `trade.settled` on the [user channel](/typescript-sdk/websockets.md#your-orders-and-fills), or by polling `portfolio.positions()`.
2. **Your resting size is a three-term subtraction.** While a settlement is in flight, part of your order is neither filled nor on the book:

   ```ts
   const resting = Number(order.quantity) - Number(order.filledQuantity) - Number(order.holdQuantity);
   ```

   The two-term version looks right and quietly overstates your exposure.

### Order statuses

<table><thead><tr><th width="220">Status</th><th>Meaning</th></tr></thead><tbody><tr><td><code>OPEN</code></td><td>Resting on the book, nothing filled.</td></tr><tr><td><code>PARTIALLY_FILLED</code></td><td>Some quantity settled; the remainder is still working.</td></tr><tr><td><code>HOLD</code> / <code>PARTIALLY_HOLD</code></td><td>Matched and locked while settlement is in flight. <strong>Not cancellable.</strong></td></tr><tr><td><code>FILLED</code></td><td>Fully settled.</td></tr><tr><td><code>CANCELLED</code></td><td>Cancelled by you, by expiry sweep, or by an unfilled FOK/FAK remainder.</td></tr><tr><td><code>EXPIRED</code></td><td>A GTD order passed its <code>expiredAt</code>.</td></tr></tbody></table>

The WebSocket user channel adds one transient status you'll never see over REST: **`MATCHED`**, emitted between the engine match and on-chain confirmation.

{% hint style="info" %}
**Cancels are restricted to `OPEN` orders.** Once any part of an order is matched or settling, cancelling it would race the settlement, so the venue refuses. A cancel that fails means **the order is still live** — never assume otherwise and quote against it.
{% endhint %}

### Splitting and merging

Because a full outcome set is worth exactly $1, you can convert between USDC and shares without touching the book at all:

* **Split** — $100 USDC becomes 100 YES + 100 NO.
* **Merge** — 100 YES + 100 NO becomes $100 USDC.
* **Redeem** — after resolution, winning shares become $1 each.

These are on-chain operations exposed as [`client.positions`](/typescript-sdk/portfolio.md#conditional-token-operations). Market makers use split to manufacture two-sided inventory instead of buying it.


---

# 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/get-started/concepts.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.
