# Lỗi > Định dạng lỗi, mọi mã trạng thái và code mà API trả về, lỗi nào nên thử lại, và một hàm xử lý lỗi Node bạn có thể sao chép ngay. Khi một request thất bại, API trả về mã trạng thái 4xx hoặc 5xx và một body JSON với `code` ổn định. Hãy rẽ nhánh theo `code`. Nội dung `error` dành cho con người và có thể thay đổi. ## Định dạng ```json { "error": "This API key doesn't have the earnings:read scope.", "code": "insufficient_scope", "scope": "earnings:read" } ``` | Trường | Luôn có | Ý nghĩa | | --- | --- | --- | | `error` | Có | Mô tả sự cố bằng lời. Có thể ghi log hoặc hiển thị cho người vận hành. | | `code` | Có | Một code ổn định. Xem các bảng bên dưới. | | `field` | Khi là `invalid` | Parameter hoặc trường trong body gây lỗi. | | `scope` | Khi là `insufficient_scope` | Scope mà key cần có. | Một vài lỗi có thêm trường riêng. Ví dụ, `409 upload_incomplete` liệt kê các phần `missing` và `wrong_size`. ## Lỗi mà mọi endpoint đều có thể trả về | Mã trạng thái | `code` | Ý nghĩa | Thử lại? | | --- | --- | --- | --- | | 400 | `invalid` | Một parameter bị sai. `field` cho biết parameter nào. | Không. Hãy sửa request. | | 401 | `unauthenticated` | Không có header `Authorization: Bearer`. | Không | | 401 | `invalid_key` | Key không tồn tại. | Không | | 401 | `key_revoked` | Key đã bị thu hồi. Hãy tạo key mới. | Không | | 401 | `key_expired` | Key đã hết hạn. Hãy tạo key mới. | Không | | 401 | `test_keys_retired` | Một key `hm_test_`, đã ngừng sử dụng từ 12/10/2026. Hãy dùng key `hm_live_`. | Không | | 403 | `insufficient_scope` | Key thiếu scope mà endpoint này cần. `scope` cho biết scope nào. | Không | | 403 | `account_inactive` | Tài khoản của bạn không hoạt động. | Không | | 403 | `api_not_in_plan` | Gói của bạn không bao gồm API. API đi kèm Enterprise và Custom. | Không | | 404 | `not_found` | Không có endpoint này, hoặc đối tượng không thuộc về bạn. | Không | | 429 | `rate_limited` | Vượt giới hạn mỗi phút của key này. | Có, sau `Retry-After` giây | | 500 | `server_error` | Có sự cố ở phía chúng tôi. | Có, với backoff | `404 not_found` bao gồm cả trường hợp "không tồn tại" lẫn "thuộc về tài khoản khác". API không bao giờ cho bạn biết một bản phát hành của người khác có tồn tại hay không. ## Lỗi của từng endpoint cụ thể | Mã trạng thái | `code` | Ở đâu | Ý nghĩa | | --- | --- | --- | --- | | 409 | `exists` | `POST /members/invite` | Đã có tài khoản với email này. | | 413 | `too_large` | `POST /ddex/validate` | Lớn hơn mức một lần kiểm thử nhận được. Hãy phân phối bằng `POST /ddex`. | | 413 | `too_large` | `POST /ddex` | Quá 20 GB (body thô) hoặc 512 MB (multipart). Hãy dùng tải lên trực tiếp. | | 429 | `busy` | `POST /ddex/validate` | Quá nhiều lần kiểm thử cùng lúc. Hãy thử lại sau ít phút. | | 409 | `upload_incomplete` | `POST /ddex/uploads/{id}/commit` | Thiếu phần hoặc phần sai kích thước. Hãy tải chúng lên, rồi commit lại. | | 409 | `already_committed` | Tải lên trực tiếp | Đã commit trước đó. `status_url` trỏ đến lần phân phối. | | 409 | `commit_in_progress` | `POST /ddex/uploads/{id}/commit` | Một lần commit khác của bản tải lên này đang chạy. | | 400 | `invalid_url` | `POST /webhooks`, `PATCH /webhooks/{id}` | Không phải URL https công khai trên cổng 443. | | 409 | `too_many` | `POST /webhooks` | Bạn đã có 20 endpoint. | | 409 | `endpoint_disabled` | Gửi test và gửi lại webhook | Endpoint đang tắt. Hãy bật nó trước. | Mỗi [trang tham chiếu](https://developer.hillsmusic.com/vi/reference/releases/) liệt kê lỗi của từng endpoint. [Scope và lỗi](https://developer.hillsmusic.com/vi/reference/scopes-and-errors/) có các lỗi dùng chung. ## Lỗi kiểm tra dữ liệu Một lỗi `400 invalid` nêu vấn đề đầu tiên mà API tìm thấy: ```json { "error": "updated_since is an ISO date or time.", "code": "invalid", "field": "updated_since" } ``` Mỗi lần chỉ báo một trường. Hãy sửa rồi gửi lại. Nếu bạn xây dựng biểu mẫu trên API, hãy hiển thị `error` cạnh ô nhập được nêu trong `field`. Tệp DDEX thì khác. Một lô DDEX có vấn đề không phải là lỗi `400`. Lần kiểm thử trả về `200` với mọi bước kiểm tra và một kết luận, còn một lần phân phối trả về `202` và báo vấn đề theo từng bản phát hành. Xem [Phân phối DDEX](https://developer.hillsmusic.com/vi/guides/ddex/). ## Nên thử lại lỗi nào - **Thử lại** `429` và `5xx`, cùng các lỗi mạng như timeout và reset. - **Không thử lại** các lỗi `4xx` khác. Cùng một request sẽ nhận cùng một phản hồi. Hãy sửa request, key hoặc scope của key trước. Với `429`, hãy chờ số giây ghi trong `Retry-After`. Với `5xx`, hãy chờ lâu hơn sau mỗi lần thử (1 giây, 2 giây, 4 giây…) và dừng lại sau vài lần. Xem [Rate limit](https://developer.hillsmusic.com/vi/guides/rate-limits/). Thao tác đọc có thể thử lại an toàn. Hãy cân nhắc trước khi thử lại một thao tác ghi. Gửi lại `POST /ddex` sau khi mất phản hồi có thể đưa lô vào hàng đợi hai lần. Hãy kiểm tra `GET /ddex` trước. ## Hàm xử lý lỗi cho Node ```js export class HillsError extends Error { constructor(status, body, headers) { super(body.error ?? `HTTP ${status}`); this.status = status; this.code = body.code; this.field = body.field; this.scope = body.scope; this.retryAfter = Number(headers.get("Retry-After")) || null; } } const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); export async function hills(path, init = {}, tries = 4) { for (let i = 1; ; i++) { const res = await fetch("https://api.hillsmusic.com/v1" + path, { ...init, headers: { ...init.headers, Authorization: `Bearer ${process.env.HILLS_API_KEY}` }, }); const body = await res.json().catch(() => ({})); if (res.ok) return body; const err = new HillsError(res.status, body, res.headers); const retryable = res.status === 429 || res.status >= 500; if (!retryable || i >= tries) throw err; await sleep(err.retryAfter ? err.retryAfter * 1000 : 1000 * 2 ** (i - 1)); } } try { await hills("/earnings"); } catch (err) { if (err.code === "insufficient_scope") console.error(`Add ${err.scope} to this key.`); else if (err.code === "api_not_in_plan") console.error("The plan doesn't include the API."); else throw err; } ``` Với curl, thêm `-w '%{http_code}'` để xem mã trạng thái, hoặc `-i` để xem các header: ```bash curl -i "https://api.hillsmusic.com/v1/releases/999999" \ -H "Authorization: Bearer $HILLS_API_KEY" # HTTP/2 404 # {"error":"…","code":"not_found"} ``` Nguồn: https://developer.hillsmusic.com/vi/guides/errors/