API Token (machine-to-machine)
API Token cấp cho hệ thống máy (CRM backend, dialer engine, integration service) gọi API Zorio mà không gắn với phiên user. Phù hợp cho server-to-server traffic, cron job, microservice tích hợp.
Khác biệt với Bearer (phiên user) (user session)
| Đặc điểm | Bearer (phiên user) (user) | API Token (machine) |
|---|---|---|
| Gắn với user nào | 1 user cụ thể | 1 ứng dụng / service |
| Khi user logout | Token mất hiệu lực | Vẫn sống |
| Khi user đổi mật khẩu | Còn sống | Còn sống |
| Audit log ghi nhận | Theo user.username | Theo tên ứng dụng |
| Phù hợp cho | App có người dùng (frontend, mobile) | Server-to-server / cron |
TIP
Cả 2 dạng đều dùng header Authorization: Bearer <token> giống nhau — phân biệt qua cách cấp + audit log, không phải qua format token.
Tạo API Token
Chỉ admin được tạo
API Token chỉ admin của tài khoản tạo được — qua Admin Console. Không có endpoint API để tự tạo (tránh CRM tự nhân bản token).
Quy trình
- Vào Admin Console → Cài đặt → API Tokens.
- Chọn tab Machine Tokens (khác tab "User Tokens").
- Bấm Tạo Machine Token:
- Tên — vd "CRM Salesforce Production", "Dialer Engine v2".
- Permission scope — chọn permissions cụ thể (vd
pbx_api_access,telesales_create_lead). - IP whitelist (tùy chọn) — chỉ chấp nhận request từ các IP cụ thể.
- Expiration (tùy chọn) — auto-expire sau N ngày.
- Hệ thống sinh token → copy ngay 1 lần.
Dùng API Token
Giống Bearer (phiên user) — chỉ thêm header Authorization: Bearer <token> vào mọi request.
curl -X POST 'https://app.zorio.vn/api/pbx/calls/click-to-call' \
-H 'Authorization: Bearer <YOUR_MACHINE_TOKEN>' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{"from_extension":"1001","to_phone":"0987654321"}'Permission scope
API Token có scope hẹp hơn user — chỉ làm được thao tác trong danh sách permission đã chọn lúc tạo.
Ví dụ scope phổ biến:
| Scope | Cho phép |
|---|---|
pbx_api_access | Mọi endpoint /api/pbx/* |
manage_caller_ids | CRUD caller ID + groups |
telesales_api_access | Đọc/ghi campaign + lead Telesales |
autocall_api_access | Đọc/ghi campaign + lead AutoCall |
view_all_cdr | Xem CDR toàn tài khoản |
view_team_cdr | Chỉ xem CDR trong team |
Endpoint kiểm tra permission của token hiện tại:
GET /api/auth/me
Authorization: Bearer <token>Response 200 trả về permissions[] array.
IP whitelist
Khi tạo token với IP whitelist:
- Mọi request từ IP không trong list → HTTP 403 với body
{ "message": "Forbidden: IP not whitelisted." }. - IP
0.0.0.0/0= chấp nhận mọi IP (mặc định). - Hỗ trợ CIDR range (vd
203.0.113.0/24).
Lưu ý load balancer
Nếu app deploy sau LB / nginx proxy — Zorio đọc IP từ header X-Forwarded-For (chuỗi client, proxy1, proxy2). LB cần cấu hình forward đúng client IP.
Audit log
Mỗi request với API Token được log với:
| Field | Mô tả |
|---|---|
token_name | Tên token (vd "CRM Salesforce Production") |
ip | IP gửi request |
endpoint | Method + path |
status | HTTP status response |
at | Timestamp |
Truy cập tại Admin Console → Audit Log → API Token Activity.
Rotate token
Vì lý do bảo mật, rotate token định kỳ (khuyến nghị 90 ngày 1 lần):
- Vào Admin Console → API Tokens → bấm Rotate bên cạnh token.
- Hệ thống sinh token mới — copy.
- Update token mới vào ứng dụng (deploy code mới với token mới).
- Verify ứng dụng chạy OK với token mới.
- Revoke token cũ sau khi confirm.
Không xoay 2 token cùng lúc
Nếu app dùng nhiều token (vd LB → N replicas), rotate từng cái một, không đồng loạt, để có rollback path khi gặp lỗi.
Revoke
Token bị compromise hoặc không còn dùng — Admin Console → API Tokens → Revoke. Mọi request với token sau khi revoke → HTTP 401.
Revoke ngay khi nghi ngờ lộ
- Code có token vô tình commit lên git public.
- Server có token bị hack.
- Nhân viên có quyền tạo token rời công ty.
Revoke ngay, không chờ điều tra. Tạo token mới + deploy.
Bổ sung token vào CI/CD
| Tool | Cách lưu token |
|---|---|
| GitHub Actions | Repository secrets → ZORIO_API_TOKEN |
| GitLab CI | CI/CD Variables (Masked + Protected) |
| Jenkins | Credentials → Secret Text |
| Vault | Path secret/zorio/api-token → fetch lúc deploy |
| K8s | Secret → mount vào env var pod |
KHÔNG echo token ra log build. Tool CI thường có "masked output" — bật flag này.
Sample server-to-server (cron import lead)
// cron-job.js — chạy mỗi 5 phút
const axios = require('axios');
const api = axios.create({
baseURL: 'https://app.zorio.vn/api',
headers: {
Authorization: 'Bearer ' + process.env.ZORIO_TOKEN,
Accept: 'application/json',
'Content-Type': 'application/json',
},
timeout: 30_000,
});
async function syncLeads() {
const crmLeads = await fetchFromCRM();
for (const lead of crmLeads) {
try {
await api.post(`/telesales/campaigns/${lead.campaign_id}/leads`, {
phone: lead.phone,
custom_fields: lead.fields,
});
} catch (err) {
if (err.response?.status === 422) {
console.error('Lead invalid:', lead, err.response.data.errors);
} else {
throw err;
}
}
}
}
syncLeads().catch(console.error);