Phân trang và đồng bộ
Các endpoint danh sách phân trang bằng con trỏ, không dùng số trang.
Con trỏ
| Tham số | Ý nghĩa |
|---|---|
limit |
Số dòng mỗi trang, từ 1 đến 100, mặc định 50. |
cursor |
Giá trị nextCursor của trang trước. Bỏ trống để đọc từ đầu. |
Phản hồi có dạng:
{
"data": [ ],
"nextCursor": "eyJ2IjoxLCJ0IjoiMjAyNi0xMC0wMVQwODozMDowMC4wMDBaIiwiaWQiOiIuLi4ifQ"
}
nextCursor là null khi hết dữ liệu. Để đọc hết một danh sách, lặp lại với cursor mới (giữ nguyên các tham số khác) cho tới khi nextCursor là null. Con trỏ chỉ để lật trang trong CÙNG một lượt đọc: đừng lưu nó để nối lượt đồng bộ sau — việc ấy dùng updatedSince.
cursor là chuỗi không trong suốt: đừng tự dựng hay phân tích nó, vì cấu trúc bên trong có thể đổi. Cursor sai hình dạng nhận 400 invalid-cursor.
Thứ tự
Các danh sách đồng bộ được (đơn hàng, sản phẩm, khách hàng, vận đơn) sắp theo (updatedAt, id) tăng dần: bản ghi cũ trước, mới sau, và mỗi dòng đều mang updatedAt để bạn lấy mốc nối tiếp. Nhờ vậy bạn xử lý theo thứ tự thời gian; giữa hai lượt đồng bộ, thứ cần lưu là mốc updatedAt, không phải con trỏ (xem bên dưới).
Tồn kho cũng đồng bộ tăng dần nhưng khác một chút: GET /inventory/stock trả tồn của từng mẫu mã tại từng kho, sắp theo lần đổi tồn tăng dần, có updatedSince và nextCursor nhưng dòng tồn không mang updatedAt và không có includeDeleted. Với updatedSince, dùng thời điểm bạn bắt đầu lượt đồng bộ trước (lùi 15 phút, xem bên dưới) làm mốc. Mốc của dòng tồn chỉ đổi khi số tồn hoặc số đang về kho (inTransit) đổi. Giá, mã, mã vạch, tên sản phẩm, tên mẫu mã, ảnh và tên kho trong dòng tồn chỉ là thông tin đọc kèm: shop đổi chúng thì dòng tồn KHÔNG hiện lại trong updatedSince. Hãy lấy các trường ấy từ đồng bộ sản phẩm và danh sách kho.
Hai danh sách còn lại có phân trang nhưng không phục vụ đồng bộ tăng dần:
GET /conversations: hội thoại có tin mới nhất trước; cóupdatedSincenhưng nó lọc theolastMessageAt— giờ của tin mới nhất theo kênh (Facebook, Zalo), không phải mốc sửa — nên tin tới muộn có thể mang giờ trước mốc bạn đã đọc, còn đổi thẻ hay đánh dấu đã đọc không làm hội thoại hiện lại; không cóincludeDeleted.GET /conversations/{id}/messages: tin mới nhất trước; không cóupdatedSincevàincludeDeleted.
Danh mục (/categories), kho (/warehouses), trang chat (/pages), thẻ (/tags) và danh mục hành chính (/geo/units, mỗi lượt một tầng) không phân trang: đó là các danh sách nhỏ, trả trọn trong data, không có nextCursor. Con trỏ chỉ dành cho các danh sách lớn dần theo thời gian.
Đồng bộ tăng dần với updatedSince
Để giữ một bản sao dữ liệu ở hệ thống của bạn, đừng đọc lại toàn bộ mỗi lần. Dùng updatedSince:
curl "https://danix.vn/api/open/v1/orders?updatedSince=2026-10-01T00:00:00.000Z&limit=100" \
-H "Authorization: Bearer dnx_live_…"
updatedSince lọc các bản ghi có updatedAt từ mốc đó trở đi (thời gian ISO 8601, UTC). Lưu mốc updatedAt lớn nhất đã xử lý, lần sau truyền nó làm updatedSince. Đổi số điện thoại, email hay địa chỉ của khách, hoặc thêm, sửa, gỡ ảnh của sản phẩm, cũng nâng updatedAt của khách hay sản phẩm ấy, nên các thay đổi đó cũng hiện qua updatedSince.
Hai điều cần biết để không mất dữ liệu:
- Độ trễ an toàn. Khi gọi kèm
updatedSince, danh sách đơn hàng, sản phẩm, khách hàng, vận đơn và tồn kho chỉ trả các bản ghi cóupdatedAtcũ hơn một khoảng trễ so với lúc gọi. Khoảng trễ ấy bằng thời gian tối đa mà một thao tác tính lại kho của shop được phép chạy (mặc định 2 phút, tối đa 10 phút, theo cài đặt của shop) cộng thêm 15 giây cho bước hoàn tất giao dịch — tức 2 phút 15 giây với cài đặt mặc định, và không bao giờ quá 10 phút 15 giây. Lý do:updatedAtlà lúc giao dịch BẮT ĐẦU, còn bản ghi chỉ hiện ra lúc giao dịch commit. Sửa một phiếu kho đã ghi sổ hay đổi trạng thái đơn kéo theo tính lại giá vốn có thể chạy vài phút trong một giao dịch; nếu danh sách trả ngay, bạn đã đọc qua mốc ấy trước khi dòng commit và sẽ không bao giờ thấy nó. Không cóupdatedSincethì KHÔNG có độ trễ: danh sách trả cả dòng vừa sửa, nên đọc như vậy (kể cả lật tiếp bằng một con trỏ đã lưu từ lượt trước) không an toàn để đồng bộ tăng dần. Lượt đồng bộ đầu tiên cũng nên truyềnupdatedSince— một mốc thật xa như2000-01-01T00:00:00Z— thay vì bỏ trống, để lượt ấy cũng có độ trễ. - Chồng lấn 15 phút và khử trùng. Mỗi lần đồng bộ, đặt
updatedSincelùi lại 15 phút so với mốc đã lưu, rồi khử trùng theoidở phía bạn (bản ghi nào gặp lại thì ghi đè bằng bản mới nhất). Chồng lấn phải dài hơn khoảng trễ an toàn tối đa (10 phút 15 giây); nó là lưới cho các ca biên mà khoảng trễ chưa phủ.
updatedSince là đường đối soát. Muốn nhận thay đổi gần thời gian thực, dùng luồng tự động và webhook.
Dòng đã xoá
DANIX xoá mềm bản ghi theo mặc định, nên danh sách thường không có chúng. Thêm includeDeleted=true để nhận cả dòng đã xoá; mỗi dòng ấy mang deletedAt. Khi đồng bộ, hãy bật tham số này, nếu không bản sao của bạn không bao giờ biết một bản ghi đã bị xoá.
includeDeleted áp cho đơn hàng, sản phẩm và khách hàng; dòng sản phẩm đã xoá mang deletedAt ngay ở danh sách. Vận đơn và tồn kho không có tham số này, có lý do:
- Vận đơn chỉ bị xoá khi hãng vận chuyển từ chối ngay lúc tạo: dòng ấy chưa từng có mã vận đơn và chưa từng tới hãng, tồn tại vài giây rồi bị xoá — ngắn hơn khoảng trễ an toàn nên bản sao của bạn gần như không bao giờ nhận được nó. Danh sách vận đơn luôn bỏ vận đơn đã xoá. Vận đơn bị huỷ không bị xoá: nó ở lại với
statuslàcancelled. - Tồn kho không bao giờ bị xoá. Khi mẫu mã, sản phẩm hay kho bị xoá, dòng tồn của nó ra khỏi danh sách; bạn biết điều ấy qua đồng bộ sản phẩm (
includeDeleted=true) và danh sách kho.
Xem bảng tham số từng endpoint ở phần tham chiếu.