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ộ member 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 (đã lọc tự động theo authentication). 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 - Viettel Sales",
"description": "Viettel 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ộ field như list, 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 - Viettel 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 — snapshot runtime
Phục vụ dashboard giám sát realtime — hiển thị caller-ID nào đang eligible / cooldown / 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 runtime | 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 - Viettel 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.
