# Pagination Guide - Cursor-Based Batching
URL: https://sockodds.com/docs/guides/data-batches/

# Pagination Guide - Cursor-Based Batching [#pagination-guide---cursor-based-batching]

This applies to `/events/`, `/teams/`, `/players/` and `/markets/`. Other endpoints always return every result that matches your query.

## How it works [#how-it-works]

1. Make a request. Each request has a limit on the number of items returned.
2. If there are more items, you get a `nextCursor` in the response.
3. Repeat the query with that value in the `cursor` parameter.
4. Repeat until `nextCursor` is null.

## The cursor parameter [#the-cursor-parameter]

- Always use the value from the last response's `nextCursor`. Don't reverse-engineer it.
- Don't change any other query parameters between cursor requests.
- Percent-encode the cursor — some ids contain non-ASCII characters.

## The limit parameter [#the-limit-parameter]

- `/events`: default 10, max 100.
- `/teams` and `/players`: default 50, max 250.
- `/markets`: default 100, max 10,000.

## Example [#example]

Grab every unfinalized NRL event:

**JavaScript** · **Python** · **Ruby** · **PHP** · **Java**

```javascript
const allEvents = []; let cursor = null;
do {
  const url = new URL("https://api.sockodds.com/v2/events");
  url.search = new URLSearchParams({ leagueID: "NRL", finalized: "false", limit: "100", ...(cursor ? { cursor } : {}) });
  const r = await fetch(url, { headers: { "x-api-key": KEY } });
  const body = await r.json();
  allEvents.push(...body.data); cursor = body.nextCursor;
} while (cursor);
console.log(`Found ${allEvents.length} events`);
```

```python
import requests
all_events, cursor = [], None
while True:
    r = requests.get("https://api.sockodds.com/v2/events", params={"leagueID": "NRL", "finalized": "false", "limit": 100, **({"cursor": cursor} if cursor else {})}, headers={"x-api-key": KEY})
    r.raise_for_status(); body = r.json()
    all_events.extend(body["data"]); cursor = body.get("nextCursor")
    if not cursor: break
print(f"Found {len(all_events)} events")
```

```ruby
require "net/http"; require "json"
all = []; cursor = nil
loop do
  uri = URI("https://api.sockodds.com/v2/events"); uri.query = URI.encode_www_form({ leagueID: "NRL", finalized: false, limit: 100, cursor: cursor }.compact)
  req = Net::HTTP::Get.new(uri); req["x-api-key"] = KEY
  body = JSON.parse(Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }.body)
  all.concat(body["data"]); cursor = body["nextCursor"]; break unless cursor
end
```

```php
$all = []; $cursor = null;
do {
  $params = ['leagueID' => 'NRL', 'finalized' => 'false', 'limit' => 100]; if ($cursor) $params['cursor'] = $cursor;
  $ch = curl_init("https://api.sockodds.com/v2/events?" . http_build_query($params));
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: $KEY"]);
  $body = json_decode(curl_exec($ch), true); curl_close($ch);
  $all = array_merge($all, $body['data']); $cursor = $body['nextCursor'] ?? null;
} while ($cursor);
```

```java
List<JsonObject> all = new ArrayList<>(); String cursor = null;
do {
  String url = "https://api.sockodds.com/v2/events?leagueID=NRL&finalized=false&limit=100" + (cursor != null ? "&cursor=" + URLEncoder.encode(cursor, "UTF-8") : "");
  HttpRequest req = HttpRequest.newBuilder().uri(URI.create(url)).header("x-api-key", KEY).GET().build();
  JsonObject body = JsonParser.parseString(client.send(req, HttpResponse.BodyHandlers.ofString()).body()).getAsJsonObject();
  body.getAsJsonArray("data").forEach(e -> all.add(e.getAsJsonObject()));
  cursor = body.has("nextCursor") && !body.get("nextCursor").isJsonNull() ? body.get("nextCursor").getAsString() : null;
} while (cursor != null);
```

> SockOdds noteWithout a date window, `eventID`, `finalized` or `includeFinished=true`, events that kicked off more than 24 hours ago are omitted from listings — the source never prunes finished events, so this keeps the default page current.

> Need help?[FAQ](https://sockodds.com/docs/faq/) · [Email](mailto:api@sockodds.com) · [Contact](https://sockodds.com/contact-us/)
