prizepicksapi

Pagination

Paginate the PrizePicks API with cursors.

Every list endpoint returns one bounded page and a continuation cursor. Read this before counting a board, building an export, or resuming a stopped job.

The contract in one table

EndpointCursor typeWhere the next cursor is
GET /api/v1/projectionsOpaque token (letters, digits, _ and -)meta.next_cursor
GET /api/v1/projections/{id}/historyNumeric sequencemeta.next_cursor
GET /api/v1/changesNumeric sequencemeta.next_cursor, and each event’s cursor
GET /api/v1/exportOpaque tokenX-Next-Cursor response header (empty when done)

Send the value back as cursor. The changes and history endpoints also accept after as an alias, which reads naturally for a feed. Sending both cursor and after, or repeating any parameter, returns 400. A cursor longer than 200 characters or in the wrong format for the endpoint is also rejected.

Walk every page with curl and jq

#!/usr/bin/env bash
set -euo pipefail
cursor=""
: > nba.jsonl
while :; do
  page=$(curl -fsS "https://prizepicksapi.com/api/v1/projections?league=NBA&limit=200${cursor:+&cursor=$cursor}" \
    -H "Authorization: Bearer $PRIZEPICKS_API_KEY")
  echo "$page" | jq -c '.data[]' >> nba.jsonl
  next=$(echo "$page" | jq -r '.meta.next_cursor // empty')
  [ -z "$next" ] && break
  [ "$next" = "$cursor" ] && { echo "repeated cursor" >&2; exit 1; }
  cursor=$next
  sleep 6.1
done
echo "status: $(echo "$page" | jq -r .meta.source_status)  rows: $(wc -l < nba.jsonl)"

Each page is one metered request. With limit=200, a 1,000-record board takes five requests; with the default 50 it takes twenty. The pause keeps one serial loop under the Free plan’s per-minute limit. Paid plans allow higher rates, but a loop should still stop on a repeated cursor.

Keep filters identical across pages

A cursor continues a specific filtered collection. If page one used league=NBA&stat=Points, every following page must send the same league, stat, search, tier, and status values. Changing a filter mid-traversal does not raise an error, but the result combines two different collections and is hard to reason about.

A traversal is not a point-in-time snapshot

Each page is evaluated when you request it. With the default status=active, a record must appear in the latest successful collection for its scope and have been confirmed within ten minutes. If a collection finishes while you are paging, later pages reflect the new state. For a consistent dataset, record meta.observed_at on every page and discard or re-run a traversal whose pages straddle different collection times.

Resume a stopped job

  • Projections: there is no durable position worth keeping across hours. Restart from the first page; the board may have changed.
  • Changes: persist the last processed event’s cursor after your work commits, then resume with after=that value. Events are replayable.
  • History: per projection, keep the last entry id and continue with cursor when you need newer entries.
  • Export: treat each CSV page like a projections page and keep the X-Next-Cursor value only for the current run.

Frequently asked questions

Can I request page 5 directly?

No. There is no offset or page-number parameter. Pages are reached by following next_cursor from the previous page.

What is the maximum page size?

limit accepts integers from 1 to 200. The default is 50. Values outside that range return 400 invalid_query.

References

Current API documentation ↗Machine-readable OpenAPI contract ↗

PrizePicks API is an independent data service. It is not affiliated with or endorsed by PrizePicks. Observations, completeness, and freshness are separate claims; consult source status before relying on a stored line.