Gå til indholdet
Sursa Developers

Inkrementel synkronisering med updated_since

Når du vil holde en kopi af Sursas data i dit eget system, behøver du ikke læse alt hver gang. Listerne over objekter, der har updated_at, accepterer updated_since og returnerer kun de objekter, der er ændret på eller efter dette tidspunkt.

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 sorteres listen stigende efter updated_at og derefter efter id, og cursoren fortsætter i samme rækkefølge. Du læser altså ændringerne i den rækkefølge, de skete i, og en sidegrænse deler dem aldrig på en måde, så en ændring går tabt.

updated_since accepteres af disse lister:

ListeHvad der tæller som en ændring
GET /v1/cards, GET /v1/cards/countKortets updated_at.
GET /v1/groupsGruppens updated_at: dens titel eller indstillinger.
GET /v1/webhooksSlutpunktets updated_at: dets indstillinger og hemmelighed, ikke dets leveringer.
GET /v1/jobsJobbets updated_at: hver ændring af dets status.
GET /v1/draftsUdkastets updated_at.
GET /v1/cards/{card_id}/threadsDen seneste oprettelse eller redigering af rodkommentaren eller af et af svarene. Tråden kommer hel.
GET /v1/folders, GET /v1/collections/{name}/foldersMappens updated_at. De matchende mapper kommer som en flad liste, se nedenfor.

Samlinger, brugere og meddelelser har intet updated_at, så deres lister filtrerer ikke efter det: De er korte, så læs dem hele ved hver kørsel. Tidspunktet skal have en tidszoneforskydning, fx Z eller +02:00; enhver anden værdi afvises, som ved GET /v1/cards.

Med updated_since er et mappetræ ikke længere et træ: folders for hver samling indeholder de ændrede mapper som en flad liste med tom children, og parent_id fortæller, hvor hver mappe ligger. GET /v1/folders udelader så de samlinger, der ikke har ændrede mapper.

En synkroniseringsløkke

  1. Læs hele listen uden updated_since ved den første kørsel, og husk det tidspunkt, hvor kørslen startede.
  2. Send ved hver følgende kørsel det huskede tidspunkt som updated_since minus en lille margin, fx ét minut, og husk det nye starttidspunkt.
  3. Skriv hvert objekt i dit lager efter dets id, så det erstatter den tidligere kopi. Objekter, der kommer to gange på grund af marginen, bliver blot skrevet igen.
  4. Hent hver følgende side med cursoren og det samme updated_since. En cursor virker kun med filtrene fra den første side: Uden dem returnerer anmodningen 400 med koden api.cursor_invalid.

Når du bruger kørslens starttidspunkt og ikke det tidspunkt, hvor den sluttede, kommer en ændring, der blev foretaget, mens kørslen var i gang, med i den næste kørsel.

GET /v1/cards returnerer et JSON-array, så den næste side kommer i headeren X-Next-Cursor (se Lister, der returnerer et 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
}

Sletninger

En liste returnerer kun objekter, der findes, så den kan ikke fortælle dig, at noget er slettet. Hent sletninger fra hændelsesfeedet:

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"

Læsning af feedet kræver en nøgle med rollen admin og scopet webhooks:manage. Hændelser gemmes i 30 dage. Har din synkronisering ikke kørt i længere tid end det, så læs hele listen igen, og fjern alle objekter fra dit lager, som ikke længere er med i den.

Eksport til et datavarehus samler lister, updated_since og hændelsesfeedet i ét job.