Langsung ke konten
Sursa Developers

Sinkronisasi inkremental dengan updated_since

Untuk menyimpan salinan data Sursa di sistem Anda sendiri, Anda tidak perlu membaca semuanya setiap kali. Daftar objek yang memiliki updated_at menerima updated_since dan hanya mengembalikan objek yang berubah pada saat itu atau sesudahnya.

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"

Dengan updated_since, daftar diurutkan menurut updated_at secara menaik, lalu menurut id, dan kursor berlanjut dalam urutan itu. Jadi Anda membaca perubahan dalam urutan terjadinya, dan batas halaman tidak pernah memisahkannya dengan cara yang membuat salah satunya hilang.

updated_since diterima oleh daftar berikut:

DaftarYang dihitung sebagai perubahan
GET /v1/cards, GET /v1/cards/countupdated_at kartu.
GET /v1/groupsupdated_at grup: judul atau pengaturannya.
GET /v1/webhooksupdated_at webhook: pengaturan dan rahasianya, bukan pengirimannya.
GET /v1/jobsupdated_at job: setiap perubahan statusnya.
GET /v1/draftsupdated_at draf.
GET /v1/cards/{card_id}/threadsPembuatan atau pengeditan terbaru dari komentar akar atau balasan mana pun. Utas datang secara utuh.
GET /v1/folders, GET /v1/collections/{name}/foldersupdated_at folder. Folder yang cocok datang sebagai daftar datar, lihat di bawah.

Koleksi, pengguna, dan pengumuman tidak memiliki updated_at, jadi daftarnya tidak menyaring menurut field itu: daftar tersebut pendek, jadi bacalah secara utuh pada setiap eksekusi. Waktunya harus memiliki offset zona waktu, seperti Z atau +02:00; nilai lain ditolak, seperti pada GET /v1/cards.

Dengan updated_since, pohon folder tidak lagi berupa pohon: folders dari setiap koleksi berisi folder yang berubah sebagai daftar datar, dengan children kosong, dan parent_id menunjukkan letak masing-masing. GET /v1/folders lalu tidak menyertakan koleksi tanpa folder yang berubah.

Loop sinkronisasi

  1. Pada eksekusi pertama, baca seluruh daftar tanpa updated_since, dan ingat saat eksekusi itu dimulai.
  2. Pada setiap eksekusi berikutnya, berikan saat yang diingat itu sebagai updated_since, dikurangi cadangan waktu kecil seperti satu menit, lalu ingat waktu mulai yang baru.
  3. Tulis setiap objek ke penyimpanan Anda menurut id-nya, menggantikan salinan sebelumnya. Objek yang muncul dua kali karena cadangan waktu itu cukup ditulis lagi.
  4. Minta setiap halaman berikutnya dengan kursor dan updated_since yang sama. Kursor hanya berfungsi dengan penyaring halaman pertama: tanpa penyaring itu, permintaan mengembalikan 400 dengan kode api.cursor_invalid.

Memakai waktu mulai eksekusi, bukan waktu selesainya, memastikan bahwa perubahan yang dibuat selama eksekusi berjalan akan terambil oleh eksekusi berikutnya.

GET /v1/cards mengembalikan array JSON, jadi halaman berikutnya datang di header X-Next-Cursor (lihat Daftar yang mengembalikan 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
}

Penghapusan

Daftar hanya mengembalikan objek yang ada, jadi daftar tidak dapat memberi tahu Anda bahwa sesuatu telah dihapus. Ambil penghapusan dari umpan peristiwa:

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"

Membaca umpan memerlukan kunci dengan peran admin dan cakupan webhooks:manage. Peristiwa disimpan selama 30 hari. Jika sinkronisasi Anda tidak berjalan lebih lama dari itu, baca lagi seluruh daftar dan hapus dari penyimpanan Anda setiap objek yang sudah tidak ada di dalamnya.

Ekspor ke gudang data menggabungkan daftar, updated_since, dan umpan peristiwa menjadi satu job.