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

# Incremental synchronization

> Pull changed Matter status using a stable updatedSince cursor and opaque page tokens.

Use the list endpoint to pull partner-visible Matter changes. It returns a minimized **current-state projection**, not an event log.

## Request

```bash theme={null}
printf 'oauth2-bearer = "%s"\n' "$CASE_PATH_IQ_API_KEY" | \
curl --disable --config - \
  --url "$CASE_PATH_IQ_BASE_URL/v1/matters?clientCode=SDCC&updatedSince=2026-09-01T00:00:00Z&limit=100"
```

| Query parameter | Required | Meaning |
| - | - | - |
| `clientCode` | Yes | A Client granted to the authenticated Source integration |
| `updatedSince` | Yes | Inclusive ISO 8601 UTC lower bound — the `syncedThrough` from your last completed run |
| `pageToken` | No | Opaque continuation token from the previous page |
| `limit` | No | Default 100; maximum 200 |

Missing, invalid or future `updatedSince` returns `400 invalid_field`.

## Response

```json theme={null}
{
  "matters": [
    {
      "matterId": "mat_01JEXAMPLE",
      "clientReferenceId": "SDCC-2026-00482",
      "clientCode": "SDCC",
      "etag": "\"m1-7f3a9c2b\"",
      "status": "paused",
      "intakeStatus": "ready",
      "outstandingBalance": "1050.00",
      "currency": "EUR",
      "lifecycle": {
        "hold": "paused",
        "reason": "payment_arrangement",
        "effectiveOn": "2026-08-27"
      },
      "payments": {
        "totalPaymentsAmount": "200.00",
        "totalRefundsAmount": "0.00",
        "totalReversalsAmount": "0.00",
        "lastObservation": {
          "externalPaymentId": "payobs_01JEXAMPLE",
          "type": "payment",
          "amount": "200.00",
          "effectiveOn": "2026-08-27"
        }
      },
      "updatedAt": "2026-09-01T11:12:00Z"
    }
  ],
  "nextPageToken": null,
  "syncedThrough": "2026-09-02T01:58:00Z"
}
```

Each sync item contains only the fields needed to reconcile operational state. It excludes Party identity, addresses, contacts, instructions, Source revisions, staff notes, and internal workflow data.

| Field | What it answers |
| - | - |
| `lifecycle` | *Why* this Matter stopped. `hold` is `none`, `paused` or `closed`; `reason` and `effectiveOn` echo the accepted pause or close command, and are `null` while no partner hold is active |
| `payments` | *What money has been observed.* Observation totals for payments, refunds and reversals, plus `lastObservation` (or `null`). These are observation totals, not a payment history and not a reconciliation statement |
| `etag` | *Whether anything you hold is stale.* Equal to your stored tag means skip the detail read; it is also the `If-Match` value for your next write |

Because a paused or closed Matter arrives with its reason attached, a nightly run reconciles stopped files straight from the list page instead of issuing a second request per Matter.

> [!NOTE]
>
> Party identity, addresses and contacts are deliberately kept out of list pages — a nightly catch-up should not move personal data it does not need. Use `etag` to find the Matters that actually changed, then GET only those for the full representation.

A partner-visible *next planned action* is not part of v1. It needs an agreed Workflow Action vocabulary that does not exist yet, and a planned action would not be a promise of dispatch.

## The run boundary

You never have to reason about clocks. CasePath IQ tells you how far each run covered, and you hand that value straight back next time.

```
Run 1  updatedSince=2026-09-01T01:58:00Z  →  … →  syncedThrough=2026-09-02T01:58:00Z
                                                        │  store it
Run 2  updatedSince=2026-09-02T01:58:00Z  ←─────────────┘
```

`syncedThrough` appears **only on the final page** of a run — the page where `nextPageToken` is `null` — and is `null` on every earlier page. That is deliberate: if a run fails half way through, there is no boundary for you to save, so the next run safely re-reads the same window instead of skipping it.

It is returned even when `matters` is empty, so a quiet night still moves you forward.

> [!NOTE]
>
> The value is held a little behind real time. A Matter's `updatedAt` is set inside the write transaction but only becomes visible when that transaction commits, so a boundary set at "now" could skip a Matter that was mid-commit — permanently, because nothing would ever bump its `updatedAt` again. Holding the boundary back keeps it clear of that window.
>
> This is why you should **not** add an overlap, a skew allowance, or a safety margin of your own. Send `syncedThrough` back exactly as given. The lag is ours to maintain, and its size may change.

## Recommended sync loop

**1. Choose the lower bound**

Use the `syncedThrough` you stored after your last completed run, or the initial UTC boundary agreed during onboarding. Nothing else — not your own clock, not the response time, not the greatest `updatedAt` you saw.

**2. Read the first page**

Send `clientCode`, `updatedSince`, and an optional `limit`. Omit `pageToken`.

**3. Apply current state**

Reconcile each item by `matterId`. Because this is current state rather than an event stream, repeated items are safe to apply again.

A sync item is a summary projection, not the Matter. It carries no `parties`, `debt` or `instruction`, so writing it over a stored full Matter would erase those fields. Either keep sync items in their own synchronization projection, or merge each one into what you hold without removing the fields it does not carry.

Compare each item's `etag` with the tag you stored for that Matter. Unchanged means nothing you hold is stale, so skip the detail read. Changed means GET the Matter, and store that full representation together with the `etag` the GET returned — it is also the `If-Match` value for your next write.

**4. Follow every page**

While `nextPageToken` is not `null`, send it unchanged and keep the original Client, lower bound, and limit. A token is bound to the integration, Client, filter, and snapshot watermark.

**5. Advance after the final page**

Once every page has been applied successfully, save the final page's `syncedThrough` as your new boundary. If the run failed or was abandoned, save nothing and repeat the same `updatedSince` next time — re-reading is always safe, because each item is current state rather than an event.

Store the boundary and the applied rows together, so a crash can never leave you with an advanced boundary and unapplied data.

Results are ordered by `updatedAt` ascending and then `matterId` ascending, so a batch of Matters sharing one timestamp pages cleanly and never straddles a page edge unpredictably. Do not parse, modify, or reuse a page token with another Client or filter, and keep one boundary per Client — a `syncedThrough` from one Client's run means nothing for another.

Because `updatedSince` is inclusive, a Matter sitting exactly on the boundary may arrive twice across consecutive runs. Upserting it again is a no-op, and its `etag` will be unchanged, so there is nothing to reconcile.

## What changes `updatedAt`

`updatedAt` advances when partner-visible state changes through:

* A materially different Matter PUT or PATCH
* A first accepted Payment observation
* An accepted lifecycle operation
* A CasePath IQ workflow or intake transition

An identical retry does not advance `updatedAt`.

## When to use GET one

Use the list endpoint for catch-up and reconciliation. Use GET one by client reference ID or `matterId` when you need the full partner-facing Source representation, including `parties`, debt, instruction, and server-owned state identifiers — normally only for the Matters whose `etag` changed.

> [!NOTE]
>
> Do not treat the list as a complete audit history. Multiple changes between sync runs may appear as one latest current-state item.

## Next

* [Understand identifiers and ownership](https://docs.casepathiq.com/concepts.md)
* [Read the full Matter representation](https://docs.casepathiq.com/matters.md#responses-and-concurrency)
* [Handle rate and transient failures](https://docs.casepathiq.com/errors-and-retries.md)


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