Khái niệm cốt lõi
Lỗi
Tick Up dùng status code HTTP quy ước. Mọi lỗi đều trả về body JSON có trường `detail` — hoặc là chuỗi cho lỗi đơn giản, hoặc là mảng cho lỗi validation.
Status code
Bạn sẽ gặp các code này:
| Code | Ý nghĩa |
|---|---|
200 OK | Request thành công. |
201 Created | Một tài nguyên đã được tạo. Body chứa tài nguyên mới. |
204 No Content | Request thành công; không có gì để trả về. |
400 Bad Request | Request sai định dạng — JSON xấu, sai kiểu, thiếu header. |
401 Unauthorized | Access token thiếu, sai định dạng, hoặc đã hết hạn. |
403 Forbidden | Đã xác thực, nhưng role của token không được phép thực hiện hành động này — hoặc gói tenant không bao gồm. |
404 Not Found | Tài nguyên không tồn tại (hoặc không tồn tại trong tenant của bạn). |
409 Conflict | Request xung đột với trạng thái hiện tại (ví dụ ứng viên trùng lặp, slug đã được dùng, không thể xóa mềm bản ghi có phụ thuộc). |
412 Precondition Failed | Điều kiện If-Unmodified-Since không thỏa — bản ghi đã bị người khác sửa. |
422 Unprocessable Entity | Body parse được, nhưng giá trị không hợp lệ. Xem lỗi validation bên dưới. |
429 Too Many Requests | Bạn đã chạm giới hạn tốc độ. Thử lại sau header Retry-After. |
500 Internal Server Error | Lỗi của chúng tôi, không phải của bạn. Đã log vào Sentry kèm request ID — hãy đính kèm khi báo bug. |
503 Service Unavailable | Một hệ thống downstream (database, parser) đang lỗi. Coi như tạm thời và thử lại với backoff. |
Lỗi đơn giản
Với tất cả các lỗi trừ lỗi validation, body là một object có chuỗi detail:
{ "detail": "Candidate not found" }Lỗi validation
Khi body request parse được nhưng không qua được Pydantic validation, body là 422 Unprocessable Entity kèm danh sách lỗi theo từng trường. Tick Up viết lại các thông báo mặc định của Pydantic thành dạng dễ đọc:
json
{
"detail": [
{
"loc": ["body", "email"],
"msg": "Email is required",
"type": "missing"
},
{
"loc": ["body", "full_name"],
"msg": "Full name must be at most 200 characters",
"type": "string_too_long"
}
]
}Mỗi entry có ba trường:
loc— đường dẫn đến giá trị sai, bắt đầu bằngbody,query, hoặcpath.msg— giải thích dễ đọc, an toàn để hiển thị cho người dùng cuối.type— nhãn lỗi đọc được bằng máy. Dùng để rẽ nhánh logic trong client của bạn (ví dụ phân biệtmissingvớistring_too_short).
Truy vết request lỗi
Mỗi phản hồi có header X-Request-ID. Khi báo vấn đề cho support, hãy đính kèm request ID — chúng tôi dùng nó để tìm chính xác request trong log.
http
HTTP/1.1 500 Internal Server Error
content-type: application/json
x-request-id: req_2QyZ0BkS7vM3a8tFChiến lược retry
- Lỗi idempotent (
500,502,503,504) trên requestGET— thử lại với exponential backoff: 1s, 2s, 4s, rồi bỏ cuộc. - Giới hạn tốc độ (
429) — đọc headerRetry-After(giây) và chờ ít nhất chừng đó. - Lỗi xác thực (
401vớiToken expired) — refresh access token một lần, rồi thử lại. Nếu lần thứ hai vẫn lỗi, hiển thị cho người dùng. - Lỗi validation (
4xx) — không retry. Sửa request.