Inkrementelle Synchronisierung mit updated_since
Um eine Kopie der Sursa-Daten in Ihrem eigenen System zu führen, müssen Sie nicht jedes Mal alles lesen. Die Listen
von Objekten mit updated_at akzeptieren updated_since und geben nur die Objekte zurück, die zu diesem Zeitpunkt
oder danach geändert wurden.
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"Mit updated_since ist die Liste aufsteigend nach updated_at und danach nach id sortiert, und der
Cursor setzt diese Reihenfolge fort. So lesen Sie die Änderungen in der Reihenfolge,
in der sie geschehen sind, und eine Seitengrenze teilt sie nie so, dass eine verloren geht.
updated_since wird von diesen Listen akzeptiert:
| Liste | Was als Änderung zählt |
|---|---|
GET /v1/cards, GET /v1/cards/count | updated_at der Karte. |
GET /v1/groups | updated_at der Gruppe: ihr Titel oder ihre Einstellungen. |
GET /v1/webhooks | updated_at des Endpunkts: seine Einstellungen und sein Signatur-Secret, nicht seine Zustellungen. |
GET /v1/jobs | updated_at des Jobs: jede Änderung seines Status. |
GET /v1/drafts | updated_at des Entwurfs. |
GET /v1/cards/{card_id}/threads | Die letzte Erstellung oder Bearbeitung des Wurzelkommentars oder einer beliebigen Antwort. Der Thread kommt vollständig. |
GET /v1/folders, GET /v1/collections/{name}/folders | updated_at des Ordners. Die passenden Ordner kommen als flache Liste, siehe unten. |
Sammlungen, Benutzer und Ankündigungen haben kein updated_at, daher filtern ihre Listen nicht danach: Diese Listen
sind kurz, lesen Sie sie also bei jedem Lauf vollständig. Die Zeitangabe muss einen Zeitzonen-Offset haben, etwa Z
oder +02:00; jeder andere Wert wird abgelehnt, wie bei GET /v1/cards.
Mit updated_since ist ein Ordnerbaum kein Baum mehr: folders jeder Sammlung enthält die geänderten Ordner als
flache Liste mit leerem children, und parent_id zeigt, wo jeder davon liegt.
GET /v1/folders lässt dann die Sammlungen ohne geänderte Ordner weg.
Eine Synchronisierungsschleife
- Lesen Sie beim ersten Lauf die ganze Liste ohne
updated_sinceund merken Sie sich den Zeitpunkt, an dem der Lauf begonnen hat. - Übergeben Sie bei jedem weiteren Lauf diesen gemerkten Zeitpunkt abzüglich einer kleinen Reserve, etwa einer
Minute, als
updated_sinceund merken Sie sich die neue Startzeit. - Schreiben Sie jedes Objekt anhand seiner
idin Ihren Speicher und ersetzen Sie dabei die vorherige Kopie. Objekte, die wegen der Reserve doppelt erscheinen, werden einfach erneut geschrieben. - Fordern Sie jede weitere Seite mit dem Cursor und demselben
updated_sincean. Ein Cursor funktioniert nur mit den Filtern der ersten Seite: Ohne sie ergibt die Anfrage400mit dem Codeapi.cursor_invalid.
Wenn Sie die Startzeit des Laufs statt seiner Endzeit verwenden, wird eine Änderung, die während des Laufs geschieht, sicher vom nächsten Lauf erfasst.
GET /v1/cards gibt ein JSON-Array zurück, daher kommt seine nächste Seite im Header X-Next-Cursor
(siehe Listen, die ein Array zurückgeben):
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
}Löschungen
Eine Liste gibt nur Objekte zurück, die existieren, und kann Ihnen daher nicht sagen, dass etwas gelöscht wurde. Übernehmen Sie Löschungen aus dem Ereignis-Feed:
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"Das Lesen des Feeds erfordert einen Schlüssel mit der Rolle admin und dem Scope webhooks:manage. Ereignisse werden
30 Tage aufbewahrt. Ist Ihre Synchronisierung länger nicht gelaufen, lesen Sie die vollständige Liste erneut und
entfernen Sie aus Ihrem Speicher jedes Objekt, das darin nicht mehr vorkommt.
Export in ein Data Warehouse fasst Listen, updated_since und den
Ereignis-Feed zu einem Job zusammen.