Caller-ID rotation groups
Bối cảnh
Chiến dịch outbound cần xoay vòng nhiều caller-ID để tránh bị nhà mạng đánh dấu spam. Admin Zorio quản lý số gọi ra trong các rotation group thông qua UI quản trị; đối tác tích hợp chỉ cần đọc danh sách nhóm để gán vào chiến dịch (qua field caller_id_group_id khi tạo Campaign).
Endpoint chỉ-đọc
Việc quản lý từng caller-ID, tạo / cập nhật / xoá nhóm (POST/PUT/DELETE), đồng bộ thành viên và clear cooldown đều thực hiện qua UI quản trị Zorio và không mở qua Integration API.
Tổng quan endpoint
| Endpoint | Mục đích |
|---|---|
GET /api/caller-id-groups | Danh sách rotation group của khách hàng |
GET /api/caller-id-groups/{id} | Chi tiết một nhóm + danh sách caller-ID thành viên |
GET /api/caller-id-groups/{id}/monitor | Snapshot runtime per-member (eligibility, cooldown, health) — phục vụ dashboard giám sát |
GET /api/caller-id-groups — danh sách
Query parameters
Endpoint chỉ trả các nhóm thuộc khách hàng (đã tự động lọc theo tài khoản xác thực). Không có filter bổ sung.
Response fields (mỗi item trong data[])
| Field | Type | Mô tả | Giá trị hợp lệ |
|---|---|---|---|
id | integer | ID nhóm xoay vòng | |
name | string | Tên nhóm | max 150 ký tự |
description | string|null | Mô tả nội bộ | max 500 ký tự |
rotation_strategy | string | Chiến lược chọn caller-ID khi gọi ra | round_robin / least_used / cap_based / weighted / sticky_lead / random |
sticky_enabled | bool | Có ghim caller-ID đã dùng cho 1 lead ở các lần gọi sau hay không | true / false |
status | string | Trạng thái nhóm — disabled sẽ bị engine bỏ qua | active / disabled |
caller_ids_count | integer | Số caller-ID thành viên đang active | ≥ 0 |
created_at | datetime | Thời điểm tạo nhóm (ISO 8601 UTC) |
Response 200:
{
"data": [
{
"id": 3,
"name": "Group A - Sales",
"description": "Outbound numbers for the summer campaign",
"rotation_strategy": "round_robin",
"sticky_enabled": true,
"status": "active",
"caller_ids_count": 12,
"created_at": "2026-05-20T03:00:00Z"
}
]
}GET /api/caller-id-groups/{id} — chi tiết
Path parameter
| Field | Type | Mô tả |
|---|---|---|
id | integer | ID nhóm (lấy từ list ở trên) |
Response fields
Bao gồm toàn bộ trường như API danh sách, kèm thêm mảng caller_ids[]:
| Field | Type | Mô tả | Giá trị hợp lệ |
|---|---|---|---|
caller_ids[] | array | Danh sách caller-ID thành viên | |
caller_ids[].id | integer | ID caller-ID | |
caller_ids[].number | string | Số điện thoại gọi ra | E.164 hoặc số nội địa |
caller_ids[].display_name | string|null | Tên hiển thị nội bộ | max 100 ký tự |
caller_ids[].carrier | string | Nhà mạng | viettel / mobifone / vinaphone / vietnamobile / landline / other |
caller_ids[].carrier_label | string | Nhãn hiển thị nhà mạng | |
caller_ids[].status | string | Trạng thái caller-ID | active / disabled |
caller_ids[].trunk_name | string|null | Tên trunk SIP gắn với caller-ID | |
caller_ids[].weight | integer | Trọng số khi rotation_strategy = weighted | ≥ 1 (default 1) |
Response 200:
{
"data": {
"id": 3,
"name": "Group A - Sales",
"description": "...",
"rotation_strategy": "round_robin",
"sticky_enabled": true,
"status": "active",
"caller_ids_count": 12,
"created_at": "2026-05-20T03:00:00Z",
"caller_ids": [
{
"id": 18,
"number": "0900000010",
"display_name": "Sales Line 1",
"carrier": "viettel",
"carrier_label": "Viettel",
"status": "active",
"trunk_name": "Trunk-Viettel-01",
"weight": 2
}
]
}
}GET /api/caller-id-groups/{id}/monitor — trạng thái hiện tại
Phục vụ màn hình giám sát theo thời gian thực — hiển thị Caller ID nào đang sẵn sàng hoặc đang trong thời gian chờ / vượt quota.
Path parameter
| Field | Type | Mô tả |
|---|---|---|
id | integer | ID nhóm |
Response fields
| Field | Type | Mô tả | Giá trị hợp lệ |
|---|---|---|---|
group_id | integer | ID nhóm | |
group_name | string | Tên nhóm | |
total_members | integer | Tổng số caller-ID thành viên | |
eligible_now | integer | Số caller-ID đang sẵn sàng được chọn | |
in_cooldown | integer | Số caller-ID đang bị cooldown tạm thời | |
disabled | integer | Số caller-ID bị disable thủ công | |
members[] | array | Snapshot từng caller-ID | |
members[].caller_id_id | integer | ID caller-ID | |
members[].number | string | Số điện thoại | |
members[].carrier | string | Nhà mạng | viettel / mobifone / vinaphone / vietnamobile / landline / other |
members[].status | string | Trạng thái hiện tại | eligible / cooldown / disabled / quota_exceeded |
members[].health_score | integer | Điểm sức khoẻ — càng thấp càng có dấu hiệu bị nhà mạng đánh dấu | 0-100 |
members[].calls_today | integer | Số cuộc đã gọi trong ngày | ≥ 0 |
members[].daily_cap | integer | Giới hạn cuộc/ngày | ≥ 1 |
members[].cooldown_until | datetime|null | Thời điểm hết cooldown (null nếu không bị cooldown) | ISO 8601 UTC |
Response 200:
{
"data": {
"group_id": 3,
"group_name": "Group A - Sales",
"total_members": 12,
"eligible_now": 9,
"in_cooldown": 2,
"disabled": 1,
"members": [
{
"caller_id_id": 18,
"number": "0900000010",
"carrier": "viettel",
"status": "eligible",
"health_score": 82,
"calls_today": 87,
"daily_cap": 200,
"cooldown_until": null
},
{
"caller_id_id": 19,
"number": "0900000011",
"carrier": "mobifone",
"status": "cooldown",
"health_score": 14,
"calls_today": 53,
"daily_cap": 200,
"cooldown_until": "2026-06-06T12:00:00Z"
}
]
}
}Response 404: { "message": "Pool not found." }.
Gán nhóm vào chiến dịch
Trong body khi tạo Campaign, gán caller_id_group_id bằng id trả về từ GET /api/caller-id-groups:
{
"name": "Summer Promo",
"caller_id_group_id": 3,
...
}Khi chiến dịch chuyển trạng thái draft → active (PUT /api/telesales/campaigns/{id}/status), field caller_id_group_id là bắt buộc — nếu thiếu, server trả 422.
