การซิงก์แบบส่วนเพิ่มด้วย updated_since
หากต้องการเก็บสำเนาข้อมูลของ Sursa ไว้ในระบบของคุณเอง ไม่จำเป็นต้องอ่านทุกอย่างใหม่ทุกครั้ง รายการของออบเจ็กต์ที่มี updated_at รองรับ updated_since และส่งคืนเฉพาะออบเจ็กต์ที่เปลี่ยนแปลง ณ เวลานั้นหรือหลังจากนั้น
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"เมื่อใช้ updated_since รายการจะเรียงตาม updated_at จากน้อยไปมาก แล้วตาม id และ เคอร์เซอร์ จะไล่ต่อตามลำดับนั้น คุณจึงอ่านการเปลี่ยนแปลงตามลำดับที่เกิดขึ้นจริง และขอบเขตระหว่างหน้าจะไม่แบ่งการเปลี่ยนแปลงในแบบที่ทำให้บางรายการหายไป
updated_since ใช้ได้กับรายการต่อไปนี้:
| รายการ | สิ่งที่นับเป็นการเปลี่ยนแปลง |
|---|---|
GET /v1/cards และ GET /v1/cards/count | updated_at ของการ์ด |
GET /v1/groups | updated_at ของกลุ่ม ได้แก่ ชื่อหรือการตั้งค่าของกลุ่ม |
GET /v1/webhooks | updated_at ของเว็บฮุก ได้แก่ การตั้งค่าและข้อมูลลับของเว็บฮุก ไม่รวมการส่ง |
GET /v1/jobs | updated_at ของงานประมวลผล ได้แก่ ทุกการเปลี่ยนสถานะของงาน |
GET /v1/drafts | updated_at ของฉบับร่าง |
GET /v1/cards/{card_id}/threads | การสร้างหรือการแก้ไขล่าสุดของความคิดเห็นหลักหรือของการตอบกลับความคิดเห็นใดก็ตาม เธรดมาครบทั้งเธรด |
GET /v1/folders และ GET /v1/collections/{name}/folders | updated_at ของโฟลเดอร์ โฟลเดอร์ที่ตรงเงื่อนไขมาเป็นรายการแบบแบน ดูด้านล่าง |
คอลเลกชัน ผู้ใช้ และประกาศไม่มี updated_at รายการของออบเจ็กต์เหล่านี้จึงไม่กรองด้วยค่านี้ รายการเหล่านี้สั้น ให้อ่านทั้งรายการในทุกการรัน เวลาที่ส่งต้องมีค่าออฟเซ็ตของเขตเวลา เช่น Z หรือ +02:00 ค่าอื่นจะถูกปฏิเสธเหมือนใน GET /v1/cards
เมื่อใช้ updated_since ต้นไม้โฟลเดอร์จะไม่เป็นต้นไม้อีกต่อไป folders ของแต่ละคอลเลกชันมีโฟลเดอร์ที่เปลี่ยนแปลงเป็นรายการแบบแบนพร้อม children ที่ว่างเปล่า และ parent_id บอกตำแหน่งของแต่ละโฟลเดอร์ ในกรณีนี้ GET /v1/folders จะไม่รวมคอลเลกชันที่ไม่มีโฟลเดอร์ที่เปลี่ยนแปลง
ลูปการซิงก์
- ในการรันครั้งแรก ให้อ่านทั้งรายการโดยไม่ใช้
updated_sinceและจดเวลาที่การรัน เริ่มต้น ไว้ - ในการรันครั้งถัดไปทุกครั้ง ให้ส่งเวลาที่จดไว้เป็น
updated_sinceโดยหักเวลาเผื่อเล็กน้อย เช่น 1 นาที แล้วจดเวลาเริ่มต้นใหม่ไว้ - เขียนแต่ละออบเจ็กต์ลงที่เก็บข้อมูลของคุณตาม
idแทนที่สำเนาเดิม ออบเจ็กต์ที่ปรากฏซ้ำเพราะเวลาเผื่อก็เพียงถูกเขียนทับอีกครั้ง - ขอทุกหน้าถัดไปด้วยเคอร์เซอร์ และ
updated_sinceค่าเดิม เคอร์เซอร์ใช้ได้เฉพาะกับตัวกรองของหน้าแรก หากไม่ส่งตัวกรองเหล่านั้น คำขอจะได้การตอบกลับ400พร้อมรหัสapi.cursor_invalid
การใช้เวลาเริ่มต้นของการรันแทนเวลาที่การรันเสร็จ ทำให้มั่นใจได้ว่าการเปลี่ยนแปลงที่เกิดขึ้นระหว่างการรันจะถูกเก็บตกในการรันครั้งถัดไป
GET /v1/cards ส่งคืนอาร์เรย์ JSON หน้าถัดไปของรายการนี้จึงมาในเฮดเดอร์ X-Next-Cursor (ดู รายการที่ส่งคืนอาร์เรย์):
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
}การลบ
รายการส่งคืนเฉพาะออบเจ็กต์ที่มีอยู่ จึงบอกไม่ได้ว่ามีอะไรถูกลบไปแล้ว ให้รับข้อมูลการลบจาก ฟีดอีเวนต์:
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"การอ่านฟีดต้องใช้คีย์ที่มีบทบาท admin และขอบเขตสิทธิ์ webhooks:manage อีเวนต์เก็บไว้ 30 วัน หากการซิงก์ไม่ได้รันนานกว่านั้น ให้อ่านทั้งรายการใหม่อีกครั้ง แล้วลบออบเจ็กต์ทุกรายการที่ไม่อยู่ในรายการแล้วออกจากที่เก็บข้อมูลของคุณ
ส่งออกไปยังคลังข้อมูล รวมรายการ updated_since และฟีดอีเวนต์เข้าไว้ในงานเดียว