# Tài liệu tham chiếu API

Wandura Delivery API cho phép backend của bạn đọc các phim bạn được cấp phép, xin playback cho từng tập một, và đồng bộ các ad creative đã duyệt. Phần này mô tả từng endpoint. Về luồng tích hợp, hãy bắt đầu với [Bắt đầu nhanh](https://docs.wandura.ai/vi/developers/quickstart), [Xác thực](https://docs.wandura.ai/vi/developers/authentication) và [Playback](https://docs.wandura.ai/vi/developers/concepts/playback).

## Base URL

```
https://www.wandura.ai
```

Luôn gọi `www.wandura.ai`. Tên miền trần `wandura.ai` trả mọi request bằng một redirect `308` sang `www`, và một số HTTP client làm rơi body hoặc header của `POST` khi đi theo redirect.

## Endpoint

| Method | Path | Scope | Trang |
|---|---|---|---|
| `GET` | `/api/delivery/v1/catalog` | `metadata:read` | [Lấy catalog được cấp phép](https://docs.wandura.ai/vi/developers/reference/catalog) |
| `POST` | `/api/delivery/v1/playback` | `playback` | [Xin playback](https://docs.wandura.ai/vi/developers/reference/playback) |
| `GET` | `/api/delivery/v1/creatives` | `creatives:export` | [Liệt kê creative](https://docs.wandura.ai/vi/developers/reference/creatives-list) |
| `GET` | `/api/delivery/v1/creatives/{id}` | `creatives:export` | [Lấy một creative](https://docs.wandura.ai/vi/developers/reference/creatives-get) |

Mọi đường dẫn khác dưới `/api/delivery/v1/`, với bất kỳ method nào, trả `404` kèm body JSON phẳng và `error_code` `not_found`. Nếu gặp nó ở một đường dẫn bạn tưởng là đúng, hãy soát lỗi gõ trong đường dẫn.

## Chỉ server-to-server

Gọi các endpoint này từ backend, không bao giờ từ trình duyệt hay app di động. Chúng không gửi header CORS, và API key không bao giờ được nằm trong client.

## Xác thực

Gửi API key dưới dạng bearer token ở mọi request:

```
Authorization: Bearer <your API key>
```

Mỗi key thuộc về một tổ chức và mang một hoặc nhiều scope. Key bị thiếu, không tồn tại hoặc đã thu hồi nhận `401`. Key hợp lệ nhưng thiếu scope của endpoint nhận `403`.

| Scope | Cấp quyền | Cách lấy |
|---|---|---|
| `metadata:read` | [Lấy catalog được cấp phép](https://docs.wandura.ai/vi/developers/reference/catalog) | Tự tạo trên partner portal |
| `creatives:export` | [Liệt kê creative](https://docs.wandura.ai/vi/developers/reference/creatives-list), [Lấy một creative](https://docs.wandura.ai/vi/developers/reference/creatives-get) | Tự tạo trên partner portal |
| `webhooks:manage` | Chưa có endpoint nào dùng | Tự tạo trên partner portal |
| `playback` | [Xin playback](https://docs.wandura.ai/vi/developers/reference/playback) | Tự tạo trên partner portal (**Stream films in an app**) |

Thành viên tổ chức có vai trò **Admin** hoặc **Developer** tạo, xoay vòng và thu hồi key trên trang **Developers** của partner portal. Key đầy đủ chỉ hiện một lần, lúc tạo. Kể cả key có scope `playback`: nếu key bị lộ, bất kỳ ai cũng stream được phim bạn được cấp phép, nên hãy thu hồi ngay. Xem [Xác thực](https://docs.wandura.ai/vi/developers/authentication).

## Phiên bản

Phiên bản API nằm trong path (`/v1`). Trong cùng một phiên bản, Wandura có thể thêm trường response mới và mã lỗi mới mà không báo trước. Hãy bỏ qua các trường bạn không nhận ra, và luôn có nhánh mặc định cho mã lỗi lạ. Thế nào là phá vỡ tương thích, và phiên bản cũ được hỗ trợ bao lâu: [Phiên bản và ngừng hỗ trợ](https://docs.wandura.ai/vi/developers/concepts/versioning).

Bản ghi creative còn mang trường `schema_version`, hiện là `1`. Trường được bổ sung thêm không làm thay đổi giá trị này.

### Beta
API đang ở bản **beta**. Mọi response từ `/v1` đều mang header `Wandura-API-Status: beta`. Trong giai đoạn beta, Wandura vẫn có thể đổi cách hoạt động bên trong `/v1`; các thay đổi được ghi ở **Nhật ký thay đổi** (link cuối mọi trang). Thấy chỗ sai hoặc thiếu? Bấm **Gửi góp ý** ở đầu mọi trang docs.

## Request và response

- Body của request và response là JSON. Gửi `Content-Type: application/json` với `POST`.
- ID của phim, tập và creative là chuỗi UUID.
- Playback trả `expires_at` dạng timestamp ISO 8601 theo UTC. Endpoint creatives trả timestamp dạng giây Unix epoch.
- Endpoint creatives gửi `Cache-Control: no-store`. Đừng cache response của chúng trong cache dùng chung.

## Pagination

Chỉ [Liệt kê creative](https://docs.wandura.ai/vi/developers/reference/creatives-list) có phân trang. Endpoint này dùng `cursor` opaque và trả `next_cursor` cho đến khi hết bản ghi. [Lấy catalog được cấp phép](https://docs.wandura.ai/vi/developers/reference/catalog) trả toàn bộ catalog trong một response.

## Lỗi

API dùng hai định dạng lỗi. Endpoint catalog và playback trả về một object phẳng:

```json
{
  "error": "Episode not found or not ready to stream",
  "error_code": "not_ready"
}
```

| Trường | Kiểu | Mô tả |
|---|---|---|
| `error` | string | Thông điệp cho người đọc. Đừng parse. Một ngoại lệ: `403` của catalog không có `error_code`, và `error` đúng bằng `org_suspended` khi tổ chức bạn bị tạm ngưng. Xem [Liệt kê catalog có giấy phép](https://docs.wandura.ai/vi/developers/reference/catalog#errors). |
| `error_code` | string | Mã máy đọc được. Rẽ nhánh theo trường này. Một số lỗi không có trường này, ví dụ `401`. |
| `reason` | string | Có mặt cùng `not_entitled`. Lý do chi tiết, dùng cho log và hỗ trợ. |

Endpoint creatives bọc mọi response, dù thành công hay lỗi, trong một envelope có `code` dạng số:

```json
{
  "code": 4011,
  "message": "Invalid or revoked API key",
  "server_time": 1790679032
}
```

| Trường | Kiểu | Mô tả |
|---|---|---|
| `code` | integer | `0` khi thành công. Mã lỗi bốn chữ số trong trường hợp khác. |
| `message` | string | `"ok"` khi thành công, thông điệp cho người đọc trong trường hợp khác. |
| `data` | object | Chỉ có khi thành công. |
| `server_time` | integer | Giờ server tính bằng giây Unix epoch. |

Trang của từng endpoint liệt kê lỗi của endpoint đó. Về hướng dẫn retry và danh sách đầy đủ, xem [Lỗi](https://docs.wandura.ai/vi/developers/concepts/errors).

## Rate limit

Mỗi tổ chức có một ngưỡng chống lạm dụng cho từng nhóm endpoint, đếm trong một cửa sổ cố định 60 giây: 10.800 request playback (khoảng 180 vé mỗi giây), 3.000 request catalog và 3.000 request creatives, mỗi nhóm một bộ đếm riêng. Chạm ngưỡng thường có nghĩa là có vòng lặp chạy mất kiểm soát. Wandura nâng được bất kỳ ngưỡng nào riêng cho tổ chức của bạn khi bạn yêu cầu, có hiệu lực trong khoảng một phút. Các header giới hạn dưới đây chỉ xuất hiện trên response `429`.

Khi bạn chạm ngưỡng, mọi endpoint, kể cả endpoint creatives, đều trả `429` với body phẳng:

```json
{
  "error": "Too many playback requests for this account. This is an abuse ceiling, not a quota — if a normal integration reaches it, contact us and it will be raised.",
  "error_code": "rate_limited"
}
```

| Header | Mô tả |
|---|---|
| `Retry-After` | Số giây cho đến khi cửa sổ hiện tại reset. |
| `X-RateLimit-Limit` | Số request được phép trong mỗi cửa sổ cho nhóm endpoint này. |
| `X-RateLimit-Window` | Độ dài cửa sổ tính bằng giây. |

Chờ hết `Retry-After` rồi mới retry. Xem [Rate limit](https://docs.wandura.ai/vi/developers/concepts/rate-limits#limits).
