---
title: "Pagination — GanttFather API"
description: "How large task lists page, and how to detect a torn multi-page read."
canonical: "https://ganttfather.com/docs/api/pagination/"
locale: "en"
category: "product"
---

# Pagination — GanttFather API

API reference [AI assistants (MCP)](https://ganttfather.com/docs/ai-agent/)

## Getting started

- [Introduction](https://ganttfather.com/docs/api/introduction/)
- [Authentication](https://ganttfather.com/docs/api/authentication/)
- [Pagination](https://ganttfather.com/docs/api/pagination/)
- [Rate limits & quotas](https://ganttfather.com/docs/api/rate-limits/)
- [Errors](https://ganttfather.com/docs/api/errors/)

## Projects

- [GET List projects](https://ganttfather.com/docs/api/list-projects/)
- [GET Get project](https://ganttfather.com/docs/api/get-project/)

## Tasks

- [GET List tasks](https://ganttfather.com/docs/api/list-tasks/)
- [GET Get task](https://ganttfather.com/docs/api/get-task/)
- [POST Create task](https://ganttfather.com/docs/api/create-task/)
- [PATCH Update task](https://ganttfather.com/docs/api/update-task/)
- [DELETE Delete task](https://ganttfather.com/docs/api/delete-task/)
- [POST Reorder tasks](https://ganttfather.com/docs/api/reorder-tasks/)
- [PUT Set assignees](https://ganttfather.com/docs/api/set-assignees/)

## Dependencies

- [GET List dependencies](https://ganttfather.com/docs/api/list-dependencies/)
- [PUT Set dependencies](https://ganttfather.com/docs/api/set-dependencies/)
- [POST Add dependency](https://ganttfather.com/docs/api/add-dependency/)
- [DELETE Remove dependency](https://ganttfather.com/docs/api/remove-dependency/)

## Resources

- [GET List resources](https://ganttfather.com/docs/api/list-resources/)
- [POST Create resource](https://ganttfather.com/docs/api/create-resource/)
- [PATCH Update resource](https://ganttfather.com/docs/api/update-resource/)
- [DELETE Delete resource](https://ganttfather.com/docs/api/delete-resource/)

## Members

- [GET List members](https://ganttfather.com/docs/api/list-members/)

 Getting started / **Pagination**

# Pagination

 Updated Jul 4, 2026

## Overview

 Most collections in the API — projects, members, resources, dependencies — come back as their full set in one response; none of those grow large enough to need paging. Task lists are the exception, since a project can hold thousands of tasks.

## Supported endpoints

 Only one endpoint pages today:

- [List tasks →](https://ganttfather.com/docs/api/list-tasks/) — GET /v1/projects/{projectId}/tasks

 Everything else (list projects, list members, list resources, list dependencies) returns its full set in a single response, unpaged.

## Parameters

 Pass these as query parameters on a paginated request:

 Parameter Type Default Notes

 page integer 1 1-indexed — the first page is page=1 , not page=0 .

 pageSize integer — Maximum 500 .

 curl "https://api.ganttfather.com/v1/projects/{projectId}/tasks?page=1&pageSize=200" \
 -H "Authorization: Bearer glt_YOUR_TOKEN"

## Response format

 The response body is a plain JSON array of that page’s tasks — no envelope, no cursor object. The full-collection count comes back on the X-Total-Count response header instead.

 To read every task, loop page upward while requesting the same pageSize , and stop once you’ve read X-Total-Count rows:

 page = 1
 fetched = 0
 while fetched < X-Total-Count:
 rows = GET tasks?page={page}&pageSize=200
 fetched += rows.length
 page += 1

 Note that X-Total-Count is CORS-exposed, so client-side JavaScript can read it directly without a proxy.

## Torn reads

 Paging is not a point-in-time snapshot: if the project is edited while you loop, the pages you stitch together may not represent one consistent state.

 Don’t try to detect this by comparing ETag s across pages. Each page’s ETag is computed from that page’s own rows, so different pages always carry different ETag s even when the project is completely stable — a cross-page comparison would flag every normal multi-page read as torn. The ETag is only for [conditional re-polling](https://ganttfather.com/#best-practices) of a single page.

 Instead, watch X-Total-Count . It comes back on every page and reflects the whole collection. If the count changes between the first and last page of a loop, a task was added or removed while you were paging — discard the result and re-run the loop once. (A stable count won’t catch a pure in-place edit, but it does catch the structural changes that shuffle rows across page boundaries.)

## Best practices

- **Use a stable pageSize ** for the life of one loop — changing it mid-loop makes X-Total-Count bookkeeping unreliable.

- **Send If-None-Match ** with the ETag from your last read of a page; an unchanged page answers 304 Not Modified with an empty body, so re-polling is cheap.

- **Stop at X-Total-Count **, not at an empty page — the count is authoritative and known up front.

- **Re-run the loop once if X-Total-Count moves** mid-loop, rather than surfacing a partial result to your integration’s user.

 See [Rate limits & quotas →](https://ganttfather.com/docs/api/rate-limits/) for the full caching contract.
