> ## 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/)

<Warning>
  **The SDK can lag the OpenAPI.** New endpoints and fields land in the venue
  spec first. For production bots that must track every surface on day one,
  generate a client from
  [venue-openapi.yaml](/api-spec/venue-openapi.yaml) (and
  [venue-asyncapi.yaml](/api-spec/venue-asyncapi.yaml) for WS) rather than waiting
  on a package release. The SDK remains the fastest path for common flows.
</Warning>

## 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 **API key** and **secret**
   (shown once).

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

## Quick start

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

with Client(api_key="<alphanumeric-api-key>", api_secret="<64-char-hex-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="<alphanumeric-api-key>", api_secret="<64-char-hex-secret>") as client:
    balance = await client.get_balance()
```

## WebSocket

One signed connection multiplexes public and private channels. Pass `market_ids`
for `orderbook_delta` and `trades`. Live channels also include `oracle`,
`rounds`, and `user`. (`ticker` is not implemented.)

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
with Client(api_key="<alphanumeric-api-key>", api_secret="<64-char-hex-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 — prefer update_subscription get_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 / retention
* Account limits (scopes, rate buckets, batch cap)
* Markets, orderbook, trades
* Rounds and oracle price
* Portfolio balance, positions, fills, orders, queue position
* Place / batch / cancel / cancel-batch / cancel-all / decrease
* Dead-man switch (arm / disarm)
* Deposit address (read)
* WebSocket subscribe / unsubscribe / update\_subscription / 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.
