REST API · v1

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.

Quy ước chung

Envelope

Mọi endpoint danh sách trả cùng một hình dạng: { data: [...], meta: { total, page, limit } }. Riêng /artists/:id/tracks có thêm khóa artist. Endpoint chi tiết trả thẳng object, không bọc data.

Phân trang

page bắt đầu từ 1 (tối đa 5000), limit mặc định 20 và trần 100. Dùng meta.total để biết khi nào dừng; đừng dựa vào việc mảng rỗng vì bạn sẽ tốn thêm một request.

Lặp hết một thể loại
async function fetchAllTracks(genre) {
  const limit = 100;             // trần cho phép
  let page = 1;
  const all = [];

  while (true) {
    const url = `https://xunibox.vn/api/public/tracks?genre=${encodeURIComponent(genre)}&sort=newest&page=${page}&limit=${limit}`;
    const res = await fetch(url, { headers: { "X-API-Key": XUNIBOX_API_KEY } });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);

    const { data, meta } = await res.json();
    all.push(...data);

    if (all.length >= meta.total || data.length === 0) break;
    page += 1;
  }

  return all;
}

Sắp xếp

Thứ tự luôn có tie-breaker theo id nên phân trang ổn định, không bị lặp hoặc rơi bản ghi giữa các trang.

sortÁp dụng choThứ tự thực tế
newest (mặc định)/tracks, /artists/:id/trackscreated_at giảm dần
oldest/tracks, /artists/:id/trackscreated_at tăng dần
popular/tracks, /artists/:id/tracksplay_count giảm dần, rồi created_at
title_asc / title_desc/tracks, /artists/:id/tracksTheo tên bài hát
name_asc (mặc định) / name_desc/artistsTheo tên nghệ sĩ
newest / oldest/artistscreated_at của nghệ sĩ

Bộ lọc và tìm kiếm

Tất cả bộ lọc chữ là tìm một phần (contains), không phân biệt hoa thường, có dấu tiếng Việt vẫn chạy. Ký tự cho phép: chữ, số, khoảng trắng và . ' ’ & + / -. Ký tự lạ như %, * hay dấu ngoặc sẽ bị trả 400 — nhớ encodeURIComponent giá trị người dùng nhập.

Tham sốEndpointGiới hạn
q/tracks, /artistsTìm đồng thời title + artist + genre (với /artists là tên). Tối đa 100 ký tự.
title/tracksTối đa 160 ký tự.
artist/tracksTối đa 120 ký tự.
genre/tracksTối đa 80 ký tự.
artist_id/tracksUUID chính xác, nhanh và chuẩn hơn lọc theo tên.
Kết hợp nhiều bộ lọc là phép AND. ?q=hè&genre=Pop nghĩa là “có chữ hè” “thể loại chứa Pop”.

Cache và ETag

Mọi response 200 đều có Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=600 và một ETag yếu tính từ nội dung JSON. Gửi lại ETag qua If-None-Match, nếu dữ liệu chưa đổi bạn nhận 304 không body — nhanh hơn và không tốn băng thông. Lỗi (4xx/5xx) luôn là no-store.

Dùng lại ETag
let cached = { etag: null, body: null };

async function getGenres() {
  const res = await fetch(`https://xunibox.vn/api/public/genres`, {
    headers: {
      "X-API-Key": process.env.XUNIBOX_API_KEY,
      ...(cached.etag ? { "If-None-Match": cached.etag } : {})
    }
  });

  if (res.status === 304) return cached.body;   // dữ liệu chưa đổi

  cached = { etag: res.headers.get("ETag"), body: await res.json() };
  return cached.body;
}
Cửa sổ cache cố tình ngắn hơn hạn 1 giờ của signed URL, nên response trong cache luôn còn media dùng được. Đừng tự đặt cache dài hơn ở phía bạn.

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.

Xin quyền tích hợp