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

# Delta polling (updates)

> Don't reload the whole board — fetch only the odds that changed.

Reloading the whole board on every request is wasteful. Instead you open a **session**: one snapshot to establish your baseline, then deltas against it.

1. **`/api/snapshot`** returns the current state and gives you a `token`. This is where you declare your scope.
2. **`/api/updated?since=<token>`** returns only the **rows that changed** since that token, plus a fresh token for the next call.

`/api/updated` never returns a snapshot — without a `since` it answers `400`. The two jobs are deliberately separate: an endpoint called *updated* that hands back the entire book would be surprising, and expensive.

```bash theme={null}
# 1) open the session — the token is issued here
curl https://api.apinn.io/api/snapshot -H "X-API-Key: YOUR_KEY"
# → { "snapshot": true, "token": "2026-07-24T15:36:48", "count": 33572, "odds": [ ... ] }

# 2) then poll for deltas, sending back the last token you received
curl "https://api.apinn.io/api/updated?since=2026-07-24T15:36:48" -H "X-API-Key: YOUR_KEY"
# → { "snapshot": false, "token": "2026-07-24T15:37:12", "window_seconds": 25, "count": 168, "odds": [ ... ] }
```

The `window_seconds` field tells you how much time your delta covered — handy to pace your polling.

## Scoping your session

The snapshot call is also where you say **what your session is about**. Add any of `sport_id`, `league_id`, `event_id`, `market` or `period` (comma-separated lists are accepted): the snapshot is limited to that scope, and the token you receive **carries the scope with it**.

From then on you send the token alone. The server knows which base to compute the delta against, and your scope cannot drift mid-session because you forgot a parameter.

```bash theme={null}
# 1) the snapshot sets the scope
curl "https://api.apinn.io/api/snapshot?sport_id=29&market=moneyline&period=0" -H "X-API-Key: YOUR_KEY"
# → { "snapshot": true, "token": "v1.eyJ0cyI6...", "scope": { "sports": [29], "markets": ["moneyline"], "periods": [0] }, "count": 510, ... }

# 2) the token alone is enough — no need to repeat the filters
curl "https://api.apinn.io/api/updated?since=v1.eyJ0cyI6..." -H "X-API-Key: YOUR_KEY"
# → { "snapshot": false, "scope": { ... }, "count": 3, "odds": [ ... ] }
```

Every response echoes `scope`, so you can always see what your token means. To change scope, open a new session with a new snapshot.

## What it costs

A call costs **1 + the number of rows returned**. Frequency is nearly free; volume is what you pay for. Two consequences are worth planning around.

Scope is the main lever on your bill. Measured on the live book, a moneyline / full-time scope is around 5% of all movements — so roughly 5% of the cost of following everything. Your snapshot is billed the same way, which is the other reason to scope it: a full-book snapshot is over 20,000 rows.

Polling faster does not get you fresher data for free. A price that moves five times in thirty seconds appears **once** in a 30-second delta and up to five times at 5-second intervals, because the cursor tracks each market's last real change. Faster polling buys granularity, not freshness.

<Note>
  Keep the last `token` you received and send it back on every call. Tokens are opaque — treat them as a cursor, not as a timestamp you can compute.
</Note>

<Tip>
  If you want a scope continuously rather than on a timer, the [WebSocket stream](/en/concepts/websocket) is far cheaper: the connection costs **1 request**, once, and takes the same filters as a subscription.
</Tip>
