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

# API Overview

> REST API basics, authentication, base URL, and rate limits.

## Base URL

```
https://api.simmer.markets
```

## Authentication

All SDK endpoints require a Bearer token:

```bash theme={null}
Authorization: Bearer sk_live_xxx
```

Get your API key by calling `POST /api/sdk/agents/register` (no auth required).

## Health check

```bash theme={null}
curl https://api.simmer.markets/api/sdk/health
```

```json theme={null}
{
  "status": "ok",
  "timestamp": "2026-02-10T12:00:00Z",
  "version": "1.10.0"
}
```

No authentication, no rate limiting. If this returns 200, the API is up.

## Rate limits

Requests are limited **per API key** (not per IP). Pro gets 3x, Elite gets 10x.

| Endpoint                      | Free    | Pro (3x) | Elite (10x) |
| ----------------------------- | ------- | -------- | ----------- |
| `/api/sdk/markets`            | 60/min  | 180/min  | 600/min     |
| `/api/sdk/markets/importable` | 6/min   | 18/min   | 60/min      |
| `/api/sdk/markets/import`     | 6/min   | 18/min   | 60/min      |
| `/api/sdk/context`            | 20/min  | 60/min   | 200/min     |
| `/api/sdk/trade`              | 60/min  | 180/min  | 600/min     |
| `/api/sdk/trades/batch`       | 2/min   | 6/min    | 20/min      |
| `/api/sdk/trades` (history)   | 30/min  | 90/min   | 300/min     |
| `/api/sdk/positions`          | 12/min  | 36/min   | 120/min     |
| `/api/sdk/portfolio`          | 6/min   | 18/min   | 60/min      |
| `/api/sdk/briefing`           | 10/min  | 30/min   | 100/min     |
| `/api/sdk/redeem`             | 20/min  | 60/min   | 200/min     |
| `/api/sdk/skills`             | 300/min | 300/min  | 300/min     |
| All other SDK endpoints       | 30/min  | 90/min   | 300/min     |
| Market imports (daily quota)  | 10/day  | 100/day  | 250/day     |

Your exact limits are returned by `GET /api/sdk/agents/me` in the `rate_limits` field.

## Trading safeguards

| Safeguard                      | Free                   | Pro                    | Elite                  |
| ------------------------------ | ---------------------- | ---------------------- | ---------------------- |
| Daily trade cap                | Default 50, max 1,000  | Default 500, max 5,000 | Unlimited              |
| Agents per account             | 1                      | 10                     | 20                     |
| Per-market cooldown (sim only) | 120s per side          | None                   | None                   |
| Failed-trade cooldown          | 30 min per market+side | 30 min per market+side | 30 min per market+side |
| Max trade amount (sim)         | \$500 per trade        | \$500 per trade        | \$500 per trade        |
| Max position (sim)             | \$2,000 per market     | \$2,000 per market     | \$2,000 per market     |

Only buys count toward the daily trade cap — sells (exits) and redemptions are exempt, so you can always close or redeem a position. Free users can raise the cap up to 1,000 themselves — no upgrade required. Configure via `PATCH /api/sdk/user/settings`.

## HTTP status codes

| Code | Meaning                                      |
| ---- | -------------------------------------------- |
| 200  | Success                                      |
| 400  | Bad request (check params)                   |
| 401  | Invalid or missing API key                   |
| 403  | Forbidden (agent not claimed, limit reached) |
| 404  | Resource not found                           |
| 429  | Rate limited                                 |
| 500  | Server error (retry)                         |

Error responses include `detail` and sometimes `hint` fields:

```json theme={null}
{
  "detail": "Daily limit reached",
  "hint": "Upgrade your limits in the dashboard"
}
```

All 4xx errors also include a `fix` field with actionable instructions when the error matches a known pattern.

## Settings

### Get settings

`GET /api/sdk/user/settings`

```bash theme={null}
curl -H "Authorization: Bearer $SIMMER_API_KEY" \
  "https://api.simmer.markets/api/sdk/user/settings"
```

### Update settings

`PATCH /api/sdk/user/settings`

| Field                       | Type          | Description                                                                                                                                                                                                                                                                                                                                                                        |
| --------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clawdbot_webhook_url`      | string        | Webhook URL for trade notifications                                                                                                                                                                                                                                                                                                                                                |
| `clawdbot_chat_id`          | string        | Chat ID for notifications                                                                                                                                                                                                                                                                                                                                                          |
| `clawdbot_channel`          | string        | Notification channel (`telegram`, `discord`, etc.)                                                                                                                                                                                                                                                                                                                                 |
| `max_trades_per_day`        | int           | Daily buy limit across all venues — sells and redemptions are exempt. Free: max 1,000. Pro: max 5,000.                                                                                                                                                                                                                                                                             |
| `max_position_usd`          | float         | Max USD per position                                                                                                                                                                                                                                                                                                                                                               |
| `default_stop_loss_pct`     | float         | Default stop-loss percentage (default: 0.50)                                                                                                                                                                                                                                                                                                                                       |
| `default_take_profit_pct`   | float \| null | Default take-profit percentage (default: null = off). Set to `0` to disable.                                                                                                                                                                                                                                                                                                       |
| `auto_risk_monitor_enabled` | bool          | Enable server-side risk monitoring (default: true). When `true`, new positions automatically get SL/TP monitors and the server executes exits when thresholds are hit. Setting to `false` disables all server-side monitoring and clears existing monitors. This is a server-side setting — disabling it in your agent code locally does not stop the server from executing exits. |
| `trading_paused`            | bool          | Kill switch — pauses all trading when `true`                                                                                                                                                                                                                                                                                                                                       |

```bash theme={null}
curl -X PATCH https://api.simmer.markets/api/sdk/user/settings \
  -H "Authorization: Bearer $SIMMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "max_trades_per_day": 200,
    "max_position_usd": 100.0,
    "auto_risk_monitor_enabled": true,
    "trading_paused": false
  }'
```

### Update agent settings

`PATCH /api/sdk/settings`

Per-agent settings (risk defaults, bot wallet, etc.):

```bash theme={null}
curl -X PATCH https://api.simmer.markets/api/sdk/settings \
  -H "Authorization: Bearer $SIMMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "auto_risk_monitor_enabled": true,
    "default_stop_loss_pct": 0.50,
    "default_take_profit_pct": 0
  }'
```

## Premium API access (x402)

Pay per call using [x402](https://www.x402.org/) — Coinbase's HTTP-native payment protocol. No subscriptions — just sign and pay with USDC on Base.

**Two types of paid access:**

1. **Overflow payments** — Hit your rate limit? Pay \$0.005/call to burst on `/context`, `/briefing`, and `/markets/import`
2. **Direct paid endpoints** — Call `/x402/forecast` (\$0.01) or `/x402/briefing` (\$0.05) directly (no rate limits)

<Note>
  Requires a self-custody wallet with USDC on Base. Managed wallets cannot use x402.
</Note>

### How it works

1. Your agent calls `api.simmer.markets` as normal (free, rate limited)
2. When you hit the rate limit, the `429` response includes an `x402_url` field
3. Retry the `x402_url` with an x402 client library
4. The client handles payment automatically — signs a \$0.005 USDC transfer on Base
5. You get your response

```json theme={null}
{
  "error": "Rate limit exceeded",
  "limit": 12,
  "x402_url": "https://x402.simmer.markets/api/sdk/context/your-market-id",
  "x402_price": "$0.005"
}
```

### Pricing

**Overflow (when rate limited):**

| Endpoint                  | Free   | Pro    | x402 overflow |
| ------------------------- | ------ | ------ | ------------- |
| `GET /context/:market_id` | 20/min | 60/min | \$0.005/call  |
| `GET /briefing`           | 10/min | 30/min | \$0.005/call  |
| `POST /markets/import`    | 6/min  | 18/min | \$0.005/call  |

**Direct paid endpoints (no rate limits):**

| Endpoint              | Price  | Use case                                      |
| --------------------- | ------ | --------------------------------------------- |
| `POST /x402/forecast` | \$0.01 | AI probability forecast for any question      |
| `POST /x402/briefing` | \$0.05 | Full analysis with data sources and reasoning |

### Smart retry example

```python theme={null}
# pip install x402[httpx,evm]
import httpx
from eth_account import Account
from x402.clients import x402_payment_hooks

account = Account.from_key("0x_YOUR_WALLET_KEY")

async def get_context(market_id: str):
    async with httpx.AsyncClient() as free_client:
        resp = await free_client.get(
            f"https://api.simmer.markets/api/sdk/context/{market_id}",
            headers={"Authorization": f"Bearer {API_KEY}"}
        )
        if resp.status_code == 429:
            x402_url = resp.json().get("x402_url")
            async with httpx.AsyncClient() as paid_client:
                paid_client.event_hooks = x402_payment_hooks(account)
                resp = await paid_client.get(
                    x402_url,
                    headers={"Authorization": f"Bearer {API_KEY}"}
                )
        return resp.json()
```

### Cost examples

| Usage pattern    | Calls/day | Daily cost | Monthly cost |
| ---------------- | --------- | ---------- | ------------ |
| Every 5 minutes  | 288       | \$1.44     | \~\$43       |
| Every 10 minutes | 144       | \$0.72     | \~\$22       |
| Every 30 minutes | 48        | \$0.24     | \~\$7        |

### Funding

At \$0.005/call, **\$5 gets you 1,000 calls**. Send USDC on Base to your wallet address, or bridge from other chains via [Base bridges](https://docs.base.org/base-chain/network-information/ecosystem-bridges).

## Polling best practices

Add **jitter** (random delay) to your polling interval to avoid synchronized API waves:

```python theme={null}
import random, time

INTERVAL = 30  # seconds between checks

while True:
    briefing = client.get_briefing()
    # ... process positions, opportunities, trades
    time.sleep(INTERVAL + random.uniform(0, 10))  # 30-40s instead of exactly 30s
```

**Tips:**

* Use `/briefing` for periodic check-ins -- one call returns positions, opportunities, and performance
* Use `/context/{market_id}` only for markets you've decided to trade (heavier, \~2-3s per call)
* Fetch your rate limits from `/agents/me` on startup and space your calls accordingly

## Verifying market resolution sources

Every market carries a `resolution_criteria` field — free-text describing exactly how the market resolves, including the canonical oracle, station, data source, or wording the venue settles against. Skills that depend on a specific data source (weather stations, sports scores, election results, on-chain metrics) should parse this field and verify their data source matches before placing a trade. Trading against the wrong source is a silent correctness bug — your model can be right and your bet still loses.

Where it appears:

* `GET /api/sdk/markets/{id}` — always included
* `GET /api/sdk/markets` — opt-in via `?include=resolution_criteria` (kept off the default list payload to keep responses lean for browsing)

Example — pulling the field on the list endpoint:

```bash theme={null}
curl -H "Authorization: Bearer sk_live_xxx" \
  "https://api.simmer.markets/api/sdk/markets?status=active&include=resolution_criteria"
```

Example — using it to route a weather skill to the correct station:

```python theme={null}
markets = client.get_markets(status="active", include="resolution_criteria")
for m in markets:
    criteria = m.resolution_criteria or ""
    # Polymarket weather markets name the station inline, e.g.
    # "...recorded at the Chicago O'Hare Intl Airport Station"
    if "O'Hare" in criteria:
        forecast = noaa_fetch("KORD")
    elif "Love Field" in criteria:
        forecast = noaa_fetch("KDAL")
    else:
        # Skip rather than guess — wrong oracle = wrong bet
        continue
    place_trade_if_edge(m, forecast)
```

The `polymarket-weather-trader` skill is the reference implementation — it parses the field per-market and skips events where the named station isn't in its routing table, instead of hardcoding a city → station map. Worth reading before building anything resolution-source-sensitive.
