HollyHR Developer Docs
  • HollyHR
  • Sign in
  • Manage API keys
  • Start Here
  • Core API
  • AI and MCP
  • API Reference
  • Recipes
  • Resources
RequestsPagination examplesEnvironments and testingWebhooksProvider readinessOpenAPI imports
Core API

Pagination examples

Use this guide when you are writing a sync job rather than testing a single request in the API reference.

Cursor helper

Cursor values are opaque. Store or replay them exactly as returned, and do not decode or construct them.

Code
const baseUrl = process.env.HOLLYHR_API_BASE_URL; const token = process.env.HOLLYHR_API_TOKEN; async function holly(path) { const response = await fetch(`${baseUrl}${path}`, { headers: { Authorization: `Bearer ${token}`, Accept: "application/json", }, }); if (response.status === 429 || response.status >= 500) { throw new Error(`Retry the same page later: ${response.status}`); } if (!response.ok) { throw new Error(`HollyHR API failed: ${response.status}`); } return response.json(); } async function* pages(path) { let cursor; do { const separator = path.includes("?") ? "&" : "?"; const page = await holly( `${path}${cursor ? `${separator}cursor=${encodeURIComponent(cursor)}` : ""}`, ); yield page; cursor = page.pagination?.next_cursor; } while (cursor); }

Retry the current page on 429 or 5xx. For incremental sync, advance your watermark only after every page in the run has completed.

People sync

Use updated_since for polling jobs. Persist the maximum updated_at seen only after the full paginated run completes.

Code
let maxUpdatedAt = "2026-06-16T09:00:00.000Z"; for await (const page of pages( `/people?limit=100&updated_since=${encodeURIComponent(maxUpdatedAt)}`, )) { for (const person of page.data) { await upsertPerson(person); if (person.updated_at > maxUpdatedAt) { maxUpdatedAt = person.updated_at; } } } await savePeopleWatermark(maxUpdatedAt);

Time-off windows

Time-off list reads should be bounded by a date window. Combine the window with status or person filters when you can.

Code
for await (const page of pages( "/time-off?limit=100&from=2026-07-01&to=2026-07-31&status=approved", )) { for (const request of page.data) { await upsertTimeOff(request); } }

Use updated_since for reconciliation jobs that need changes since the last run. Keep the date window if the downstream system only needs a bounded calendar range.

Document metadata

Document endpoints return metadata only. They do not return document bytes or download URLs.

Code
for await (const page of pages("/documents?limit=50&updated_since=2026-06-16T09%3A00%3A00.000Z")) { for (const document of page.data) { await upsertDocumentMetadata(document); } }

Provider mappings

Provider mappings are useful when reconciling remote identifiers. They require provider_mappings:read plus the relevant resource read scope.

Code
for await (const page of pages("/provider-mappings?limit=100&provider_name=merge")) { for (const mapping of page.data) { await linkRemoteObject(mapping); } }

Webhook delivery logs

Delivery logs are paginated independently per webhook endpoint. Use filters to review failures or retry queues.

Code
for await (const page of pages( "/webhooks/{webhookId}/deliveries?limit=50&status=failed&event_type=person.updated&created_since=2026-06-21T00%3A00%3A00.000Z", )) { for (const delivery of page.data) { await inspectDelivery(delivery); } }

Use the redelivery action only after you have fixed the receiver problem that caused the delivery to fail.

Non-paginated collections

Some endpoints return small full collections under data and do not include a pagination object. Examples include /organisation/locations, /org-units, /working-patterns, /custom-fields, /public-holidays, and /reference/* dictionaries. Treat those responses as a single page.

Single-resource endpoints, such as GET /people/{personId} or GET /webhooks/{webhookId}/deliveries/{deliveryId}, also do not paginate.

Last modified on June 24, 2026
RequestsEnvironments and testing
On this page
  • Cursor helper
  • People sync
  • Time-off windows
  • Document metadata
  • Provider mappings
  • Webhook delivery logs
  • Non-paginated collections
Javascript
Javascript
Javascript
Javascript
Javascript
Javascript