---
title: Paging & bulk export
description: Page through results with next links or startIndex, and export in bulk by windowing on observed_at.
---

## Page size

**`limit` is capped at 10,000** features per request; a larger value is silently clamped
to 10,000.

## Paging

Page through larger result sets by following the **`next` link** in each response, or
with `startIndex`:

```bash
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/ogc/features/v1/collections/deepfire:hotspots/items?limit=1000&startIndex=1000&f=application/geo%2Bjson"
```

:::caution[No total count in responses]
Responses **do not include `numberMatched`**. To page reliably, keep requesting until a
page returns **fewer than `limit`** features (or zero) — never rely on a total.
:::

**Avoid deep offsets.** Very large `startIndex` values (hundreds of thousands and up) are
slow and will hit the 30-second query limit. For anything bulk-sized, window by time
instead.

## Bulk export: window by `observed_at`

Request successive closed time windows via CQL, paging within each window. Windows keep
every `startIndex` shallow, so each request stays fast:

```python
import os
import requests

BASE = "https://api.deepfire.co/ogc/features/v1"
# See /guides/authentication.
HEADERS = {"Authorization": f"Bearer {os.environ['DEEPFIRE_TOKEN']}"}

def fetch_window(collection, start, end, page_size=10_000):
    """All features with observed_at in [start, end), paging within the window."""
    features, start_index = [], 0
    while True:
        r = requests.get(
            f"{BASE}/collections/{collection}/items",
            headers=HEADERS,
            params={
                "f": "application/geo+json",
                "limit": page_size,
                "startIndex": start_index,
                "filter-lang": "cql2-text",
                "filter": (
                    f"observed_at >= TIMESTAMP('{start}') "
                    f"AND observed_at < TIMESTAMP('{end}')"
                ),
            },
            timeout=60,
        )
        r.raise_for_status()
        page = r.json()["features"]
        features.extend(page)
        if len(page) < page_size:
            return features
        start_index += page_size

# One day at a time
day = fetch_window(
    "deepfire:hotspots", "2026-07-01T00:00:00Z", "2026-07-02T00:00:00Z"
)
print(len(day), "hotspots")
```

Pick a window size that keeps each window to a handful of pages (a day of global hotspots
is a reasonable starting point; shrink the window for busy periods).

