Phân trang
Danh sách của Sursa API được phân trang bằng con trỏ: bạn yêu cầu tối đa limit phần tử, và phản hồi cho bạn biết
cách lấy trang tiếp theo. Bạn không bao giờ phải tính offset, và phần tử không bị lặp hay bị sót giữa các trang khi dữ
liệu thay đổi trong lúc đó.
| Tham số | Giá trị |
|---|---|
limit | Số phần tử mỗi trang, thường từ 1 đến 200. Các danh sách mới mặc định là 50; tài liệu tham chiếu ghi khoảng giá trị và giá trị mặc định của từng danh sách. |
cursor | Con trỏ từ trang trước. Bỏ qua tham số này cho trang đầu tiên. |
Danh sách trả về con trỏ tiếp theo theo một trong hai cách, tùy theo dạng phản hồi của nó. Trang của mỗi endpoint trong tài liệu tham chiếu API cho biết nó dùng cách nào.
Danh sách có lớp bọc data
Các danh sách được thêm cho API công khai, chẳng hạn nguồn cấp sự kiện, trả về một đối tượng với các phần tử trong
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
}
Khi has_more là true, hãy yêu cầu trang tiếp theo với cursor đặt bằng next_cursor và cùng các bộ lọc:
curl "https://api.sursa.com/v1/webhook-events?limit=2&cursor=eyJ2IjoxLCJrIjpbMTA0Ml19" \
-H "Authorization: Bearer $SURSA_API_KEY"Các danh sách có từ trước khi có con trỏ và trả về một đối tượng giữ lớp bọc riêng của chúng (ví dụ
{"items": […], "total": 120}). Chúng nhận next_cursor và has_more trong cùng đối tượng; các phần tử vẫn ở chỗ
cũ.
Danh sách trả về mảng
Một vài danh sách trả về mảng JSON thuần, ví dụ GET /v1/collections.
Dạng phản hồi của chúng không thể thay đổi, nên trang tiếp theo được trả về trong header:
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", …}, …]
Linkvớirel="next"là địa chỉ đầy đủ của trang tiếp theo;X-Next-Cursorlà chính con trỏ đó.- Không có
Linkvớirel="next"và không cóX-Next-Cursornghĩa là đây là trang cuối cùng. - Khi không có
limit, các danh sách này trả về mọi phần tử trong một phản hồi, như trước nay. Hãy truyềnlimitđể phân trang chúng; con trỏ ghi nhớ kích thước trang, nên yêu cầu tiếp theo có thể bỏ qualimit. GET /v1/cardslà ngoại lệ: danh sách này luôn trả về theo trang, mặc định 200 thẻ và tối đa 1000 thẻ vớilimit, nên hãy theoX-Next-Cursorngay cả khi không có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;
}
}Nguồn cấp sự kiện
Nguồn cấp sự kiện GET /v1/webhook-events là một nhật ký, nên nó phân trang
hơi khác:
- Sự kiện được sắp xếp tăng dần, cũ nhất trước.
next_cursorđược trả về trên mọi trang, ngay cả khihas_morelàfalse. Hãy lưu nó, và hỏi lại sau với cùng con trỏ để nhận các sự kiện đã xảy ra kể từ đó. Nguồn cấp là một hàng đợi mà bạn có thể đọc theo nhịp độ của mình.- Sự kiện xuất hiện trong nguồn cấp trong khoảng một giây sau thay đổi mà nó mô tả, và không bao giờ xuất hiện trước một sự kiện đã được đọc.
- Nguồn cấp chứa sự kiện của toàn bộ tổ chức, nên để đọc nó bạn cần một khóa có vai trò
adminvà phạm viwebhooks:manage.
Xuất sang kho dữ liệu trình bày một vòng lặp thăm dò hoàn chỉnh.
Quy tắc về con trỏ
- Con trỏ là một chuỗi không trong suốt dài tối đa 512 ký tự. Đừng phân tích hay tự tạo nó: định dạng của nó có thể thay đổi.
- Con trỏ thuộc về một danh sách và một tập bộ lọc. Con trỏ bị hỏng, đến từ danh sách khác hoặc được gửi kèm bộ lọc
khác trả về
400với mãapi.cursor_invalid. - Mỗi danh sách có thứ tự sắp xếp cố định kết thúc bằng một khóa duy nhất, nên mỗi phần tử xuất hiện trên đúng một trang.
- Danh sách được thêm cùng với con trỏ không trả về tổng số; danh sách đã có
totaltừ trước vẫn giữ nó. Hãy tự đếm phần tử trong quá trình đọc nếu bạn cần tổng số.
Phân trang theo offset
Một số danh sách đã chấp nhận offset từ trước khi có con trỏ và vẫn chấp nhận, để các tích hợp hiện có tiếp tục hoạt
động. Trong mã mới, hãy ưu tiên cursor. Không thể kết hợp offset và cursor: gửi cả hai trả về 422 với mã
validation.failed.