API Reference
API Reference
Toàn bộ API công khai nằm ở https://api.chattudong.com. Endpoint gọi model được thiết kế tương thích OpenAI nên bạn dùng lại thư viện sẵn có, không phải học gì mới.
Xác thực
Mọi request tới /v1 phải mang API key của tổ chức. Tạo key trong dashboard ở Cài đặt → Khoá API (/dashboard/cai-dat). Key có dạng ck_live_… cho môi trường thật và ck_test_… cho môi trường thử.
Authorization: Bearer ck_live_xxxxxxxxxxxxxxxxxxxxxxxx
# Hoặc, nếu thư viện của bạn không cho đổi header Authorization:
X-Api-Key: ck_live_xxxxxxxxxxxxxxxxxxxxxxxxVài điều nên biết trước khi tích hợp:
- Key thô chỉ hiện đúng một lần lúc tạo. Cơ sở dữ liệu chỉ lưu SHA-256 của key, nên không có đường “xem lại”. Mất thì thu hồi và tạo cái mới.
- Key gắn với tổ chức, không gắn với người. Nhân sự nghỉ việc không làm chết tích hợp.
- Đặt được
scopesvà số ngày hết hạn khi tạo. Key thiếu scope sẽ nhận403 insufficient_scope. - Thu hồi có hiệu lực ngay ở request kế tiếp.
GET /v1/models
Trả về danh sách model đang bật cho tổ chức bạn, theo đúng khung list của OpenAI và có thêm vài trường riêng để bạn dựng giao diện chọn model.
curl https://api.chattudong.com/v1/models \
-H "Authorization: Bearer $CHATLY_API_KEY"{
"object": "list",
"data": [
{
"id": "local/gemma-3-12b",
"object": "model",
"created": 1750000000,
"owned_by": "local",
"display_name": "Gemma 3 12B",
"friendly_name": "Tiết kiệm",
"tier": "economy",
"context_window": 128000,
"vn_hosted": true
}
]
}owned_by là provider: openai, anthropic, google, xai hoặc local. vn_hosted cho biết model chạy trên máy chủ đặt tại Việt Nam — dùng để lọc khi tổ chức yêu cầu dữ liệu không rời lãnh thổ.
POST /v1/chat/completions
Endpoint chính. Nhận đúng định dạng OpenAI; những trường lạ trong body được bỏ qua thay vì báo lỗi, nên SDK phiên bản mới hơn cũng không làm hỏng tích hợp.
Tham số
| Tên | Kiểu | Ghi chú |
|---|---|---|
| model | string · bắt buộc | Id model lấy từ GET /v1/models, ví dụ local/gemma-3-12b. |
| messages | array · bắt buộc | Tối thiểu 1 phần tử. Mỗi phần tử có role (system | user | assistant | tool) và content dạng chuỗi, tối đa 200.000 ký tự. |
| temperature | number · 0…2 | Càng thấp càng bám sát tài liệu. Bỏ trống thì dùng mặc định của model. |
| max_tokens | integer · 1…200000 | Trần token sinh ra. Cũng là trần chi phí ước tính bị giữ trước. |
| top_p | number · 0…1 | Nucleus sampling. Thường chỉ chỉnh một trong hai: top_p hoặc temperature. |
| stop | string[] | Danh sách chuỗi dừng. |
| stream | boolean | true để nhận SSE từng mẩu thay vì đợi trả lời đầy đủ. |
Header tuỳ chọn
| Header | Tác dụng |
|---|---|
| x-chatly-use-byok | Đặt true để dùng khoá provider riêng của tổ chức — lần gọi đó không trừ credits. Xem BYOK. |
| Idempotency-Key | Dùng trên các request có tính tiền để gửi lại an toàn sau khi mạng đứt. Gửi lại cùng khoá với nội dung khác sẽ nhận 409 idempotency_key_reused. |
Ví dụ — không streaming
curl https://api.chattudong.com/v1/chat/completions \
-H "Authorization: Bearer $CHATLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "local/gemma-3-12b",
"messages": [
{"role": "system", "content": "Bạn là trợ lý của một cửa hàng thời trang. Trả lời ngắn gọn, lịch sự."},
{"role": "user", "content": "Shop mở cửa mấy giờ?"}
],
"temperature": 0.3,
"max_tokens": 512
}'{
"id": "chatcmpl-…",
"object": "chat.completion",
"created": 1750000000,
"model": "local/gemma-3-12b",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Shop mở cửa từ 9h đến 21h mỗi ngày ạ." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 48, "completion_tokens": 17, "total_tokens": 65 },
"chatly": { "charged_micros": "1830", "byok": false }
}Khối chatly là phần mở rộng ngoài chuẩn OpenAI: charged_micros là số tiền đã trừ tính theo micro (một phần triệu đơn vị tiền, trả về dạng chuỗi để không mất chính xác), byok cho biết lần gọi đó có dùng khoá riêng của bạn hay không. SDK OpenAI bỏ qua trường lạ nên khối này không làm hỏng gì.
Ví dụ — streaming (SSE)
Đặt "stream": true. Phản hồi là chuỗi sự kiện chat.completion.chunk: mẩu đầu mang role, các mẩu sau mang delta.content, mẩu áp chót mang finish_reason, mẩu cuối mang usage để bạn đối soát, rồi kết thúc bằng [DONE].
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Shop mở cửa"},"finish_reason":null}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":48,"completion_tokens":17,"total_tokens":65},"chatly":{"charged_micros":"1830","byok":false}}
data: [DONE]Hình dạng lỗi
Mọi lỗi ra khỏi API đều có cùng một hình dạng. Đây là hợp đồng: bạn switch-case theo error.code được, không phải parse chuỗi tiếng Việt.
{
"error": {
"code": "insufficient_credits",
"message": "Ví của tổ chức không đủ credits cho lần gọi này",
"field": "model", // chỉ có khi lỗi validate
"docsUrl": "https://chattudong.com/docs/api-reference", // chỉ có khi trỏ được tới mục cụ thể
"retryAfter": 42, // chỉ có với 429 / 503, đơn vị giây
"requestId": "req_…" // LUÔN có
}
}code— mã ổn định, xem bảng bên dưới. Đổi tên mã là breaking change nên chúng tôi không đổi lặng lẽ.message— viết cho người đang đọc log lúc 2 giờ sáng: nói rõ chuyện gì xảy ra và làm gì tiếp theo.requestId— dán vào ticket hỗ trợ, chúng tôi tra được đúng request đó.- Với
429và503, giá trịretryAftercũng được trả ở header HTTPRetry-After.
Bảng mã lỗi đầy đủ
Đây là toàn bộ mã lỗi công khai, không có mã nào nằm ngoài bảng này.
| Mã | HTTP | Nghĩa và cách xử lý |
|---|---|---|
| invalid_request | 400 | Body hoặc tham số không hợp lệ. Trường sai được ghi ở error.field. |
| unsupported_model | 400 | Model không tồn tại hoặc tổ chức của bạn chưa được bật. Tra lại bằng GET /v1/models. |
| context_too_long | 400 | Tổng hội thoại vượt cửa sổ ngữ cảnh của model. Cắt bớt lịch sử hoặc đổi model có context lớn hơn. |
| unauthenticated | 401 | Thiếu thông tin xác thực — không có API key và cũng không có phiên đăng nhập hợp lệ. |
| invalid_api_key | 401 | Key sai định dạng, không tồn tại hoặc đã hết hạn. |
| api_key_revoked | 401 | Key từng hợp lệ nhưng đã bị thu hồi. Tạo key mới trong Cài đặt. |
| insufficient_scope | 403 | Key hợp lệ nhưng không có scope cần thiết cho thao tác này. |
| forbidden | 403 | Không đủ quyền — sai vai trò, hoặc tài nguyên thuộc tổ chức khác. |
| insufficient_credits | 402 | Ví hết tiền. Nạp thêm rồi gọi lại; chúng tôi không ghi nợ. |
| organization_suspended | 402 | Tổ chức đang bị tạm ngưng. Liên hệ hỗ trợ để mở lại. |
| plan_limit_exceeded | 402 | Chạm hạn mức của gói hiện tại (số kênh, dung lượng kho kiến thức…). |
| not_found | 404 | Không có tài nguyên với id đó trong tổ chức của bạn. |
| conflict | 409 | Xung đột trạng thái — thường là trùng tên hoặc bản ghi đã tồn tại. |
| idempotency_key_reused | 409 | Idempotency-Key đã dùng cho một request có nội dung khác. Đổi khoá mới. |
| channel_needs_reauth | 422 | Token của kênh hết hạn hoặc bị thu hồi phía nền tảng. Kết nối lại kênh. |
| service_window_expired | 422 | Quá cửa sổ được phép nhắn chủ động của nền tảng (ví dụ 24 giờ của Meta). |
| template_required | 422 | Ngoài cửa sổ dịch vụ, nền tảng chỉ cho gửi mẫu tin đã duyệt. |
| rate_limited | 429 | Vượt số yêu cầu mỗi phút của gói. Xem header Retry-After rồi thử lại. |
| internal_error | 500 | Lỗi phía chúng tôi. Gửi error.requestId cho hỗ trợ để tra đúng dòng log. |
| provider_error | 502 | Nhà cung cấp model trả lỗi, hoặc provider chưa được cấu hình khoá. |
| provider_overloaded | 503 | Nhà cung cấp đang quá tải. Thử lại sau, có thể kèm backoff. |
| provider_timeout | 504 | Nhà cung cấp không phản hồi kịp. Thử lại hoặc giảm max_tokens. |
Giới hạn tần suất
Giới hạn tính theo tổ chức, cửa sổ cố định 60 giây. Số yêu cầu mỗi phút phụ thuộc gói bạn đang dùng; vượt thì nhận 429 rate_limited kèm Retry-After cho biết còn bao nhiêu giây nữa sang cửa sổ mới.
Cách xử lý đúng là đợi đúng Retry-After rồi thử lại, có jitter nếu bạn chạy nhiều worker song song. Đừng thử lại ngay lập tức trong vòng lặp — cửa sổ chưa đổi thì kết quả vẫn thế.
Các nhóm endpoint khác
Ngoài /v1, API còn các nhóm phục vụ dashboard và tích hợp sâu hơn. Chúng dùng phiên đăng nhập hoặc API key có scope tương ứng:
| Nhóm | Dùng để |
|---|---|
| /api-keys | Tạo, liệt kê và thu hồi API key của tổ chức. |
| /provider-keys | Quản lý khoá BYOK — chỉ vai trò quản trị trở lên. |
| /agents | Trợ lý: model, chỉ dẫn hệ thống, kho kiến thức gắn kèm. |
| /knowledge-bases | Kho kiến thức và tài liệu bên trong. |
| /channels | Kênh nhắn tin và thông tin kết nối nền tảng. |
| /conversations | Hội thoại, tin nhắn, chuyển cho nhân viên. |
| /wallet | Số dư, lịch sử giao dịch, chi phí từng lần gọi model. |
| /widget/{channelId} | API công khai cho web widget, chặn theo domain. |
| /webhooks/* | Điểm nhận tin từ các nền tảng, xác thực bằng chữ ký. |
Đặc tả OpenAPI được sinh thẳng từ mã nguồn nên không bao giờ lệch với thực tế — xem tại https://api.chattudong.com/docs.