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:
| Liste | Hvad der tæller som en ændring |
|---|---|
GET /v1/cards, GET /v1/cards/count | Kortets updated_at. |
GET /v1/groups | Gruppens updated_at: dens titel eller indstillinger. |
GET /v1/webhooks | Slutpunktets updated_at: dets indstillinger og hemmelighed, ikke dets leveringer. |
GET /v1/jobs | Jobbets updated_at: hver ændring af dets status. |
GET /v1/drafts | Udkastets updated_at. |
GET /v1/cards/{card_id}/threads | Den seneste oprettelse eller redigering af rodkommentaren eller af et af svarene. Tråden kommer hel. |
GET /v1/folders, GET /v1/collections/{name}/folders | Mappens 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
- Læs hele listen uden
updated_sinceved den første kørsel, og husk det tidspunkt, hvor kørslen startede. - Send ved hver følgende kørsel det huskede tidspunkt som
updated_sinceminus en lille margin, fx ét minut, og husk det nye starttidspunkt. - 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. - 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 anmodningen400med kodenapi.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.