Sincronizzazione incrementale con updated_since
Per mantenere una copia dei dati di Sursa nel tuo sistema non devi leggere tutto ogni volta. Gli elenchi degli
oggetti che hanno updated_at accettano updated_since e restituiscono solo gli oggetti modificati in quel momento o
dopo.
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"Con updated_since, l’elenco è ordinato per updated_at crescente, poi per id, e il cursore
prosegue in quell’ordine. Così leggi le modifiche nell’ordine in cui sono avvenute, e il confine tra due pagine non le
divide mai in modo da perderne una.
updated_since è accettato da questi elenchi:
| Elenco | Cosa conta come modifica |
|---|---|
GET /v1/cards, GET /v1/cards/count | updated_at della scheda. |
GET /v1/groups | updated_at del gruppo: il suo titolo o le sue impostazioni. |
GET /v1/webhooks | updated_at del webhook: le sue impostazioni e il suo segreto, non le sue consegne. |
GET /v1/jobs | updated_at del job: ogni cambio del suo stato. |
GET /v1/drafts | updated_at della bozza. |
GET /v1/cards/{card_id}/threads | La creazione o la modifica più recente del commento principale o di una qualsiasi risposta. La discussione arriva per intero. |
GET /v1/folders, GET /v1/collections/{name}/folders | updated_at della cartella. Le cartelle corrispondenti arrivano come elenco piatto, vedi sotto. |
Raccolte, utenti e comunicazioni non hanno updated_at, quindi i loro elenchi non filtrano in base a esso: sono brevi,
perciò leggili per intero a ogni esecuzione. L’orario deve avere uno scostamento dal fuso orario, come Z o +02:00;
qualsiasi altro valore viene rifiutato, come con GET /v1/cards.
Con updated_since, un albero di cartelle non è più un albero: folders di ogni raccolta contiene le cartelle
modificate come elenco piatto, con children vuoto, e parent_id indica dove si trova ciascuna.
GET /v1/folders in questo caso omette le raccolte senza cartelle modificate.
Un ciclo di sincronizzazione
- Alla prima esecuzione, leggi l’intero elenco senza
updated_sincee annota il momento in cui l’esecuzione è iniziata. - A ogni esecuzione successiva, passa quel momento come
updated_since, meno un piccolo margine, per esempio un minuto, e annota il nuovo orario di inizio. - Scrivi ogni oggetto nel tuo archivio in base al suo
id, sostituendo la copia precedente. Gli oggetti che compaiono due volte a causa del margine vengono semplicemente scritti di nuovo. - Richiedi ogni pagina successiva con il cursore e lo stesso
updated_since. Un cursore funziona solo con i filtri della prima pagina: senza di essi la richiesta restituisce400con il codiceapi.cursor_invalid.
Usare l’orario di inizio dell’esecuzione, e non quello di fine, garantisce che una modifica fatta mentre l’esecuzione era in corso venga raccolta dalla successiva.
GET /v1/cards restituisce un array JSON, quindi la sua pagina successiva arriva nell’intestazione X-Next-Cursor
(vedi Elenchi che restituiscono un 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
}Eliminazioni
Un elenco restituisce solo gli oggetti che esistono, quindi non può dirti che qualcosa è stato eliminato. Ricava le eliminazioni dal feed degli eventi:
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"Per leggere il feed serve una chiave con il ruolo admin e l’ambito webhooks:manage. Gli eventi vengono conservati
per 30 giorni. Se la tua sincronizzazione non è stata eseguita per più tempo, leggi di nuovo l’elenco completo e rimuovi
dal tuo archivio ogni oggetto che non vi compare più.
Esportare in un data warehouse riunisce elenchi, updated_since e feed degli
eventi in un unico job.