Pagination
List endpoints (maps, markers, and marker search) return results in pages using an opaque keyset cursor. Cursor paging stays fast and stable at any depth — important because a single map can hold tens of thousands of markers.
The model
Each list response carries a page_info object:
{
"markers": [ /* … up to page_size items … */ ],
"page_info": {
"total_count": 4210,
"next_page_token": "eyJpZCI6ODgzNDEwMjd9"
}
}
| Field | Type | Meaning |
|---|---|---|
next_page_token |
string | null | Opaque cursor for the next page. null means you’ve reached the last page. |
total_count |
integer | null | Best-effort total of matching items. May be null when computing it would be too expensive — treat it as a hint, never a loop condition. |
Parameters
| Query param | Default | Notes |
|---|---|---|
page_size |
100 |
Items per page. Clamped to a maximum of 1000 — larger values are silently reduced. |
page_token |
— | The next_page_token from the previous response. Omit it for the first page. |
The token is opaque: don’t decode, construct, or mutate it. Pass back exactly what you received.
Walking every page
Fetch the first page, then keep following next_page_token until it comes back null.
TOKEN=""
while : ; do
RESP=$(curl -s "$ZM_API/maps/$ZM_MAP/markers?page_size=500${TOKEN:+&page_token=$TOKEN}" \
-H "Authorization: Bearer $ZM_KEY")
echo "$RESP" | jq '.markers[]'
TOKEN=$(echo "$RESP" | jq -r '.page_info.next_page_token // empty')
[ -z "$TOKEN" ] && break
done
The same shape applies to GET /maps,
GET /maps/{map_id}/markers,
and GET /maps/{map_id}/markers/search.
Tips
- Don’t rely on
total_countto terminate. Loop onnext_page_token == null; it is the authoritative end-of-results signal even whentotal_countisnull. - Pick a large
page_size(up to 1000) for bulk reads to cut round-trips and stay well under your rate limit. - Tokens are tied to a query. Keep the other parameters (filters,
page_size) stable across a paging loop; changing them mid-walk invalidates the cursor’s meaning.