Pagination
Relay cursor-based pagination
Pagination
List endpoints in the API use Relay cursor-based pagination. This provides stable, efficient pagination over large datasets.
Connection shape
Paginated results follow the Relay connection pattern:
type AccountConnection {
nodes: [Account]!
edges: [AccountEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type AccountEdge {
cursor: String!
node: Account!
}
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}| Field | Description |
|---|---|
nodes | Flat array of items on the current page |
edges | Array of { cursor, node } pairs |
pageInfo | Pagination metadata |
totalCount | Total number of items across all pages |
Forward pagination
Use first and after to paginate forward:
query Accounts($first: Int!, $after: String) {
accounts(first: $first, after: $after) {
edges {
cursor
node {
id
status
}
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}First page — omit after:
{ "first": 20 }Next page — pass endCursor from the previous response as after:
{ "first": 20, "after": "YXJyYXljb25uZWN0aW9uOjIw" }Stop when pageInfo.hasNextPage is false.
Backward pagination
Use last and before to paginate backward. Do not combine first with last in the same request.
query Accounts($last: Int!, $before: String) {
accounts(last: $last, before: $before) {
edges {
cursor
node { id }
}
pageInfo {
hasPreviousPage
startCursor
}
}
}Example: paginate through all accounts
async function fetchAllAccounts(client: GraphQLClient) {
const accounts = [];
let cursor: string | null = null;
let hasNextPage = true;
while (hasNextPage) {
const { data } = await client.query({
query: ACCOUNTS_QUERY,
variables: { first: 50, after: cursor },
});
for (const edge of data.accounts.edges) {
accounts.push(edge.node);
}
hasNextPage = data.accounts.pageInfo.hasNextPage;
cursor = data.accounts.pageInfo.endCursor;
}
return accounts;
}Tips
- Use
nodeswhen you only need the items (simpler). Useedgeswhen you need cursors for pagination. - Page sizes of 20–50 are typical. Very large
firstvalues may hit complexity limits. - Cursors are opaque strings — do not parse or construct them manually.
Updated about 2 months ago
Did this page help you?

