> For the complete documentation index, see [llms.txt](https://knowledgebase.flaik.com/flaik-knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://knowledgebase.flaik.com/flaik-knowledge-base/for-it-specialists/3.-flaik-connect-api/overview/pagination-and-delta-sync.md).

# Pagination and Delta Sync

Some flaik Connect endpoints come in pairs: a **full pull** for an initial load, and a **delta pull** for incremental sync afterwards. Both are paginated with the same cursor pattern, so once you understand one pair you understand them all.

Today this pattern applies to:

* [Shift Data By Season](https://knowledgebase.flaik.com/flaik-knowledge-base/for-it-specialists/3.-flaik-connect-api/schedule/shift-data-by-season)
* [Task Data By Season](https://knowledgebase.flaik.com/flaik-knowledge-base/for-it-specialists/3.-flaik-connect-api/schedule/task-data-by-season)

This page is the shared reference for the cursor mechanics, the timestamp-boundary rules, and the recommended client loop. The endpoint pages cover what each record contains and what makes that endpoint specific — they link here for the rest.

## Full pull vs delta pull

|                           | Full pull                      | Delta pull                                                   |
| ------------------------- | ------------------------------ | ------------------------------------------------------------ |
| Route shape               | `GET …/{seasonId}`             | `GET …/{seasonId}/delta`                                     |
| Use case                  | Initial load, complete re-sync | Ongoing incremental sync                                     |
| `updatedAfterUtcDateTime` | Not accepted                   | **Required**                                                 |
| Soft-deleted records      | Excluded                       | Included (so you can tombstone them)                         |
| Cursor                    | `nextAfterId` only             | `nextAfterId` **and** `nextUpdatedAfterUtcDateTime` together |

A typical client lifecycle is:

1. Run the **full pull** once to seed your store.
2. Record the timestamp at which you finished.
3. From then on, run the **delta pull** on a schedule, passing the last successful sync time.

## Page size

| Parameter  | Type    | Required | Description                                                                         |
| ---------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `pageSize` | integer | No       | Records per page. Default and maximum: `1000`. Values outside `1–1000` are clamped. |

Every paged endpoint returns at most `pageSize` records and tells you whether more remain via `hasMore`. There is no way to fetch more than 1,000 records in a single call.

## The cursor

Every paged response includes the cursor for the **next** request, so clients don't need to inspect individual records.

| Response field                | Notes                                                                                                                |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `hasMore`                     | `true` if further pages exist for this query. Loop until this is `false`.                                            |
| `pageSize`                    | The page size that was applied to this response.                                                                     |
| `nextAfterId`                 | Pass this back as the `nextAfterId` query parameter on the next call. `null` when `hasMore` is `false`.              |
| `nextUpdatedAfterUtcDateTime` | **Delta pull only.** Pass this back as `updatedAfterUtcDateTime` on the next call. `null` when `hasMore` is `false`. |

### Full pull — single-axis cursor

The full pull is ordered by record `id` and uses a single cursor: `nextAfterId`.

```
GET /api/schedule/tasks/18
  → hasMore: true,  nextAfterId: 1000,  data: [records 1–1000]

GET /api/schedule/tasks/18?nextAfterId=1000
  → hasMore: true,  nextAfterId: 2000,  data: [records 1001–2000]

GET /api/schedule/tasks/18?nextAfterId=2000
  → hasMore: false, nextAfterId: null,  data: [records 2001–2247]
  → Done
```

### Delta pull — compound cursor

The delta pull is ordered by `(updatedUtc, id)` and uses **both** cursor fields. You must pass them together.

```
GET /api/schedule/tasks/18/delta?updatedAfterUtcDateTime=2025-01-01T00:00:00Z
  → hasMore: true,  nextAfterId: 50500,
                    nextUpdatedAfterUtcDateTime: "2025-01-10T14:22:00Z"

GET /api/schedule/tasks/18/delta
        ?updatedAfterUtcDateTime=2025-01-10T14:22:00Z&nextAfterId=50500
  → hasMore: false, nextAfterId: null,
                    nextUpdatedAfterUtcDateTime: null
  → Done
```

## Why the delta needs two cursors

`updatedUtc` has **one-second resolution**. Bulk scheduling actions — mass publish, schedule import, employee assignment to a class — can produce many records that share the same second.

If a page break lands inside one of those clusters, a single timestamp cursor would force a choice between losing records and re-emitting them. The compound `(updatedUtc, id)` cursor avoids both:

* The server orders by `updatedUtc` first, then by `id` as a tiebreaker.
* "Next page starts after `(nextUpdatedAfterUtcDateTime, nextAfterId)`" gives a precise restart point even mid-second.

{% hint style="warning" %}
**Always pass both `nextUpdatedAfterUtcDateTime` and `nextAfterId` together when paging a delta result.** Sending just one can either skip records that share the boundary second or return them twice.
{% endhint %}

## Loop pattern

The same loop works for any paged endpoint.

{% tabs %}
{% tab title="Full pull" %}

```
GET …/{seasonId}                              # first page, no cursor
loop while hasMore:
    GET …/{seasonId}?nextAfterId={nextAfterId}
```

{% endtab %}

{% tab title="Delta pull" %}

```
GET …/{seasonId}/delta?updatedAfterUtcDateTime={lastSuccessfulSync}

loop while hasMore:
    GET …/{seasonId}/delta
        ?updatedAfterUtcDateTime={nextUpdatedAfterUtcDateTime}
        &nextAfterId={nextAfterId}
```

{% endtab %}
{% endtabs %}

When the delta loop finishes, persist the timestamp of the moment your sync **started** (not the last `nextUpdatedAfterUtcDateTime` you saw — that's an internal page boundary, not a watermark) and use it as `updatedAfterUtcDateTime` for the next sync run.

## Tombstones

The full pull only returns active records (`deleted: false`). The delta pull includes deleted records (`deleted: true`) so that clients can detect deletions and remove them locally.

* On a delta page, treat each record with `deleted: true` as "this record was removed in flaik" and delete it from your store.
* A record can appear on multiple delta pulls if it has been edited multiple times since the last sync — apply the most recent state. Records are uniquely identified by their endpoint-specific id (e.g. `shiftId`, `taskAssignmentId`).

## Recovery — what to do when state is lost

If your sync state is lost or corrupted (for example a clean redeploy without persistence), the safest reset is:

1. Clear or quarantine the local store for that season.
2. Run the **full pull** again to reseed.
3. Record the start time of the full pull and resume **delta pulls** from there.

You do not need to retain or replay individual `nextAfterId` cursors across runs — they only have meaning within a single paging loop.

## Error responses

| HTTP Status | Endpoint   | Description                                             |
| ----------- | ---------- | ------------------------------------------------------- |
| `400`       | Both       | The supplied `seasonId` does not exist for this resort. |
| `400`       | Delta only | `updatedAfterUtcDateTime` was not provided.             |
| `401`       | Both       | Missing or invalid access token.                        |

See [Authentication](https://knowledgebase.flaik.com/flaik-knowledge-base/for-it-specialists/3.-flaik-connect-api/overview/authentication) for token acquisition.

## Common pitfalls

* **Forgetting `nextAfterId` on a delta continuation.** Sending only `updatedAfterUtcDateTime` between pages can skip or duplicate records at the boundary second. Always pass both.
* **Using `nextUpdatedAfterUtcDateTime` as your sync watermark.** It's a page-boundary value, not a "last sync time". Use the timestamp at which your sync started.
* **Looping on the full pull and expecting deletions.** The full pull never returns soft-deleted records. Switch to the delta pull as soon as you have an initial seed.
* **Assuming `pageSize` smaller than 1000 reduces server load.** It only changes how many records you get per call — total work is the same, more round-trips are usually slower. Use the default unless you have a memory constraint on the client.

Need help? Contact <resortsupport@flaik.com>.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://knowledgebase.flaik.com/flaik-knowledge-base/for-it-specialists/3.-flaik-connect-api/overview/pagination-and-delta-sync.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
