# Liệt kê bộ phim

Trả về một trang các bộ phim tổ chức của bạn được cấp quyền, mỗi bộ kèm `content_version`. Dùng trong job đồng bộ CMS: khi `content_version` bằng giá trị bạn đã lưu thì không có gì đổi, bạn bỏ qua được [Lấy metadata một bộ phim](https://docs.wandura.ai/vi/developers/reference/series-get).

```
GET /api/delivery/v1/series
```

**Scope:** `metadata:read`

## Mô tả
Liệt kê các bộ bạn được cấp quyền, thay đổi cũ nhất trước. Gửi `updated_since` (giây Unix epoch) để chỉ nhận các bộ đổi sau mốc đó. Bộ hết giấy phép vẫn còn trong danh sách dạng `withdrawn` 30 ngày, để job đồng bộ của bạn kịp thấy. Response thành công được bọc trong envelope `{code, message, data, server_time}`; lỗi dùng cùng envelope nhưng không có `data`, trừ `429` và `400` `unsupported_version` dùng định dạng phẳng. Endpoint này dùng chung bộ đếm rate limit với [catalog](https://docs.wandura.ai/vi/developers/reference/catalog).

CMS của bạn được sửa đè bất kỳ trường nào. Wandura không bao giờ ghi đè bản sửa của bạn: lưu `content_version` đã nhập và giữ bản sửa của bạn.

## Tham số request
| Tên | Vị trí | Kiểu | Bắt buộc | Mô tả |
|---|---|---|---|---|
| `Authorization` | header | string | Có | `Bearer <API key>` của một key có scope `metadata:read`. |
| `updated_since` | query | integer | Không | Tuỳ chọn. Giây Unix epoch; chỉ trả bộ đổi sau mốc này. |
| `limit` | query | integer | Không | Tuỳ chọn. Số phần tử mỗi trang, 1 đến 100. Mặc định 50. |
| `cursor` | query | string | Không | Tuỳ chọn. `next_cursor` của trang trước, truyền lại nguyên vẹn. |
| `Wandura-Version` | header | string | Không | Tuỳ chọn. Một phiên bản API theo ngày (YYYY-MM-DD) dùng cho request này thay cho bản ghim vào API key của bạn. Giá trị lạ hoặc đã ngừng trả 400 với `error_code` `unsupported_version`. |

Giữ nguyên `updated_since` trên mọi trang của một lượt đồng bộ, và đi theo `next_cursor` tới khi nó là `null`.

## Ví dụ request
```bash
curl -s "https://www.wandura.ai/api/delivery/v1/series?updated_since=1790390000&limit=50" \
  -H "Authorization: Bearer $WANDURA_API_KEY"
```

## Response
`200 OK`. Trường mới có thể được thêm bất cứ lúc nào: bỏ qua trường bạn không biết.

| Trường | Kiểu | Mô tả |
|---|---|---|
| `code` | integer | `0`. |
| `message` | string | `"ok"`. |
| `data.next_cursor` | string hoặc null | Gửi lại làm `cursor`; `null` ở trang cuối. |
| `server_time` | integer | Giờ server tính bằng giây Unix epoch. |
| `links` | object | URL tuyệt đối dựng sẵn của một response dạng danh sách. Đi theo chúng thay vì tự ráp URL. |

### Các trường của một bộ (`data.items[]`)
| Trường | Kiểu | Mô tả |
|---|---|---|
| `code` | string | Mã bộ, ví dụ `WD000016`. |
| `status` | string | `active`: bạn đang được stream. `withdrawn`: giấy phép của bạn hết hạn hay bị tạm ngưng, hoặc Wandura gỡ bộ; bộ còn trong danh sách 30 ngày để job đồng bộ của bạn kịp thấy. Có thể có giá trị mới. |
| `updated_at` | integer | Lần đổi gần nhất tính bằng giây Unix epoch (metadata, giấy phép hoặc tập trong media space của bạn). |
| `content_version` | string hoặc null | Mã băm của mọi thứ GET /series/{code} trả cho bạn. Không đổi = không cần gọi chi tiết. `null` khi withdrawn. |
| `episode_count` | integer hoặc null | Số tập đã phát hành. `null` khi withdrawn. |
| `withdrawn_at` | integer hoặc null | Lúc bị gỡ (giây epoch), hoặc `null`. |
| `film_status` | string hoặc null | Trạng thái của phim trong kho Wandura: `published` (đã phát hành), `draft` (đang làm, chưa phát hành) hoặc `archived` (đã gỡ). Khác `status`, trường cho biết bạn có được stream hay không. Đã ra đủ tập dự kiến hay chưa là `is_completed`. Có thể có giá trị mới. |
| `tier` | string hoặc null | Hạng chất lượng của phim do Wandura chấm, `S` cao nhất tới `F` thấp nhất, hoặc `null` khi chưa chấm. Không phải phân loại độ tuổi (xem `content_rating`). |

## Ví dụ response
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "items": [
      {
        "code": "WD000016",
        "status": "active",
        "updated_at": 1790390000,
        "content_version": "c3f1a9e07b2d4c5e8f9a0b1c2d3e4f50",
        "episode_count": 60,
        "withdrawn_at": null,
        "film_status": "published",
        "tier": "A"
      },
      {
        "code": "WD000021",
        "status": "withdrawn",
        "updated_at": 1790395000,
        "content_version": null,
        "episode_count": null,
        "withdrawn_at": 1790395000,
        "film_status": "archived",
        "tier": null
      }
    ],
    "next_cursor": null
  },
  "server_time": 1790400000
}
```

## Header của response
| Header | Response | Mô tả |
|---|---|---|
| `Wandura-API-Status` | mọi response | Trạng thái API. Hiện là `beta`, ở mọi response, thành công hay lỗi. |
| `Wandura-Version` | 200 | Phiên bản API theo ngày (YYYY-MM-DD) mà response này dùng: bản ghim vào API key của bạn, hoặc bản bạn gửi trong header request `Wandura-Version`. Key tạo trước khi có phiên bản ngày dùng `2026-10-02`. |
| `Wandura-Request-Id` | 200 | Mã định danh mờ của request này (`req_` và 26 ký tự). Mọi response đều có, kể cả lỗi, và body lỗi lặp lại nó ở `request_id`. Hãy ghi log nó, và gửi kèm khi liên hệ Wandura về một request: nó tìm đúng request đó trong log của chúng tôi. Đừng phân tích chuỗi này. |
| `Cache-Control` | 200 | Luôn là `no-store`. Đừng lưu các response này trong cache dùng chung. |
| `Retry-After` | 429 | Số giây cần chờ trước khi thử lại. Có ở response 429 và các response 503 nên thử lại. |

## Lỗi
| Status | `code` | Khi nào |
|---|---|---|
| 400 | không có | Header `Wandura-Version`, hoặc bản ghim của key, là bản lạ hay đã ngừng. |
| 401 | 4010 | Thiếu header `Authorization: Bearer`. |
| 401 | 4011 | Key không tồn tại hoặc đã bị thu hồi. |
| 403 | 4030 | Key thiếu scope `metadata:read`. |
| 403 | 4031 | Quyền truy cập của tổ chức bạn đang bị tạm ngưng. |
| 422 | 4220 | `limit` không trong 1 đến 100, `updated_since` không phải giây epoch, hoặc `cursor` không phải giá trị endpoint này trả về. |
| 429 | không có | Đã chạm rate limit. |
| 503 | 5030 | Danh sách tạm thời không khả dụng. |
| 503 | 5031 | Wandura chưa kiểm được API key kịp thời. |

Xem [Lỗi](https://docs.wandura.ai/vi/developers/concepts/errors#series-errors) để biết cách xử lý từng trường hợp.
