> For the complete documentation index, see [llms.txt](https://docs.ojolabs.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ojolabs.xyz/markets/api/python-sdk/client-reference.md).

# Client Reference

Complete reference for all `TurbineClient` methods, organized by access level.

## Public Data (No Auth)

These methods work with any client, including read-only clients with no credentials.

### get\_markets

Fetch all markets, optionally filtered by chain.

```python
markets = client.get_markets()
markets = client.get_markets(chain_id=137)

for m in markets:
    print(f"{m.question} | volume={m.volume / 1e6:.2f} USDC | resolved={m.resolved}")
```

| Parameter  | Type  | Required | Description        |
| ---------- | ----- | -------- | ------------------ |
| `chain_id` | `int` | No       | Filter by chain ID |

**Returns:** `list[Market]`

### get\_market

Get stats for a single market.

```python
stats = client.get_market(market_id="0x...")

print(f"Last price: {stats.last_price / 1e6:.4f} (${stats.last_price / 1e6:.4f})")
print(f"24h volume: {stats.volume_24h / 1e6:.2f} USDC")
print(f"Total volume: {stats.total_volume / 1e6:.2f} USDC")
```

| Parameter   | Type  | Required | Description            |
| ----------- | ----- | -------- | ---------------------- |
| `market_id` | `str` | Yes      | Market ID (hex string) |

**Returns:** `MarketStats`

### get\_orderbook

Get the orderbook snapshot for a market, optionally filtered by outcome.

```python
# Full orderbook (both outcomes)
ob = client.get_orderbook("0x...")

# YES side only
yes_ob = client.get_orderbook("0x...", outcome=Outcome.YES)

# Print top of book
if yes_ob.bids:
    best_bid = yes_ob.bids[0]
    print(f"Best bid: {best_bid.price} (${best_bid.price / 1e6:.4f}) x {best_bid.size / 1e6:.2f}")
if yes_ob.asks:
    best_ask = yes_ob.asks[0]
    print(f"Best ask: {best_ask.price} (${best_ask.price / 1e6:.4f}) x {best_ask.size / 1e6:.2f}")
```

| Parameter   | Type      | Required | Description                             |
| ----------- | --------- | -------- | --------------------------------------- |
| `market_id` | `str`     | Yes      | Market ID                               |
| `outcome`   | `Outcome` | No       | Filter by `Outcome.YES` or `Outcome.NO` |

**Returns:** `OrderBookSnapshot`

### get\_trades

Get recent trades for a market.

```python
trades = client.get_trades("0x...", limit=50)

for t in trades:
    side = "BUY" if t.outcome == 0 else "SELL"
    print(f"{side} {t.size / 1e6:.2f} @ {t.price} (${t.price / 1e6:.4f}) | tx={t.tx_hash}")
```

| Parameter   | Type  | Required | Description                           |
| ----------- | ----- | -------- | ------------------------------------- |
| `market_id` | `str` | Yes      | Market ID                             |
| `limit`     | `int` | No       | Max trades to return (default: `100`) |

**Returns:** `list[Trade]`

### get\_stats

Get statistics for a market. Alias for `get_market`.

| Parameter   | Type  | Required | Description |
| ----------- | ----- | -------- | ----------- |
| `market_id` | `str` | Yes      | Market ID   |

**Returns:** `MarketStats`

### get\_platform\_stats

Get platform-wide statistics across all chains.

```python
stats = client.get_platform_stats()

print(f"Total volume: {stats.total_volume / 1e6:.2f} USDC")
print(f"Total trades: {stats.total_trades}")

for chain in stats.chains:
    print(f"  Chain {chain.chain_id}: {chain.total_volume / 1e6:.2f} USDC")
```

**Returns:** `PlatformStats`

### get\_holders

Get top position holders for a market.

```python
holders = client.get_holders("0x...", limit=10)

for h in holders:
    print(f"{h.user_address}: YES={h.yes_shares / 1e6:.2f}, NO={h.no_shares / 1e6:.2f}")
```

| Parameter   | Type  | Required | Description                            |
| ----------- | ----- | -------- | -------------------------------------- |
| `market_id` | `str` | Yes      | Market ID                              |
| `limit`     | `int` | No       | Max holders to return (default: `100`) |

**Returns:** `list[Holder]`

### get\_resolution

Get resolution status for a market.

```python
res = client.get_resolution("0x...")

print(f"Resolved: {res.resolved}")
if res.resolved:
    outcome = "YES" if res.outcome == 0 else "NO"
    print(f"Winner: {outcome}")
    print(f"Assertion ID: {res.assertion_id}")
```

| Parameter   | Type  | Required | Description |
| ----------- | ----- | -------- | ----------- |
| `market_id` | `str` | Yes      | Market ID   |

**Returns:** `Resolution`

### get\_health

Check API server health.

```python
health = client.get_health()
print(health)
```

**Returns:** `dict`

### get\_quick\_market

Get the active quick market for an asset.

```python
qm = client.get_quick_market("BTC")

print(f"Market ID: {qm.market_id}")
print(f"Strike: ${qm.start_price / 1e8:,.2f}")
print(f"Ends: {qm.end_time}")
print(f"Contract: {qm.contract_address}")
```

| Parameter | Type  | Required | Description                     |
| --------- | ----- | -------- | ------------------------------- |
| `asset`   | `str` | Yes      | Asset symbol (`"BTC"`, `"ETH"`) |

**Returns:** `QuickMarket`

### get\_quick\_market\_history

Get historical quick markets for an asset.

```python
history = client.get_quick_market_history("BTC", limit=10)

for qm in history:
    outcome = "YES" if qm.outcome == 0 else ("NO" if qm.outcome == 1 else "N/A")
    print(f"ID={qm.id} | resolved={qm.resolved} | outcome={outcome}")
```

| Parameter | Type  | Required | Description                            |
| --------- | ----- | -------- | -------------------------------------- |
| `asset`   | `str` | Yes      | Asset symbol                           |
| `limit`   | `int` | No       | Max markets to return (default: `100`) |

**Returns:** `list[QuickMarket]`

### get\_quick\_market\_price

Get the current price for an asset.

```python
price = client.get_quick_market_price("BTC")
print(f"BTC: ${price.price / 1e8:,.2f}")
```

| Parameter | Type  | Required | Description  |
| --------- | ----- | -------- | ------------ |
| `asset`   | `str` | Yes      | Asset symbol |

**Returns:** `AssetPrice`

### get\_quick\_market\_price\_history

Get price history for an asset.

```python
prices = client.get_quick_market_price_history("BTC", limit=60)

for p in prices:
    print(f"  {p.timestamp}: ${p.price / 1e8:,.2f}")
```

| Parameter | Type  | Required | Description                           |
| --------- | ----- | -------- | ------------------------------------- |
| `asset`   | `str` | Yes      | Asset symbol                          |
| `limit`   | `int` | No       | Max prices to return (default: `100`) |

**Returns:** `list[AssetPrice]`

### get\_failed\_trades

Get all failed trade settlements.

```python
failed = client.get_failed_trades()
for t in failed:
    print(f"tx={t.tx_hash} | reason={t.reason} | size={t.fill_size}")
```

**Returns:** `list[FailedTrade]`

### get\_pending\_trades

Get all pending trade settlements.

```python
pending = client.get_pending_trades()
for t in pending:
    print(f"tx={t.tx_hash} | size={t.fill_size} | batch={t.is_batch}")
```

**Returns:** `list[PendingTrade]`

### get\_failed\_claims

Get all failed redemption claims.

**Returns:** `list[FailedClaim]`

### get\_pending\_claims

Get all pending redemption claims.

**Returns:** `list[PendingClaim]`

### get\_settlement\_status

Check the settlement status for a specific transaction.

```python
status = client.get_settlement_status("0xTxHash...")

print(f"Found: {status.found}")
print(f"Status: {status.status}")
print(f"Error: {status.error}")
```

| Parameter | Type  | Required | Description      |
| --------- | ----- | -------- | ---------------- |
| `tx_hash` | `str` | Yes      | Transaction hash |

**Returns:** `SettlementStatus`

***

## Order Management (Requires Signing)

These methods require a `private_key` in the client constructor (Level 1+).

### create\_order

Create and sign an order from an `OrderArgs` object.

```python
from turbine_client import OrderArgs, Outcome, Side
import time

args = OrderArgs(
    market_id="0x...",
    side=Side.BUY,
    outcome=Outcome.YES,
    price=500000,           # $0.50
    size=10000000,          # 10 shares
    expiration=int(time.time()) + 3600,
)

signed = client.create_order(args)
print(f"Order hash: {signed.order_hash}")
print(f"Signature: {signed.signature}")
```

| Parameter            | Type        | Required | Description                                                       |
| -------------------- | ----------- | -------- | ----------------------------------------------------------------- |
| `order_args`         | `OrderArgs` | Yes      | Order parameters                                                  |
| `settlement_address` | `str`       | No       | Override settlement address (auto-fetched from market if omitted) |

**Returns:** `SignedOrder`

### create\_limit\_buy

Convenience method for creating a signed buy order.

```python
signed = client.create_limit_buy(
    market_id="0x...",
    outcome=Outcome.YES,
    price=450000,       # $0.45
    size=5000000,       # 5 shares
    expiration=int(time.time()) + 3600,
)
```

| Parameter            | Type      | Required | Description                                      |
| -------------------- | --------- | -------- | ------------------------------------------------ |
| `market_id`          | `str`     | Yes      | Market ID                                        |
| `outcome`            | `Outcome` | Yes      | `Outcome.YES` or `Outcome.NO`                    |
| `price`              | `int`     | Yes      | Price (`1`–`999999`, where `500000` = $0.50)     |
| `size`               | `int`     | Yes      | Size in shares (6 decimals; `1000000` = 1 share) |
| `expiration`         | `int`     | No       | Unix timestamp (default: 1 hour from now)        |
| `settlement_address` | `str`     | No       | Override settlement address                      |

**Returns:** `SignedOrder`

### create\_limit\_sell

Same parameters and behavior as `create_limit_buy`, but creates a sell order.

**Returns:** `SignedOrder`

***

## Authenticated Endpoints (Requires Bearer Token)

These methods require `api_key_id` + `api_private_key` (Level 2). Bearer tokens are generated automatically per request.

### post\_order

Submit a signed order to the orderbook.

```python
signed = client.create_limit_buy(
    market_id="0x...",
    outcome=Outcome.YES,
    price=500000,
    size=1000000,
)

result = client.post_order(signed)
print(f"Response: {result}")
```

| Parameter      | Type          | Required | Description    |
| -------------- | ------------- | -------- | -------------- |
| `signed_order` | `SignedOrder` | Yes      | A signed order |

**Returns:** `dict` — API response with match/fill details

### get\_orders

Get orders, optionally filtered.

```python
# All open orders for a market
orders = client.get_orders(market_id="0x...", status="open")

# All orders by a specific trader
orders = client.get_orders(trader="0xAddress...")

for o in orders:
    side = "BUY" if o.side == 0 else "SELL"
    outcome = "YES" if o.outcome == 0 else "NO"
    print(f"{side} {outcome} | {o.remaining_size / 1e6:.2f} @ {o.price} (${o.price / 1e6:.4f}) | {o.status}")
```

| Parameter   | Type  | Required | Description                                 |
| ----------- | ----- | -------- | ------------------------------------------- |
| `trader`    | `str` | No       | Filter by trader address                    |
| `market_id` | `str` | No       | Filter by market ID                         |
| `status`    | `str` | No       | Filter: `"open"`, `"filled"`, `"cancelled"` |

**Returns:** `list[Order]`

### get\_order

Get a specific order by hash.

```python
order = client.get_order("0xOrderHash...")
print(f"Status: {order.status} | Filled: {order.filled_size / 1e6:.2f} / {order.size / 1e6:.2f}")
```

| Parameter    | Type  | Required | Description    |
| ------------ | ----- | -------- | -------------- |
| `order_hash` | `str` | Yes      | The order hash |

**Returns:** `Order`

### cancel\_order

Cancel a single order.

```python
result = client.cancel_order(
    order_hash="0x...",
    market_id="0x...",     # optional
    side=Side.BUY,         # optional
)
```

| Parameter    | Type   | Required | Description                 |
| ------------ | ------ | -------- | --------------------------- |
| `order_hash` | `str`  | Yes      | The order hash              |
| `market_id`  | `str`  | No       | Market ID (for validation)  |
| `side`       | `Side` | No       | Order side (for validation) |

**Returns:** `dict`

### cancel\_market\_orders

Cancel all your orders for a market.

```python
result = client.cancel_market_orders(market_id="0x...")
```

| Parameter   | Type  | Required | Description |
| ----------- | ----- | -------- | ----------- |
| `market_id` | `str` | Yes      | Market ID   |

**Returns:** `dict`

### get\_positions

Get positions for a market, optionally filtered by user.

```python
positions = client.get_positions(market_id="0x...", user_address="0x...")

for p in positions:
    print(f"YES: {p.yes_shares / 1e6:.2f} shares (cost: {p.yes_cost / 1e6:.2f} USDC)")
    print(f"NO:  {p.no_shares / 1e6:.2f} shares (cost: {p.no_cost / 1e6:.2f} USDC)")
```

| Parameter      | Type  | Required | Description            |
| -------------- | ----- | -------- | ---------------------- |
| `market_id`    | `str` | Yes      | Market ID              |
| `user_address` | `str` | No       | Filter by user address |

**Returns:** `list[Position]`

### get\_user\_positions

Get all positions across markets for a user.

```python
positions = client.get_user_positions(address="0x...", chain_id=137)

for p in positions:
    print(f"Market {p.market_id[:16]}... | YES={p.yes_shares / 1e6:.2f} | NO={p.no_shares / 1e6:.2f}")
```

| Parameter  | Type  | Required | Description        |
| ---------- | ----- | -------- | ------------------ |
| `address`  | `str` | Yes      | User address       |
| `chain_id` | `int` | No       | Filter by chain ID |

**Returns:** `list[Position]`

### get\_user\_orders

Get all orders for a user.

| Parameter | Type  | Required | Description                                 |
| --------- | ----- | -------- | ------------------------------------------- |
| `address` | `str` | Yes      | User address                                |
| `status`  | `str` | No       | Filter: `"open"`, `"filled"`, `"cancelled"` |

**Returns:** `list[Order]`

### get\_user\_activity

Get trading activity summary for a user.

```python
activity = client.get_user_activity("0x...")

print(f"Total trades: {activity.total_trades}")
print(f"Total volume: {activity.total_volume / 1e6:.2f} USDC")
print(f"PNL: {activity.pnl / 1e6:.2f} USDC")
print(f"Markets traded: {activity.markets_traded}")
```

| Parameter | Type  | Required | Description  |
| --------- | ----- | -------- | ------------ |
| `address` | `str` | Yes      | User address |

**Returns:** `UserActivity`

### get\_user\_stats

Get statistics for the authenticated user.

```python
stats = client.get_user_stats()

print(f"Total cost: {stats.total_cost / 1e6:.2f} USDC")
print(f"Position value: {stats.position_value / 1e6:.2f} USDC")
print(f"PNL: {stats.pnl / 1e6:.2f} USDC ({stats.pnl_percentage:.1f}%)")
```

**Returns:** `UserStats`

***

## Gasless / Relayer Operations

These methods sign EIP-712 permits and submit them to the relayer for gasless execution. Requires Level 2 access (private key + API credentials). No native gas tokens are needed.

### approve\_usdc\_for\_settlement

Sign and submit a gasless max USDC permit. One-time per settlement contract — all future orders reuse the allowance.

```python
result = client.approve_usdc_for_settlement()
print(f"TX: {result}")

# With explicit settlement address
result = client.approve_usdc_for_settlement(
    settlement_address="0xdB96C91d9e5930fE3Ed1604603CfA4ece454725c"
)
```

| Parameter            | Type  | Required | Description                                    |
| -------------------- | ----- | -------- | ---------------------------------------------- |
| `settlement_address` | `str` | No       | Settlement contract (defaults to chain config) |

**Returns:** `dict` — Relayer response with `tx_hash`

### approve\_ctf\_for\_settlement

Sign and submit a gasless CTF `SetApprovalForAll` permit to let the settlement contract transfer your conditional tokens.

```python
result = client.approve_ctf_for_settlement()
```

| Parameter            | Type  | Required | Description                                    |
| -------------------- | ----- | -------- | ---------------------------------------------- |
| `settlement_address` | `str` | No       | Settlement contract (defaults to chain config) |

**Returns:** `dict` — Relayer response with `tx_hash`

### sign\_usdc\_permit

Sign an EIP-2612 permit for a specific USDC amount. Use this for per-order permits instead of the max permit.

```python
permit = client.sign_usdc_permit(
    value=10000000,  # $10 USDC
)

# Attach to a signed order before submission
signed_order.permit_signature = permit
result = client.post_order(signed_order)
```

| Parameter            | Type  | Required | Description                                         |
| -------------------- | ----- | -------- | --------------------------------------------------- |
| `value`              | `int` | Yes      | Amount to approve (6 decimals; `1000000` = $1 USDC) |
| `settlement_address` | `str` | No       | Spender address (defaults to chain config)          |
| `deadline`           | `int` | No       | Expiration timestamp (default: 1 hour from now)     |

**Returns:** `PermitSignature`

### approve\_usdc

On-chain USDC approval (requires native gas). Alternative to permit-based approval for high-frequency scenarios.

```python
tx_hash = client.approve_usdc(amount=2**256 - 1)  # Max approval
print(f"TX: {tx_hash}")
```

| Parameter | Type  | Required | Description                              |
| --------- | ----- | -------- | ---------------------------------------- |
| `amount`  | `int` | Yes      | Amount to approve (6 decimals)           |
| `spender` | `str` | No       | Spender address (defaults to settlement) |

**Returns:** `str` — Transaction hash

### get\_usdc\_allowance

Query the current USDC allowance for a spender.

```python
allowance = client.get_usdc_allowance()
print(f"Allowance: {allowance / 1e6:.2f} USDC")
```

| Parameter | Type  | Required | Description                               |
| --------- | ----- | -------- | ----------------------------------------- |
| `owner`   | `str` | No       | Token owner (defaults to signer address)  |
| `spender` | `str` | No       | Spender (defaults to settlement contract) |

**Returns:** `int` — Allowance in USDC (6 decimals)

### claim\_winnings

Claim winnings from a single resolved market via gasless permit.

```python
result = client.claim_winnings(
    market_contract_address="0xMarketContractAddress..."
)
print(f"TX: {result}")
```

This method:

{% stepper %}
{% step %}

### Query on-chain

Queries the market contract on-chain for resolution status and condition data.
{% endstep %}

{% step %}

### Check balance

Checks your balance of the winning token.
{% endstep %}

{% step %}

### Sign permit

Signs an EIP-712 `RedeemPositions` permit.
{% endstep %}

{% step %}

### Submit to relayer

Submits to the relayer for gasless execution.
{% endstep %}
{% endstepper %}

| Parameter                 | Type  | Required | Description                                   |
| ------------------------- | ----- | -------- | --------------------------------------------- |
| `market_contract_address` | `str` | Yes      | The market's contract address (not market ID) |

**Returns:** `dict` — Relayer response with `tx_hash`

**Raises:** `ValueError` if the market is not resolved or you have no winning tokens.

### batch\_claim\_winnings

Claim winnings from multiple resolved markets in a single batch transaction.

```python
result = client.batch_claim_winnings([
    "0xMarket1ContractAddress...",
    "0xMarket2ContractAddress...",
    "0xMarket3ContractAddress...",
])
print(f"TX: {result}")
```

Markets that are not resolved or where you have no winning tokens are skipped automatically.

| Parameter                   | Type        | Required | Description                       |
| --------------------------- | ----------- | -------- | --------------------------------- |
| `market_contract_addresses` | `list[str]` | Yes      | List of market contract addresses |

**Returns:** `dict` — Relayer response with `txHash`

### sync\_permit\_nonce

Resync the local permit nonce with the blockchain. Use after a permit failure or when nonces get out of sync.

```python
nonce = client.sync_permit_nonce()
print(f"On-chain nonce: {nonce}")
```

| Parameter          | Type  | Required | Description                       |
| ------------------ | ----- | -------- | --------------------------------- |
| `contract_address` | `str` | No       | Token contract (defaults to USDC) |

**Returns:** `int` — The current on-chain nonce

***

## Static Methods

### request\_api\_credentials

Register for API credentials by proving wallet ownership. This is a static method — no client instance needed.

```python
creds = TurbineClient.request_api_credentials(
    host="https://api.turbinefi.com",
    private_key="0xYourPrivateKey",
    name="my-trading-bot",  # optional
)

print(f"Key ID: {creds['api_key_id']}")
print(f"Private Key: {creds['api_private_key']}")
```

| Parameter     | Type  | Required | Description                   |
| ------------- | ----- | -------- | ----------------------------- |
| `host`        | `str` | Yes      | API base URL                  |
| `private_key` | `str` | Yes      | Wallet private key            |
| `name`        | `str` | No       | Friendly name for the API key |

**Returns:** `dict` with `api_key_id`, `api_private_key`, `message`

**Raises:** `TurbineApiError` with status `409` if the wallet already has a key.


---

# 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://docs.ojolabs.xyz/markets/api/python-sdk/client-reference.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.
