ข้ามไปยังเนื้อหา
Sursa Developers

การแบ่งหน้า

รายการของ Sursa API แบ่งหน้าด้วย เคอร์เซอร์ คุณขอรายการได้ไม่เกิน limit รายการ และการตอบกลับจะบอกวิธีรับหน้าถัดไป คุณไม่ต้องคำนวณออฟเซ็ตเอง และรายการจะไม่ซ้ำหรือหายไประหว่างหน้า แม้ข้อมูลจะเปลี่ยนแปลงในระหว่างนั้น

พารามิเตอร์ค่า
limitจำนวนรายการต่อหน้า โดยทั่วไป 1–200 รายการใหม่มีค่าเริ่มต้น 50 และเอกสารอ้างอิงแสดงช่วงค่าและค่าเริ่มต้นของแต่ละรายการ
cursorเคอร์เซอร์จากหน้าก่อนหน้า ไม่ต้องส่งสำหรับหน้าแรก

รายการส่งคืนเคอร์เซอร์ถัดไปได้สองแบบ ขึ้นอยู่กับโครงสร้างของการตอบกลับ หน้าของแต่ละเอนด์พอยต์ใน เอกสารอ้างอิง API ระบุว่าใช้แบบใด

รายการที่ห่อด้วย data

รายการที่เพิ่มเข้ามาสำหรับ API สาธารณะ เช่น ฟีดอีเวนต์ ส่งคืนออบเจ็กต์ที่มีรายการอยู่ใน data:

curl "https://api.sursa.com/v1/webhook-events?limit=2" \
  -H "Authorization: Bearer $SURSA_API_KEY"
{
  "data": [
    {"id": "evt_8a1f…", "type": "card.published", "created_at": "2026-10-24T10:00:00Z"},
    {"id": "evt_8a20…", "type": "card.updated", "created_at": "2026-10-24T10:00:03Z"}
  ],
  "next_cursor": "eyJ2IjoxLCJrIjpbMTA0Ml19",
  "has_more": true
}

เมื่อ has_more เป็น true ให้ขอหน้าถัดไปโดยตั้ง cursor เป็นค่า next_cursor และใช้ ตัวกรองเดิม:

curl "https://api.sursa.com/v1/webhook-events?limit=2&cursor=eyJ2IjoxLCJrIjpbMTA0Ml19" \
  -H "Authorization: Bearer $SURSA_API_KEY"

รายการที่มีมาก่อนการใช้เคอร์เซอร์และส่งคืนออบเจ็กต์ยังคงใช้โครงสร้างที่ห่อแบบของตัวเอง (เช่น {"items": […], "total": 120}) รายการเหล่านี้ได้ next_cursor และ has_more ในออบเจ็กต์เดียวกัน ส่วนตัวรายการยังอยู่ที่เดิม

รายการที่ส่งคืนอาร์เรย์

รายการจำนวนหนึ่งส่งคืนอาร์เรย์ JSON ล้วน เช่น GET /v1/collections โครงสร้างการตอบกลับของรายการเหล่านี้เปลี่ยนไม่ได้ หน้าถัดไปจึงมาในเฮดเดอร์แทน:

curl -i "https://api.sursa.com/v1/collections?limit=50" \
  -H "Authorization: Bearer $SURSA_API_KEY"
HTTP/1.1 200 OK
Link: <https://api.example.com/v1/collections?limit=50&cursor=eyJ2IjoxLCJrIjpbNTBdfQ>; rel="next"
X-Next-Cursor: eyJ2IjoxLCJrIjpbNTBdfQ

[{"id": 1, "name": "support", …}, …]
  • Link ที่มี rel="next" คือที่อยู่เต็มของหน้าถัดไป ส่วน X-Next-Cursor คือเคอร์เซอร์เดียวกันแบบเดี่ยว
  • หากไม่มี Link ที่มี rel="next" และไม่มี X-Next-Cursor แสดงว่านี่คือหน้าสุดท้าย
  • หากไม่ระบุ limit รายการเหล่านี้จะส่งคืนทุกรายการในการตอบกลับเดียวเหมือนที่เคยเป็นมา ส่ง limit เพื่อแบ่งหน้า เคอร์เซอร์จำขนาดหน้าไว้ คำขอถัดไปจึงไม่ต้องส่ง limit ก็ได้
  • GET /v1/cards เป็นข้อยกเว้น รายการนี้ส่งคืนเป็นหน้าเสมอ ค่าเริ่มต้นคือ 200 การ์ด และได้สูงสุด 1,000 การ์ดเมื่อระบุ limit จึงต้องติดตาม X-Next-Cursor แม้ไม่ได้ระบุ limit
// Every item of a list that returns an array.
async function* listArray(path) {
  let next = `https://api.sursa.com${path}?limit=200`;
  while (next) {
    const response = await fetch(next, { headers: { Authorization: `Bearer ${process.env.SURSA_API_KEY}` } });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    yield* await response.json();
    const cursor = response.headers.get("X-Next-Cursor");
    next = cursor ? `https://api.sursa.com${path}?cursor=${encodeURIComponent(cursor)}` : null;
  }
}

ฟีดอีเวนต์

ฟีดอีเวนต์ GET /v1/webhook-events เป็นล็อก จึงแบ่งหน้าต่างออกไปเล็กน้อย:

  • อีเวนต์เรียงจากเก่าไปใหม่
  • next_cursor ส่งคืนมาใน ทุก หน้า แม้ has_more จะเป็น false ให้เก็บค่านี้ไว้ แล้วขอใหม่ภายหลังด้วยเคอร์เซอร์เดิมเพื่อรับอีเวนต์ที่เกิดขึ้นหลังจากนั้น ฟีดเป็นคิวที่คุณอ่านตามจังหวะของคุณเองได้
  • อีเวนต์ปรากฏในฟีดภายในประมาณ 1 วินาทีหลังการเปลี่ยนแปลงที่อีเวนต์นั้นอธิบาย และจะไม่ปรากฏก่อนอีเวนต์ที่อ่านไปแล้ว
  • ฟีดเก็บอีเวนต์ขององค์กรทั้งหมด การอ่านฟีดจึงต้องใช้คีย์ที่มีบทบาท admin และขอบเขตสิทธิ์ webhooks:manage

ส่งออกไปยังคลังข้อมูล แสดงลูปการโพลที่สมบูรณ์

กฎของเคอร์เซอร์

  • เคอร์เซอร์เป็นสตริงทึบ (opaque) ยาวไม่เกิน 512 อักขระ อย่าแยกวิเคราะห์หรือสร้างเคอร์เซอร์เอง เพราะรูปแบบอาจเปลี่ยนได้
  • เคอร์เซอร์เป็นของรายการเดียวและชุดตัวกรองชุดเดียว เคอร์เซอร์ที่เสียหาย มาจากรายการอื่น หรือส่งพร้อมตัวกรองที่ต่างไป จะได้การตอบกลับ 400 พร้อมรหัส api.cursor_invalid
  • แต่ละรายการมีลำดับการเรียงตายตัวที่ลงท้ายด้วยคีย์ที่ไม่ซ้ำกัน ทุกรายการจึงปรากฏในหน้าเดียวเท่านั้น
  • รายการที่เพิ่มเข้ามาพร้อมเคอร์เซอร์ไม่ส่งคืนจำนวนรวม ส่วนรายการที่เคยมี total ยังคงมีอยู่ หากต้องการจำนวนรวม ให้นับรายการไประหว่างอ่าน

การแบ่งหน้าแบบออฟเซ็ต

รายการบางรายการรับ offset มาตั้งแต่ก่อนมีเคอร์เซอร์ และยังรับอยู่ เพื่อให้ระบบที่เชื่อมต่ออยู่แล้วทำงานต่อได้ ในโค้ดใหม่ให้ใช้ cursor จะใช้ offset ร่วมกับ cursor ไม่ได้ การส่งทั้งคู่จะได้การตอบกลับ 422 พร้อมรหัส validation.failed