Incremental sync
To keep a copy of your orders without reading all of them every time, ask GET /v1/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
- Note the current time before you request page 1. Call it
started. - Read every page with the same
updatedSince. The first time, leaveupdatedSinceout to read everything. - Save each order by
id, replacing the copy you had. - Next time, use
startedminus a safety margin of a few minutes asupdatedSince.
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}, including a change to the lines only, changesupdatedAt, so the nextupdatedSinceread picks it up. - Purchase orders, shipments, requests and quotes have no
updatedSince. Use webhooks and fetch the resource withGET, 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 plusGET. - Webhooks usually tell you about a change within a minute. Polling with
updatedSinceis a good safety net next to them: see Keep your orders in sync.
Example
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} for the full order, such as the recipient, fulfilment and charges.