Skip to content
GuidesBlogPlaygroundDashboard
Working with Data

Pagination

Navigate large result sets with cursor-based pagination and Link headers.

Plaza supports cursor-based and offset-based pagination. Cursor mode uses osm_id for efficient keyset pagination. Offset mode uses traditional LIMIT/OFFSET. If both are provided, cursor takes precedence.

List endpoints return a page of results and a Link header pointing to the next page:

Terminal window
curl -i -H "x-api-key: $PLAZA_API_KEY" \
"https://plaza.fyi/api/v1/features?around=48.85,2.34&radius=1000&tags[amenity]=cafe&limit=20"

Response headers:

X-Limit: 20
X-Has-More: true
X-Next-Cursor: 12345678
Link: </api/v1/features?around=48.85%2C2.34&radius=1000&tags[amenity]=cafe&limit=20&cursor=12345678>; rel="next"

When X-Has-More is false and the Link header is absent, you’ve reached the end.

ParameterTypeDefaultDescription
limitint20Results per page. Min 1, max 1,000.
cursorstringCursor from a previous Link header.
offsetint0Offset for offset-based pagination.

The Link header follows RFC 8288. The URL is in angle brackets, the relation type is after the semicolon.

import Plaza from "@plazafyi/sdk";
const plaza = new Plaza({ apiKey: process.env.PLAZA_API_KEY });
// The SDK handles pagination automatically
const allCafes = [];
for await (const page of plaza.nodes.list({
within: {
type: "Polygon",
coordinates: [[[2.2, 48.8], [2.5, 48.8], [2.5, 48.9], [2.2, 48.9], [2.2, 48.8]]],
},
tags: "amenity:cafe",
limit: 50,
})) {
allCafes.push(...page.features);
}
console.log(`Found ${allCafes.length} cafes`);
import plaza
client = plaza.Client(api_key="your-key")
# The SDK auto-paginates
all_cafes = list(client.nodes.list(
within={
"type": "Polygon",
"coordinates": [[[2.2, 48.8], [2.5, 48.8], [2.5, 48.9], [2.2, 48.9], [2.2, 48.8]]],
},
tags="amenity:cafe",
limit=50,
))
package main
import (
"context"
"fmt"
"github.com/plazafyi/plaza-go"
)
func main() {
client := plaza.NewClient(plaza.WithAPIKey("your-key"))
iter := client.Nodes.List(context.Background(), &plaza.NodeListParams{
Within: &plaza.Geometry{
Type: "Polygon",
Coordinates: [][][2]float64{{{2.2, 48.8}, {2.5, 48.8}, {2.5, 48.9}, {2.2, 48.9}, {2.2, 48.8}}},
},
Tags: plaza.String("amenity:cafe"),
Limit: plaza.Int(50),
})
var count int
for iter.Next() {
page := iter.Current()
count += len(page.Features)
}
if err := iter.Err(); err != nil {
panic(err)
}
fmt.Printf("Found %d cafes\n", count)
}

Cursors are stable until the next data update (daily for OSM, varies for other datasets). After an update, old cursors return 400 — start from the first page.

This only matters for long-running pagination jobs. A few thousand results will finish well before the next update.

HeaderDescription
X-LimitThe page size used for this request.
X-Has-Moretrue if there are more results, false if this is the last page.
X-Next-CursorThe cursor value for the next page (cursor mode only).
X-Next-OffsetThe offset for the next page (offset mode only).
LinkRFC 8288 link to the next page (absent on the last page).