Tài liệu API XuniBOX
API chỉ đọc để lấy danh sách nhạc, nghệ sĩ và thể loại từ kho XuniBOX. Mỗi chủ đề dưới đây là một trang riêng, có đường dẫn riêng để bạn chia sẻ cho đội kỹ thuật.
Checklist go-live & thuật ngữ
Đi qua đủ danh sách này trước khi đưa tích hợp lên production. Phần lớn sự cố của đối tác đến từ đúng ba lỗi: lộ API key ở frontend, lưu link media vào cơ sở dữ liệu, và retry không có backoff.
Bảo mật
- API key nằm trong biến môi trường phía server, không có trong repo, bundle frontend hay file cấu hình mobile.
- Mọi lời gọi từ trình duyệt và app đều đi qua backend proxy của bạn.
- Proxy chỉ mở whitelist các endpoint cần thiết, không forward tùy ý mọi đường dẫn.
- Webhook secret lưu riêng và mọi gói tin đều được xác minh chữ ký timing-safe.
- Log của bạn không in ra API key, secret hay signed URL đầy đủ.
Độ ổn định
- Có timeout tối đa 10 giây cho mọi request tới XuniBOX.
- Có retry với backoff cho lỗi 5xx và tôn trọng Retry-After ở lỗi 429.
- Có cache ở backend cho danh sách, thể loại, nghệ sĩ và sóng âm.
- Không cache audio_url, cover_url hay bất kỳ link ký hạn nào.
- Bộ chọn nhạc vẫn dùng được khi XuniBOX lỗi: hiển thị dữ liệu cache gần nhất thay vì màn hình trắng.
Dữ liệu
- Chỉ lưu track id vào cơ sở dữ liệu, mọi thứ khác coi là dữ liệu tạm.
- Có luồng đồng bộ định kỳ hoặc webhook để bắt bài mới, bài sửa và bài bị gỡ.
- Xử lý idempotent theo id, chịu được webhook trùng lặp và sai thứ tự.
- Có kế hoạch xử lý khi một bài trả 404: ẩn khỏi bộ chọn nhạc, giữ nguyên video đã xuất.
Trải nghiệm & tuân thủ
- Ô tìm kiếm có debounce và huỷ request cũ bằng AbortController.
- Có trạng thái rỗng khi không tìm thấy bài, kèm gợi ý từ /trending.
- Lọc bài theo giấy phép trước khi hiển thị cho luồng nội dung có tài trợ.
- Hiển thị ghi nguồn đúng định dạng khi attribution_required là true.
- Ẩn bài is_explicit ở chế độ dành cho trẻ em.
- Nút phát không cho tải file: dùng controlsList="nodownload" hoặc player tự dựng.
Vận hành
- Có cảnh báo khi tỉ lệ lỗi 4xx/5xx tăng bất thường.
- Theo dõi X-RateLimit-Remaining và cảnh báo khi thường xuyên xuống dưới 20%.
- Kiểm tra /me/usage định kỳ để phát hiện mức dùng tăng đột biến.
- Đã chạy script smoke test bên dưới và tất cả bước đều đạt.
Script smoke test
Chạy trong CI trước mỗi lần phát hành. Script thoát với mã khác 0 nếu bất kỳ bước nào hỏng, nên gắn thẳng vào pipeline được.
bash — smoke-test.sh
#!/usr/bin/env bash
# smoke-test.sh — chạy trước khi lên production. Thoát khác 0 nếu có bước hỏng.
set -euo pipefail
: "${XUNIBOX_API_KEY:?Chưa đặt biến môi trường XUNIBOX_API_KEY}"
BASE="https://xunibox.vn/api/public"
call() { curl -sS -o /tmp/xb.json -w '%{http_code}' -H "X-API-Key: $XUNIBOX_API_KEY" "$BASE$1"; }
echo "1. Readiness" && [ "$(curl -sS -o /dev/null -w '%{http_code}' "$BASE/readyz")" = 200 ]
echo "2. Danh sách bài" && [ "$(call '/tracks?limit=1')" = 200 ]
echo "3. Thể loại" && [ "$(call '/genres')" = 200 ]
echo "4. Nghệ sĩ" && [ "$(call '/artists?limit=1')" = 200 ]
echo "5. Tìm kiếm" && [ "$(call '/search?q=nang&limit=1')" = 200 ]
ID=$(curl -sS -H "X-API-Key: $XUNIBOX_API_KEY" "$BASE/tracks?limit=1" | jq -r '.data[0].id')
echo "6. Chi tiết bài" && [ "$(call "/tracks/$ID")" = 200 ]
echo "7. Link media tươi" && [ "$(call "/tracks/$ID/audio-url")" = 200 ]
echo "8. Sai key trả 403" && [ "$(curl -sS -o /dev/null -w '%{http_code}' -H 'X-API-Key: xnb_live_sai' "$BASE/me/usage")" = 403 ]
echo "✅ Tất cả bước đều đạt."Giám sát
Endpoint /metrics theo chuẩn Prometheus và không cần API key, nên bạn gắn thẳng vào hệ thống giám sát sẵn có.
prometheus.yml
# Prometheus: scrape số liệu vận hành XuniBOX (không cần API key)
scrape_configs:
- job_name: xunibox
metrics_path: /api/public/metrics
scheme: https
scrape_interval: 60s
static_configs:
- targets: ["xunibox.vn"]
# Cảnh báo gợi ý
groups:
- name: xunibox
rules:
- alert: XuniBoxDown
expr: xunibox_up == 0
for: 3m
annotations:
summary: "API XuniBOX không phản hồi quá 3 phút"
- alert: XuniBoxDatabaseSlow
expr: xunibox_database_response_seconds > 1.5
for: 5m
annotations:
summary: "Kho nhạc phản hồi chậm, cân nhắc phục vụ từ cache của bạn"Bảng thuật ngữ
| Thuật ngữ | Giải thích |
|---|---|
| track | Một bài nhạc trong kho XuniBOX. Định danh bằng UUID không đổi — đây là thứ duy nhất bạn nên lưu vào cơ sở dữ liệu của mình. |
| preview | Đoạn nhạc do admin cắt sẵn (15 / 30 / 60 giây) dành cho nền tảng đối tác. audio_url luôn trỏ tới đoạn này, không phải bản đầy đủ. |
| signed URL | Link media có chữ ký và hạn dùng. Hết hạn sau media_expires_in giây (mặc định 3600). Không lưu vào DB, lấy mới trước khi phát. |
| media_expires_in | Số giây còn lại của link media tính từ lúc phản hồi được tạo. |
| X-Total-Count | Tổng số bản ghi khớp bộ lọc, không phải số bản ghi trong trang hiện tại. |
| ETag | Dấu vân tay của nội dung. Gửi lại bằng If-None-Match để nhận 304 và không tốn băng thông. |
| cửa sổ hạn mức | Khoảng 60 giây trượt. X-RateLimit-Reset-After cho biết còn bao nhiêu giây tới lúc cửa sổ mở lại. |
| hạn mức theo key | Hiện chỉ áp dụng cho endpoint cần API key (/tracks/:id/watermarked): mặc định 60 request/phút mỗi key, admin có thể nâng riêng. Các endpoint đọc kho nhạc chưa tính hạn mức. |
| score | Điểm liên quan từ 0 đến 1 ở /search và /tracks/:id/similar. Dưới 0.2 bị loại khỏi kết quả. |
| ISRC | Mã định danh ghi âm quốc tế, dùng khi bạn phải báo cáo bản quyền cho bên thứ ba. |
| takedown | Yêu cầu gỡ bài. Khi nhận webhook track.deleted, bạn có 24 giờ để ngừng dùng bài cho nội dung mới. |
| proxy | Endpoint trung gian trên backend của bạn, gắn X-API-Key rồi mới gọi XuniBOX. Bắt buộc nếu client là trình duyệt hoặc app. |
Đã xong checklist? Đối chiếu lần cuối với trang lỗi & retry và chính sách phiên bản rồi theo dõi tình trạng hệ thống tại trang trạng thái.
Sẵn sàng tích hợp?
Gửi thông tin sản phẩm để admin XuniBOX xét duyệt và cấp API key.