HTTP status codes
Tham chiếu đầy đủ HTTP status codes Zorio API trả về và cách CRM xử lý.
2xx — Thành công
| HTTP | Khi nào | Body |
|---|---|---|
| 200 OK | Đa số request GET / PUT / DELETE thành công | { "data": {} } hoặc list paginated |
| 201 Created | POST tạo resource mới | { "data": { "id": ..., "..." } } |
| 202 Accepted | Action async đã enqueue (vd click-to-call, import lead) | { "data": { "call_uuid": "...", "status": "queued" } } |
3xx — Redirect
| HTTP | Khi nào | Body |
|---|---|---|
| 302 Found | /api/pbx/cdr/{uuid}/recording redirect tới signed URL | Empty body, header Location: <signed URL> |
4xx — Lỗi từ client
400 Bad Request
Request không hợp lệ ở mức HTTP (JSON malformed, missing required header, ...).
{ "message": "Malformed request body" }Xử lý: kiểm tra JSON đã đúng + header Content-Type: application/json đầy đủ.
401 Unauthorized
Token thiếu / sai / expired.
{ "message": "Unauthenticated." }Xử lý: redirect user đến trang login lấy token mới. KHÔNG hardcode token trong frontend.
403 Forbidden
Token hợp lệ nhưng thiếu permission.
{ "message": "This action is unauthorized." }Xử lý: ghi log + báo admin cấp thêm permission cho user (vd pbx_api_access, telesales_api_access).
404 Not Found
Resource không tồn tại trong dữ liệu của khách hàng.
{ "message": "Resource not found" }Bảo mật
Khi gửi token sai khách hàng (vd tài khoản A truy vấn data của tài khoản B) — Zorio cũng trả 404 thay vì 403 để không leak existence của resource. CRM không phân biệt được 2 case này.
409 Conflict
State machine vi phạm hoặc unique constraint conflict.
{ "message": "Extension đã tồn tại trong queue này." }Xử lý: refresh state local + thông báo user.
422 Unprocessable Entity
Validation lỗi — body parse OK nhưng giá trị field không hợp lệ.
{
"message": "The given data was invalid.",
"errors": {
"extension_number": ["Định dạng số máy nhánh không hợp lệ."],
"outbound_caller_id": ["Giá trị đã chọn cho outbound caller id không hợp lệ."]
}
}Xử lý:
- Lặp qua
errorsobject, hiển thị error message bên cạnh field tương ứng trên UI. - Nếu là form submit — không refresh trang, giữ state cũ của user.
429 Too Many Requests
Vượt rate limit.
{ "message": "Too many requests. Retry after 25 seconds." }Header trả về:
Retry-After: 25
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1782706011Xử lý: backoff theo Retry-After. Triển khai exponential backoff + jitter để tránh thundering herd.
5xx — Lỗi từ server
500 Internal Server Error
Lỗi bất ngờ ở backend.
{ "message": "Internal server error" }Xử lý: retry với exponential backoff (3 lần, 1s / 4s / 16s). Nếu vẫn 500 → báo team support Zorio kèm X-Request-Id (nếu có) hoặc timestamp request.
502 Bad Gateway
Lỗi tầng dưới — phổ biến nhất:
- Click-to-call: Zorio PBX không tiếp nhận originate (có thể PBX restart).
{ "message": "PBX không tiếp nhận originate cuộc gọi. Vui lòng thử lại." }Xử lý: retry sau vài giây. Nếu vẫn 502 → escalate.
503 Service Unavailable
Hệ thống đang bảo trì hoặc quá tải tạm thời.
{ "message": "Service temporarily unavailable" }Header Retry-After: <giây> cho biết thời gian gợi ý retry.
504 Gateway Timeout
Upstream timeout. Hiếm gặp.
Best practice
Always handle 4xx + 5xx
Mọi API call PHẢI có error handler. KHÔNG assume "200 OK by default".
Phân biệt retry-able vs non-retry-able
| Status | Retry? | Lý do |
|---|---|---|
| 4xx (trừ 408, 429) | Không | Lỗi do client — retry không đổi kết quả |
| 408 Request Timeout | Có (1-3 lần) | Có thể do network |
| 429 Too Many Requests | Có (sau Retry-After) | Backoff theo header |
| 500, 502, 503, 504 | Có (exponential backoff) | Server lỗi tạm thời |
Trace request
Header response: X-Request-Id: <uuid> — copy vào ticket support khi báo lỗi, team Zorio dùng để trace nguyên nhân nhanh.
Network error vs HTTP error
Network error (DNS fail, connection refused, TLS error) KHÔNG phải HTTP status code — không có body. Cần catch riêng:
try {
const res = await fetch(url, opts);
if (!res.ok) {
// HTTP error 4xx / 5xx
}
} catch (err) {
// Network error
}