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के रूप में भेजें, उसमें से एक मिनट जैसा छोटा मार्जिन घटाकर, और नया शुरुआती समय याद रखें। - हर ऑब्जेक्ट को उसके
idके आधार पर अपने स्टोर में लिखें, पिछली कॉपी की जगह। जो ऑब्जेक्ट मार्जिन की वजह से दो बार आते हैं, वे बस फिर से लिख दिए जाते हैं। - हर अगला पेज कर्सर और उसी
updated_sinceके साथ माँगें। कर्सर सिर्फ़ पहले पेज के फ़िल्टर के साथ काम करता है: उनके बिना रिक्वेस्ट कोडapi.cursor_invalidके साथ400लौटाती है।
रन ख़त्म होने के समय के बजाय उसके शुरू होने का समय इस्तेमाल करने से यह पक्का होता है कि रन के दौरान हुआ बदलाव अगले रन में आ जाए।
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 और इवेंट फ़ीड को एक
जॉब में जोड़ता है।