# Incremental sync

To keep a copy of your orders without reading all of them every time, ask [`GET /v1/orders`](https://docs.rephut.com/developers/reference/orders#list-orders) only for the orders that changed.

## How it works

`GET /v1/orders?updatedSince=<time>` returns the orders whose `updatedAt` is at or after that time. The list is still sorted by creation time, newest first, and paged as usual. You can combine it with `status`.

`updatedSince` is an ISO 8601 date-time with a time zone, for example `2026-11-01T00:00:00Z`. Encode `+` in an offset as `%2B`: `2026-11-01T08:00:00%2B08:00`.

## The recipe

1. Note the current time **before** you request page 1. Call it `started`.
2. Read every page with the same `updatedSince`. The first time, leave `updatedSince` out to read everything.
3. Save each order by `id`, replacing the copy you had.
4. Next time, use `started` minus a safety margin of a few minutes as `updatedSince`.

The margin covers clock differences and orders that changed while you were reading. You will see some orders again; that is expected: match them on `id`.

## Things to know

- Any edit through [`PATCH /v1/orders/{id}`](https://docs.rephut.com/developers/reference/orders#change-an-order-that-needs-attention), including a change to the lines only, changes `updatedAt`, so the next `updatedSince` read picks it up.
- Purchase orders, shipments, requests and quotes have no `updatedSince`. Use webhooks and fetch the resource with `GET`, or re-read the first pages of the list (newest first). Re-reading the first pages only finds new purchase orders, shipments and requests, because lists sort by creation time; for changes to older ones use webhooks plus `GET`.
- Webhooks usually tell you about a change within a minute. Polling with `updatedSince` is a good safety net next to them: see [Keep your orders in sync](https://docs.rephut.com/developers/guides/sync-orders).

## Example

```js
import { readFile, writeFile } from "node:fs/promises";

const MARGIN_MS = 5 * 60 * 1000;
const state = JSON.parse(await readFile("sync-state.json", "utf8").catch(() => "{}"));
const started = new Date();
const orders = new Map(Object.entries(state.orders ?? {}));

for (let page = 1; ; page += 1) {
  const query = new URLSearchParams({ page: String(page), ...(state.updatedSince ? { updatedSince: state.updatedSince } : {}) });
  const response = await fetch(`https://api.rephut.com/v1/orders?${query}`, { headers: { Authorization: `Bearer ${process.env.FULFILLBOT_API_KEY}` } });
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  const { data, meta } = await response.json();
  for (const order of data) orders.set(order.id, order);
  if (data.length === 0 || page >= meta.pageCount) break;
}

const updatedSince = new Date(started.getTime() - MARGIN_MS).toISOString();
await writeFile("sync-state.json", JSON.stringify({ updatedSince, orders: Object.fromEntries(orders) }));
console.log(orders.size, "orders saved; next updatedSince:", updatedSince);
```

The list endpoint returns order summaries. Fetch [`GET /v1/orders/{id}`](https://docs.rephut.com/developers/reference/orders#get-an-order) for the full order, such as the recipient, fulfilment and charges.
