Incremental sync

Embed
Preview of the card
<a href="https://forumulate.com/reference/incremental-sync"><img src="https://forumulate.com/reference/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/8042f004-e3d9-445f-b7a4-b6c1f86836e6/pages/6cfe3e8c-8298-49f7-842d-28eccc26e516/social-card.svg?v=3e7ae33eec8b" alt="Incremental sync" width="600" height="315"></a>

Ask for what changed, not for everything.

The loop

GET /api/orgs/{orgId}/spaces/{spaceId}/items?updated_since=2026-08-18T03:00:00Z&include_deleted=true&limit=200
{
  "items": [
    { "id": "item_912", "updatedAt": "2026-08-18T04:12:09Z", "contentHash": "9f86d081884c7d659a2f" },
    { "id": "item_733", "updatedAt": "2026-08-18T04:41:55Z", "deleted": true }
  ],
  "page": { "has_more": false, "next_cursor": null, "limit": 200, "total": 2 },
  "sync": { "checkpoint": "2026-08-18T04:41:55Z" }
}

Store sync.checkpoint verbatim and pass it back as updated_since next time. The server defines the watermark so you never have to reason about clock skew or about the window between a write landing and becoming visible.

Deletions

include_deleted=true returns a tombstone — { id, updatedAt, deleted: true } — for anything removed in the last 30 days. Without tombstones you cannot tell "this was deleted" from "this was not in my window", and you would have to do a full list anyway. If you have been away longer than 30 days, reconcile with a full list.

Content, without a second request

include=sections folds the markdown per named slot into every row; include=body folds in the whole piece as markdown. fields=id,title,updatedAt trims what comes back — id always survives.

A 400-page space costs 4 requests, not 401.

Diffing without transferring

Every row carries contentHash, a hash of the content itself rather than of a row version, so a save that changed nothing does not invalidate your cache. Compare hashes to decide what to fetch. A single item read also carries an ETag: send it back as If-None-Match and an unchanged piece answers 304 with no body.

The Forumulate teamUpdated