> ## Documentation Index
> Fetch the complete documentation index at: https://docs.andteam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination and syncing

> Cursors, and reading only what changed since your last read.

## Pages

Every list takes `limit` (1 to 500, default 100) and `cursor`, and answers:

```json theme={null}
{ "data": [ { "id": "…" } ], "next_cursor": "eyJ1IjoiMjAyNy0w…" }
```

Pass `next_cursor` as `cursor` to read the next page. It is `null` on the last page. There is no
total and no offset. **The cursor is opaque**: do not build or parse one. A cursor that andteam did
not issue answers `invalid-parameter`.

```javascript theme={null}
async function readAll(path, key) {
  const out = [];
  let cursor = null;
  do {
    const url = new URL(`https://api.v3.andteam.com/v1${path}`);
    url.searchParams.set("limit", "500");
    if (cursor) url.searchParams.set("cursor", cursor);
    const res = await fetch(url, { headers: { Authorization: `Bearer ${key}` } });
    if (!res.ok) throw new Error(await res.text());
    const page = await res.json();
    out.push(...page.data);
    cursor = page.next_cursor;
  } while (cursor);
  return out;
}
```

## Nothing is skipped while you page

Lists that change (employees, positions, time off and events) are read in the order records **last
changed**. A record that changes while you page moves to the end and is read again there, so a page
never skips it and never repeats it out of order. Small configuration lists (companies, locations,
lookups and org units) page by id.

## Changed since

To stay in step with andteam, read everything once, then read again with `updated_since` set to the
time **your last full read began**, not when it ended:

1. Note the time. Read every page of `GET /v1/employees`.
2. Later, note the time again. Read `GET /v1/employees?updated_since=<the earlier time>`.
3. Apply what comes back, by `id`. Repeat from step 2.

`updated_since` takes an ISO 8601 instant and returns records changed after it. Starting the window
at the beginning of the previous read means a record that changed during that read is read again, not
lost. Applying it by `id` makes reading it twice harmless.

`GET /v1/time-off` takes `updated_since` too. An absence that was approved and then withdrawn or
cancelled is returned with status `cancelled`, inside the window of its change, so you can remove it.
`GET /v1/events` takes `since`, which filters on when the event became readable.

## Filters

| Endpoint | Filters |
| - | - |
| `GET /v1/employees` | `status` (`upcoming`, `active` or `left`), `company_id`, `employee_number`, `work_email`, `updated_since` |
| `GET /v1/time-off` | `company_id`, `updated_since` |
| `GET /v1/events` | `type`, `company_id`, `since` |
| `GET /v1/lookups/{type}` | `type` is `departments`, `cost-centres`, `grades` or `job-titles` |

A `company_id` the key does not hold answers `company-not-allowed`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.