Skip to Content

Pagination

Every list pages by cursor.

Lists return at most limit items (default 100 on most routes, maximum 1000). When there are more, meta holds a next_cursor. Pass it back as cursor to get the next page, until next_cursor is null.

"meta": { "limit": 100, "next_cursor": "eyJvIjoxMDB9", "total": 412 }

Treat the cursor as opaque. Pass it back exactly as you received it, with the same filters. A cursor from another list is a 400 invalid_cursor.

import os
import requests

session = requests.Session()
session.headers.update({
    "Authorization": f"Bearer {os.environ['OPENGRID_API_KEY']}",
    "OpenGrid-Version": "2026-11-03",
})

def all_rows(path, **params):
    cursor = None
    while True:
        r = session.get(f"https://data.tryopengrid.com{path}",
                        params={**params, "limit": 1000, "cursor": cursor}, timeout=60)
        r.raise_for_status()
        body = r.json()
        yield from body["data"]
        cursor = body["meta"].get("next_cursor")
        if not cursor:
            return

listings = list(all_rows("/v1/listings", gpu="nvidia-h100-80gb-sxm5"))

Two kinds of cursor

  • Reference lists (GPUs, providers, markets) are small and change slowly. Their cursor is a position in the list, and meta.total is the full count.
  • Time-ordered feeds (listing changes, capacity changes, events, news, fixings) are newest first. Their cursor marks the last row you saw, so pages stay stable while new rows arrive.

To get everything for a past day in one file, use bulk exports instead.

On this page