Pagination
The Buffer API uses cursor-based pagination for queries that return lists of items. Here's how to page through results.
How it works
Rather than using page numbers, the Buffer API uses cursor strings to track your position in a result set. You request a batch of items, receive a cursor pointing to the last item, then pass that cursor to fetch the next batch.
This means you won't skip or duplicate results if new items are added between requests.
Basic query structure
Paginated queries use three key arguments:
first- how many items to return (the page size)after- the cursor to start from (omit for the first page)input- filters for the query
And the response includes:
edges- the list of items, each wrapped in anodepageInfo- pagination metadata
query {
posts(
first: 20,
input: {
organizationId: "your_org_id",
filter: { status: [sent] }
}
) {
edges {
node {
id
text
dueAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Reading the response
The pageInfo object tells you about pagination state:
hasNextPage-trueif there are more items after this batchendCursor- the cursor of the last item, used to fetch the next pagestartCursor- the cursor of the first itemhasPreviousPage- currently alwaysfalse(only forward pagination is supported)
Fetching the next page
To get the next page, pass the endCursor from the previous response as the after argument:
query {
posts(
first: 20,
after: "cursor_from_previous_response",
input: {
organizationId: "your_org_id",
filter: { status: [sent] }
}
) {
edges {
node {
id
text
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Tips
- Choose an appropriate page size. A
firstvalue of 20–50 works well for most use cases. Larger pages mean fewer requests but larger responses. - Don't parse cursors. Cursors are opaque strings. Store them and pass them back as-is.
- Respect rate limits. When fetching many pages, be mindful of the rate limits. Consider adding a small delay between requests if needed.
Filtering
Most paginated queries support filtering via the input.filter object. Filters are combined with AND logic - all conditions must match.
query {
posts(
first: 20,
input: {
organizationId: "your_org_id",
filter: {
status: [scheduled],
channelIds: ["your_channel_id", "your_other_channel_id"]
}
}
) {
edges { node { id text channelId } }
pageInfo { hasNextPage endCursor }
}
}
This returns only scheduled posts from the specified channels.
Next steps
- Get Paginated Posts: working pagination example
- API Limits: rate limiting and query constraints
- Posts & Scheduling: more about working with posts