Pagination
The Lumar API uses cursor-based pagination for all connection fields. Every connection exposes the pageInfo object:
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
Where hasNextPage and hasPreviousPage will tell us whether there is a next or previous page or we hit the last or first one respectively.
On the other hand, startCursor and endCursor will give us cursor values for the start and end of the collection retrieved. These can be used as the after or before parameter in subsequent queries.
Pagination parameters
| Parameter | Type | Description |
|---|---|---|
first | Int | Return the first N items from the start of the set. Use with after. |
after | String | Cursor to start after (from endCursor). |
last | Int | Return the last N items from the end of the set. Use with before. |
before | String | Cursor to end before (from startCursor). |
Use first / after for forward pagination and last / before for backward pagination.
Forward pagination example
We run the following query:
- Query
- Response
- cURL
query firstPage {
me {
accounts(first: 1) {
nodes {
projects(first: 3) {
pageInfo {
hasNextPage
endCursor
}
nodes {
name
}
}
}
}
}
}
{
"data": {
"me": {
"accounts": {
"nodes": [
{
"projects": {
"pageInfo": {
"hasNextPage": true,
"endCursor": "Mw"
},
"nodes": [
{
"name": "Cool Project"
},
{
"name": "Deep Crawling"
},
{
"name": "Pro Ject"
}
]
}
}
]
}
}
}
}
curl -X POST -H "Content-Type: application/json" -H "apollographql-client-name: docs-example-client" -H "apollographql-client-version: 1.0.0" -H "x-auth-token: YOUR_API_SESSION_TOKEN" --data '{"query":"query firstPage { me { accounts(first: 1) { nodes { projects(first: 3) { pageInfo { hasNextPage endCursor } nodes { name } } } } } }"}' https://api.lumar.io/graphql
We can then get the second page with the query:
- Query
- Response
- cURL
query secondPage {
me {
accounts(first: 1) {
nodes {
projects(first: 3, after: "Mw") {
pageInfo {
hasNextPage
endCursor
}
nodes {
name
}
}
}
}
}
}
{
"data": {
"me": {
"accounts": {
"nodes": [
{
"projects": {
"pageInfo": {
"hasNextPage": true,
"endCursor": "Ng"
},
"nodes": [
{
"name": "Dev.io: Main"
},
{
"name": "Dev.io: Blog"
},
{
"name": "Some Project"
}
]
}
}
]
}
}
}
}
curl -X POST -H "Content-Type: application/json" -H "apollographql-client-name: docs-example-client" -H "apollographql-client-version: 1.0.0" -H "x-auth-token: YOUR_API_SESSION_TOKEN" --data '{"query":"query secondPage { me { accounts(first: 1) { nodes { projects(first: 3, after: \"Mw\") { pageInfo { hasNextPage endCursor } nodes { name } } } } } }"}' https://api.lumar.io/graphql
Backward pagination
You can also paginate backward from the end of a collection using last and before:
- Query
- Response
- cURL
query LastPageProjects {
me {
accounts(first: 1) {
nodes {
projects(last: 3) {
pageInfo {
hasPreviousPage
startCursor
}
nodes {
name
}
}
}
}
}
}
{
"data": {
"me": {
"accounts": {
"nodes": [
{
"projects": {
"pageInfo": {
"hasPreviousPage": true,
"startCursor": "OA"
},
"nodes": [
{
"name": "Final Project A"
},
{
"name": "Final Project B"
},
{
"name": "Final Project C"
}
]
}
}
]
}
}
}
}
curl -X POST -H "Content-Type: application/json" -H "apollographql-client-name: docs-example-client" -H "apollographql-client-version: 1.0.0" -H "x-auth-token: YOUR_API_SESSION_TOKEN" --data '{"query":"query LastPageProjects { me { accounts(first: 1) { nodes { projects(last: 3) { pageInfo { hasPreviousPage startCursor } nodes { name } } } } } }"}' https://api.lumar.io/graphql
To get the previous page, pass the startCursor value as the before parameter:
- Query
- Response
- cURL
query PreviousPageProjects {
me {
accounts(first: 1) {
nodes {
projects(last: 3, before: "OA") {
pageInfo {
hasPreviousPage
startCursor
}
nodes {
name
}
}
}
}
}
}
{
"data": {
"me": {
"accounts": {
"nodes": [
{
"projects": {
"pageInfo": {
"hasPreviousPage": true,
"startCursor": "NQ"
},
"nodes": [
{
"name": "Project D"
},
{
"name": "Project E"
},
{
"name": "Project F"
}
]
}
}
]
}
}
}
}
curl -X POST -H "Content-Type: application/json" -H "apollographql-client-name: docs-example-client" -H "apollographql-client-version: 1.0.0" -H "x-auth-token: YOUR_API_SESSION_TOKEN" --data '{"query":"query PreviousPageProjects { me { accounts(first: 1) { nodes { projects(last: 3, before: \"OA\") { pageInfo { hasPreviousPage startCursor } nodes { name } } } } } }"}' https://api.lumar.io/graphql
Pagination loop in TypeScript
For programmatic access, loop through all pages until hasNextPage is false:
async function fetchAllPages<T>(
queryFn: (cursor: string | null) => Promise<{
nodes: T[];
pageInfo: { hasNextPage: boolean; endCursor: string | null };
}>,
): Promise<T[]> {
const allNodes: T[] = [];
let cursor: string | null = null;
let hasNextPage = true;
while (hasNextPage) {
const page = await queryFn(cursor);
allNodes.push(...page.nodes);
hasNextPage = page.pageInfo.hasNextPage;
cursor = page.pageInfo.endCursor;
}
return allNodes;
}
Tips for large datasets
- Use a reasonable page size (50--500) depending on the number of fields requested.
- For very large exports (tens of thousands of records), consider using report downloads instead of paginating through the API.
- Include
totalCountin your first request to estimate the total number of pages. - Avoid combining
firstandlastin the same request -- use one direction at a time.