> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omnibook.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Install the official Omnibook Python client and place your first order.

The official Python SDK wraps HMAC signing, REST, and WebSocket so agents and
bots can trade without assembling headers by hand.

* GitHub: [OmniBook-HQ/python-sdk-v1](https://github.com/OmniBook-HQ/python-sdk-v1)
* PyPI: [`omnibook`](https://pypi.org/project/omnibook/)

## Install

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install omnibook
```

Requires Python 3.10+.

## Prerequisites

1. Sign in at [omnibook.xyz](https://omnibook.xyz).
2. Deposit USDC (bot keys **cannot** withdraw).
3. Create a key under **Settings → API keys**. Copy the **key ID** and **secret**
   (shown once).

The SDK talks to the venue (`https://api.omnibook.xyz`), not the browser session
proxy. Pass the base64 secret from Settings — the client decodes it to the raw
32-byte HMAC key for you.

## Quick start

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from omnibook import Client

with Client(api_key="6", api_secret="<base64-secret>") as client:
    print(client.get_exchange_status())
    rounds = client.get_rounds(limit=5)
    print(rounds)
```

### Place an order

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
order = client.place_order(
    client_order_id="42",          # your idempotency key
    market_id=66,
    side="buy",
    outcome="yes",
    type="limit",
    tick=47,
    qty=10,
    tif="gtc",
    post_only=True,
)
print(order["order_id"], order["status"])
client.cancel_order(order["order_id"])
```

On a `504` sequencing timeout, **retry with the same `client_order_id`** — see
[Orders](/concepts/orders).

### Async

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from omnibook import AsyncClient

async with AsyncClient(api_key="6", api_secret="<base64-secret>") as client:
    balance = await client.get_balance()
```

## WebSocket

One signed connection multiplexes public and private channels. Pass `market_ids`
for `orderbook_delta`, `trades`, and `ticker`.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with Client(api_key="6", api_secret="<base64-secret>") as client:
    with client.websocket() as ws:
        ws.subscribe(channels=["rounds", "oracle", "user"])
        ws.subscribe(channels=["orderbook_delta", "trades"], market_ids=[66])
        for msg in ws:
            if msg.get("_gap"):
                # Public channel gap — resubscribe for a fresh snapshot.
                ...
            print(msg)
```

Channel details: [WebSocket overview](/websocket/overview) and
[Channels](/websocket/channels).

## Environments

| Env                  | REST                       | WebSocket                      |
| -------------------- | -------------------------- | ------------------------------ |
| Production (default) | `https://api.omnibook.xyz` | `wss://api.omnibook.xyz/v1/ws` |
| Local                | `http://127.0.0.1:9104`    | `ws://127.0.0.1:9105/v1/ws`    |

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
Client(
    api_key="...",
    api_secret="...",
    base_url="http://127.0.0.1:9104",
    ws_url="ws://127.0.0.1:9105/v1/ws",
)
```

## Errors

The SDK raises typed exceptions from the venue envelope:

| Exception                | When                                        |
| ------------------------ | ------------------------------------------- |
| `OmnibookAuthError`      | 401 / bad signature / clock skew            |
| `OmnibookRateLimitError` | 429 — check `retry_after`                   |
| `OmnibookTimeoutError`   | 504 — retry same `client_order_id`          |
| `OmnibookAPIError`       | other HTTP errors (`code`, `origin`, `num`) |

Branch on `exc.code`, not the message. Full list: [Errors](/concepts/errors).

## What the SDK covers

* Exchange status / schedule
* Markets, orderbook, trades
* Rounds and oracle price
* Portfolio balance, positions, fills, orders
* Place / batch / cancel / mass-cancel / decrease
* Deposit address (read)
* WebSocket subscribe / unsubscribe / stream

Withdrawals and account signup are intentionally out of scope for bot keys.

## Running the tests

From the [SDK repository](https://github.com/OmniBook-HQ/python-sdk-v1):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install -e ".[dev]"
pytest                     # unit tests (mocked) — always safe
```

Live venue tests (auth, market data, place+cancel, WebSocket subscribe):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
OMNIBOOK_RUN_INTEGRATION=1 \
  OMNIBOOK_API_KEY=... \
  OMNIBOOK_API_SECRET=... \
  OMNIBOOK_BASE_URL=http://127.0.0.1:9104 \
  OMNIBOOK_WS_URL=ws://127.0.0.1:9105/v1/ws \
  pytest -m integration
```

Prefer the local venue when available. Place-order tests use tiny `post_only`
sizes and cancel in teardown.

## Prefer raw HTTP?

See [Authentication](/quickstart/authentication) for HMAC header details in
Python, TypeScript, and cURL without the SDK.
