Hoppa till innehållet
Sursa Developers

Inkrementell synkning med updated_since

För att hålla en kopia av Sursas data i ditt eget system behöver du inte läsa allt varje gång. Listorna över objekt som har updated_at tar emot updated_since och returnerar bara de objekt som har ändrats vid eller efter den tidpunkten.

curl -G https://api.sursa.com/v1/cards \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  --data-urlencode "updated_since=2026-10-23T00:00:00Z" \
  --data-urlencode "limit=200"

Med updated_since sorteras listan stigande efter updated_at och sedan efter id, och markören fortsätter i den ordningen. Du läser alltså ändringarna i den ordning de gjordes, och en sidgräns delar aldrig upp dem så att någon går förlorad.

updated_since tas emot av de här listorna:

ListaVad som räknas som en ändring
GET /v1/cards, GET /v1/cards/countKortets updated_at.
GET /v1/groupsGruppens updated_at: dess rubrik eller inställningar.
GET /v1/webhooksWebhookens updated_at: dess inställningar och hemlighet, inte dess leveranser.
GET /v1/jobsJobbets updated_at: varje ändring av dess status.
GET /v1/draftsUtkastets updated_at.
GET /v1/cards/{card_id}/threadsDen senaste gången den första kommentaren eller något svar skapades eller redigerades. Tråden kommer i sin helhet.
GET /v1/folders, GET /v1/collections/{name}/foldersMappens updated_at. De matchande mapparna kommer som en platt lista, se nedan.

Samlingar, användare och meddelanden har inget updated_at, så deras listor filtrerar inte efter det: de är korta, så läs dem i sin helhet vid varje körning. Tidpunkten måste ha en tidszonsförskjutning, till exempel Z eller +02:00; varje annat värde avvisas, som med GET /v1/cards.

Med updated_since är ett mappträd inte längre ett träd: folders för varje samling innehåller de ändrade mapparna som en platt lista, med tomma children, och parent_id anger var var och en ligger. GET /v1/folders utelämnar då samlingarna utan ändrade mappar.

En synkningsloop

  1. Vid den första körningen läser du hela listan utan updated_since och sparar tidpunkten då körningen startade.
  2. Vid varje följande körning skickar du den sparade tidpunkten som updated_since, minus en liten marginal, till exempel en minut, och sparar den nya starttiden.
  3. Skriv varje objekt till din lagring med dess id som nyckel och ersätt den tidigare kopian. Objekt som kommer två gånger på grund av marginalen skrivs helt enkelt igen.
  4. Hämta varje nästa sida med markören och samma updated_since. En markör fungerar bara med filtren från den första sidan: utan dem returnerar anropet 400 med koden api.cursor_invalid.

Genom att använda körningens starttid, inte tiden då den blev klar, ser du till att en ändring som gjordes medan körningen pågick plockas upp av nästa körning.

GET /v1/cards returnerar en JSON-array, så dess nästa sida kommer i huvudet X-Next-Cursor (se Listor som returnerar en array):

const BASE = "https://api.sursa.com";
const headers = { Authorization: `Bearer ${process.env.SURSA_API_KEY}` };

async function syncCards(since, saveCard) {
  const startedAt = new Date();
  const params = new URLSearchParams({ limit: "200" });
  if (since) params.set("updated_since", new Date(since.getTime() - 60_000).toISOString());
  let query = params.toString();
  while (query) {
    const response = await fetch(`${BASE}/v1/cards?${query}`, { headers });
    if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
    for (const card of await response.json()) await saveCard(card); // write into your store by card.id
    const cursor = response.headers.get("X-Next-Cursor");
    if (cursor) params.set("cursor", cursor); // keep updated_since: the cursor needs the same filters
    query = cursor ? params.toString() : "";
  }
  return startedAt; // pass it as `since` next time
}

Borttagningar

En lista returnerar bara objekt som finns, så den kan inte berätta att något har tagits bort. Hämta borttagningar från händelseflödet:

curl -G https://api.sursa.com/v1/webhook-events \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  --data-urlencode "type=card.deleted" \
  --data-urlencode "created_since=2026-10-23T00:00:00Z"

För att läsa flödet behövs en nyckel med rollen admin och omfånget webhooks:manage. Händelser sparas i 30 dagar. Om din synkning inte har körts på längre tid än så läser du hela listan igen och tar bort varje objekt ur din lagring som inte längre finns i den.

Export till ett datalager samlar listor, updated_since och händelseflödet i ett och samma jobb.