API: POST /track/open
Bạn sẽ học: Toàn bộ hợp đồng của endpoint
POST /api/v1/track/open — cách xác thực, các trường request, server chọn đường xử lý ra sao, hình dạng response, và ý nghĩa từng giá trị matchMethod / missReason.Endpoint & môi trường
AuthMobileApikeyMiddleware.
Xác thực
Gửi publishable key trong header:- Lấy publishable key ở đâu: dashboard → Settings → Analytics → Publishable Key (dạng
li2_pk_...). Key được tạo tự động khi bật Analytics; chi tiết tại Thiết lập Conversion Tracking. - Fallback cho caller không đặt được custom header (ví dụ
sendBeacon): tham số query?li2_key=.... - Không dùng server API key (
X-Li2-API-Key) cho endpoint này — sẽ trả về 401. Endpoint mobile chỉ chấp nhận key dạngli2_pk_*.
Vì sao publishable key an toàn khi nhúng trong app: với request từ web (có
Origin/Referer), server kiểm tra origin theo whitelist của key. Với app native (không có Origin/Referer), server bỏ qua bước origin và kiểm tra phía server rằng domain được track thuộc đúng organization của key. Key không thể dùng để track domain tùy ý hay truy cập dữ liệu org khác.Request
Request
Phải có ít nhất một trong
deepLink, li2Domains, hoặc installReferrer.
Server chọn đường xử lý như thế nào
Trước khi xử lý, server kiểm tra org có gói Pro (
deep_link_attribution) và suy ra platform (ios/android) từ User-Agent.
Response
Response
- Khi khớp:
linkđược điền,missReasonbị bỏ qua. - Khi trượt (deferred không đối chiếu được):
linklànull,missReasonđược điền. clickIdluôn có: dùng id của click gốc khi khớp, hoặc một id ngẫu nhiên khi trượt (đồng thời ghi một dòngdeferred_miss).link.idlà UUID của touch point (cấu hình link trong Li2), không phải id của short link hiển thị hay của click. Điều hướng người dùng bằnglink.url;link.keylà slug,link.domainlà host.
Ví dụ theo từng luồng
Mỗi tab là một lệnhcurl chạy được (thay your-domain.com và li2_pk_... bằng giá trị của bạn) kèm response mẫu.
platform và matchMethod suy ra từ User-Agent. Server đọc UA của request để phân loại ios/android. Một lệnh curl mặc định (UA curl/8.x) khớp không nền tảng nào → trả về platform: null và matchMethod rỗng. Vì vậy các ví dụ dưới đây đều kèm header -A giả lập UA thiết bị để response khớp như minh họa. Từ app thật, UA của URLSession/okhttp đã chứa sẵn dấu hiệu nền tảng nên bạn không cần làm gì thêm.- Immediate (đã cài app)
- iOS deferred (khớp)
- Android deferred (khớp)
- Deferred (trượt)
App đã cài, mở qua Universal Link / App Link — chỉ gửi Trên Android, cùng request này trả về
deepLink, không có li2_cid:Request
Response · 200
"matchMethod": "app_link" và "platform": "android".Giá trị matchMethod
Giá trị missReason
Mã trạng thái
Cô lập tenant ở luồng deferred (clipboard/referrer) không trả 403 mà trả
200 + missReason: cross_tenant_blocked (link: null) — để không lộ việc hostname có thuộc org khác hay không. Chỉ luồng immediate mới trả 403 khi domain không thuộc org.Hình dạng body lỗi
Response thành công là object phẳng ({ clickId, link, ... } như trên — không bọc envelope). Mọi response lỗi dùng chung một envelope:
Error
code= HTTP status;message= mô tả tiếng Anh dễ đọc;dataluônnullkhi lỗi.error_codelà mã ổn định, máy đọc được — hãy branch theo nó thay vì so khớp chuỗimessage. Hầu hết lỗi phía client (4xx) đều kèmerror_code; lỗi server (5xx) trả cùng envelope nhưng không cóerror_code(chỉ cần retry/backoff). Ngoại lệ quan trọng: lỗi xác thực sinh ở tầng middleware (key thiếu/sai, origin sai) không kèmerror_code— xem cảnh báo bên dưới.
Các error_code của endpoint
Bước tiếp theo
Tích Hợp iOS & Android
Xem cách gọi endpoint này từ app native.
Tổng Quan Deep Link
Quay lại bức tranh tổng thể về immediate vs deferred.

