# Get calibration

Source: https://langbot.ai/docs/api/research/get-calibration

`GET /v1/research/calibration`

How the venue's opening prices compared with settlement over every settled market the filters keep, by price bucket, with intervals.

**Auth.** An API token: `Authorization: Bearer lb_…` ([create one](https://langbot.ai/app/tokens)). Signed-in web sessions work too.

**Limits.** One history query per call (500 a day on Free; unlimited on Builder and Standard).

## Parameters

### Query parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `speaker` | string | no | A canonical speaker key. |
| `series` | string | no | A venue series ticker. |
| `category` | string | no | A category. |
| `phrase` | string | no | A normalized phrase key. |
| `venue` | string | no | `kalshi` or `polymarket`. |
| `since` | integer | no | ms epoch, by settlement time. |
| `until` | integer | no | ms epoch, by settlement time. |
| `min_volume` | integer | no | Leave out markets with less volume. |
| `basis` | string | no | `mid` (the first two-sided mid, default) or `trade` (the first trade, which the caveats explain). |
| `buckets` | integer | no | Number of equal-width price buckets. 2 to 20. Default `10`. |
| `test_fraction` | number | no | Share of markets, by settlement time, held out as the later split. Default `0.3`. |

## Request

**curl**

```bash
curl "https://api.langbot.ai/v1/research/calibration?speaker=powell&basis=mid" \
  -H "Authorization: Bearer $LANGBOT_API_TOKEN"
```

**Python**

```python
from langbot import LangbotClient

async with LangbotClient() as lb:  # reads LANGBOT_API_TOKEN
    cal = await lb.calibration(speaker="powell", basis="mid")
    print(cal["n"], cal["overall"])
```

**TypeScript**

```ts
const res = await fetch("https://api.langbot.ai/v1/research/calibration?speaker=powell&basis=mid", {
  headers: { Authorization: `Bearer ${process.env.LANGBOT_API_TOKEN}` },
});
console.log(await res.json());
```

## Response

`200 OK`

```json
{
  "v": 1,
  "basis": "mid",
  "buckets": 10,
  "n": 214,
  "by_bucket": [ { "bucket": 1, "lo_c": 10, "hi_c": 20, "n": 31, "avg_price_c": 14.6, "yes_rate": 0.161, "yes_rate_ci90": [0.08, 0.29], "gap_c": 1.5, "brier": 0.134, "p_value": 0.71 } ],
  "overall": { "n": 214, "gap_c": -0.8, "gap_ci90_clustered": [-4.1, 2.6], "brier": 0.151 },
  "split": { "test_fraction": 0.3, "train": { "n": 150 }, "test": { "n": 64 } },
  "trials": { "count_30d": 4 },
  "caveats": ["mid basis: the first two-sided mid"]
}
```

Every figure has its sample size and a 90% interval, with Benjamini-Hochberg control across buckets. Each query is written to your [trials ledger](https://langbot.ai/docs/api/research/list-trials). Measurements, never signals.

## Errors

| Status | `code` | When |
|---|---|---|
| 401 | `auth_required` | No token was sent. |
| 401 | `token_invalid` | The token was not recognised (mistyped, revoked or expired). |
| 422 | `validation_error` | A parameter failed validation; `detail[].loc` names it. |
| 429 | `quota_exceeded` | Today's history queries are spent; `quota.resets_at` says when they reset. |
| 429 | `rate_limited` | Over your request budget; wait `Retry-After` seconds. |

Every error body is `{"detail": …, "code": "…"}`; branch on `code`. All codes: [Errors](https://langbot.ai/docs/api#errors).
