Báo cáoBáo cáo cuộc gọi

Báo cáo cuộc gọi

Nhữ Hào Nam·2/6/2026

API Reports — Call Logs

Authentication chung: Header Authorization (X-Api-Key) bắt buộc với tất cả endpoint. Kong dual-auth: ưu tiên X-Tenant-ID header, fallback query DB theo key.

Base URL: Dev: https://xapi-dev.alohub.vn  |  Prod: https://xapi.alohub.vn


POST /v1/reports/call-logs

Lấy danh sách call logs với bộ lọc theo số điện thoại, khoảng thời gian, loại cuộc gọi và phân trang. Trả về thông tin tóm tắt mỗi cuộc gọi kèm customerName liên kết.

Authentication: Header X-Api-Key, scope: report

Lưu ý: Endpoint này dùng POST (không phải GET) vì filter được truyền qua request body.

Request Body

{
  "phoneNumber": "0912345678",
  "callStartTime": "2026-04-14T00:00:00+07:00",
  "callEndtime": "2026-04-20T23:59:59+07:00",
  "callType": 0,
  "page": 1,
  "limit": 50
}

Field

Kiểu

Bắt buộc

Mô tả

phoneNumber

string

Không

Filter theo số điện thoại — match với caller hoặc called. Bỏ qua = không filter

callStartTime

string (ISO 8601)

Không

Thời điểm bắt đầu, format yyyy-MM-ddTHH:mm:ss±HH:mm

callEndtime

string (ISO 8601)

Không

Lưu ý typo: tên field là callEndtime (chữ t thường) — không phải callEndTime

callType

number

Không

Loại cuộc gọi: 0 = inbound, 1 = outbound. Bỏ qua = lấy tất cả

page

number

Không

Số trang, bắt đầu từ 1. Default: 1

limit

number

Không

Số bản ghi/trang. Default: 50, khuyến nghị max 100

Gotcha: Field backend là callEndtime (typo — chữ t thường). FE phải gửi đúng chính tả, nếu không filter endTime sẽ không được apply.

Code mẫu

curl -X POST "https://xapi.alohub.vn/v1/reports/call-logs" \
  -H "X-Api-Key: sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "0912345678",
    "callStartTime": "2026-04-14T00:00:00+07:00",
    "callEndtime": "2026-04-20T23:59:59+07:00",
    "callType": 0,
    "page": 1,
    "limit": 50
  }'
const axios = require('axios');
const response = await axios.post(
  '{{host}}/api/v1/reports/call-logs',
  {
    phoneNumber: '0912345678',
    callStartTime: '2026-04-14T00:00:00+07:00',
    callEndtime: '2026-04-20T23:59:59+07:00',   // ⚠️ typo: lowercase t
    callType: 0,
    page: 1,
    limit: 50
  },
  { headers: { 'X-Api-Key': '{{api-key}}' } }
);
console.log(response.data);
import requests
payload = {
    "phoneNumber": "0912345678",
    "callStartTime": "2026-04-14T00:00:00+07:00",
    "callEndtime": "2026-04-20T23:59:59+07:00",  # typo: lowercase t
    "callType": 0,
    "page": 1,
    "limit": 50
}
response = requests.post(
    '{{host}}/api/v1/reports/call-logs',
    json=payload,
    headers={"X-Api-Key": "{{api-key}}"}
)
print(response.json())

Response 200

{
  "success": "1",
  "error_code": "SUCCESS",
  "error_message": "SUCCESS",
  "totalRecord": 3829,
  "data": [
    {
      "callId": "20260310095227-ABCXYZ-342",
      "caller": "0912345678",
      "called": "alohub2",
      "startTime": "21/01/2026 09:52:33",
      "waitingTime": "6",
      "firstRingTime": "21/01/2026 09:52:35",
      "firstConnectTime": "",
      "agentId": "AloHub",
      "endTime": "21/01/2026 09:52:41",
      "acdTime": "0",
      "description": "INBOUND-Khách hàng kết thúc trước khi timeout",
      "customerName": "0912345678",
      "url": ""
    }
  ]
}

Response Fields

Field

Kiểu

Mô tả

success

string

"1" = thành công, "0" = lỗi

error_code

string

Mã lỗi (SUCCESS khi thành công)

totalRecord

number

Tổng số bản ghi match filter (không phải số row trong page hiện tại)

data[].callId

string

Mã cuộc gọi

data[].caller

string

Số gọi đi

data[].called

string

Số / hotline được gọi

data[].agentId

string

Username agent xử lý (rỗng nếu không ai nhận)

data[].startTime

string

Thời điểm bắt đầu, format dd/MM/yyyy HH:mm:ss

data[].endTime

string

Thời điểm kết thúc

data[].firstRingTime

string

Thời điểm đổ chuông lần đầu

data[].firstConnectTime

string

Thời điểm agent bắt máy lần đầu (rỗng nếu không kết nối)

data[].waitingTime

string

Thời gian khách chờ — giây, kiểu string (cần parseInt)

data[].acdTime

string

Thời gian ACD — giây, kiểu string

data[].description

string

Mô tả trạng thái kết thúc cuộc gọi

data[].customerName

string

Tên / mã khách hàng liên kết

data[].url

string

URL file ghi âm (rỗng nếu không có)

Duplicate rows: Response có thể trả về nhiều row cùng callId với customerName khác nhau — do BE JOIN call với bảng customer (1-n). FE nên dedup nếu muốn hiển thị 1 row/call: Array.from(new Map(data.map(r => [r.callId, r])).values())

Error Codes

HTTP

error_code

Mô tả

FE xử lý

401

UNAUTHORIZED

Thiếu hoặc sai X-Api-Key

Redirect nhập lại key

403

INSUFFICIENT_SCOPE

Key không có scope report

Thông báo liên hệ admin

400

INVALID_INPUT

Body sai format (date, page/limit không phải số)

Hiện lỗi cụ thể

429

RATE_LIMIT_EXCEEDED

Vượt giới hạn request

Retry sau Retry-After giây

500

FAIL

Lỗi hệ thống

Toast lỗi chung

Rate Limit Headers

Header

Mô tả

X-RateLimit-Limit-Tenant

Giới hạn tenant/10s

X-RateLimit-Remaining-Tenant

Còn lại tenant/10s

X-RateLimit-Limit-Route

Giới hạn route/10s

X-RateLimit-Remaining-Route

Còn lại route/10s

Retry-After

Giây cần chờ khi bị 429


GET /v1/reports/call-logs/{callId}

Lấy chi tiết một cuộc gọi theo callId, bao gồm thông tin caller/called, agent xử lý, thời gian, thời lượng, trạng thái kết thúc và URL file ghi âm.

Authentication: Header X-Api-Key, scope: report

Lưu ý thời gian: Các field thời gian (startTime, endTime, ...) là string format dd/MM/yyyy HH:mm:ss theo UTC+7, không phải ISO 8601 — FE cần parse thủ công.

Path Parameters

Tham số

Vị trí

Bắt buộc

Kiểu

Mô tả

Ví dụ

callId

path

string

Mã định danh cuộc gọi, format YYYYMMDDHHmmss-XXXXXXXX-NNN

20260310095227-ABCXYZ-342

Request Body

Không có (method GET).

Code mẫu

curl -X GET "https://xapi.alohub.vn/v1/reports/call-logs/20260310095227-ABCXYZ-342" \
  -H "X-Api-Key: sk_live_xxx" \
  -H "Accept: application/json"
const axios = require('axios');
const callId = '20260310095227-ABCXYZ-342';
const response = await axios.get(
  `{{host}}/api/v1/reports/call-logs/${encodeURIComponent(callId)}`,
  { headers: { 'X-Api-Key': '{{api-key}}' } }
);
// response.data.data[0] là object chi tiết (null nếu không tìm thấy)
console.log(response.data.data[0]);
import requests
call_id = '20260310095227-ABCXYZ-342'
response = requests.get(
    f'{{host}}/api/v1/reports/call-logs/{call_id}',
    headers={"X-Api-Key": "{{api-key}}"}
)
data = response.json()
# data["data"][0] là object chi tiết
print(data["data"][0] if data["data"] else None)

Response 200

{
  "success": "1",
  "error_code": "SUCCESS",
  "error_message": "SUCCESS",
  "totalRecord": 1,
  "data": [
    {
      "callId": "20260310095227-ABCXYZ-342",
      "caller": "0912345678",
      "called": "alohub2",
      "agentId": "AloHub",
      "startTime": "21/01/2026 09:52:33",
      "endTime": "21/01/2026 09:52:41",
      "ringTime": "21/01/2026 09:52:35",
      "connectTime": "",
      "answerTime": 0,
      "duration": 8,
      "callType": "0",
      "description": "INBOUND-Khách hàng kết thúc trước khi timeout",
      "customerName": "20260107172924-KZGTVFTE-600",
      "recordingUrl": ""
    }
  ]
}

Response Fields

Field

Kiểu

Mô tả

success

string

"1" = thành công, "0" = lỗi

totalRecord

number

Luôn = 1 với API detail (hoặc 0 nếu không tìm thấy)

data[].callId

string

Mã cuộc gọi

data[].caller

string

Số điện thoại / extension gọi đi

data[].called

string

Số / hotline / extension được gọi

data[].agentId

string

Username agent xử lý (rỗng nếu không ai nhận)

data[].startTime

string

Thời điểm bắt đầu, format dd/MM/yyyy HH:mm:ss

data[].endTime

string

Thời điểm kết thúc

data[].ringTime

string

Thời điểm đổ chuông (cf. firstRingTime ở list API)

data[].connectTime

string

Thời điểm agent bắt máy (rỗng nếu không kết nối)

data[].answerTime

number

Thời gian chờ đến khi được trả lời (giây). 0 = không được trả lời

data[].duration

number

Tổng thời lượng cuộc gọi (giây)

data[].callType

string

"0" = inbound, "1" = outbound

data[].description

string

Mô tả trạng thái kết thúc cuộc gọi

data[].customerName

string

Tên / mã khách hàng liên kết

data[].recordingUrl

string

URL file ghi âm (rỗng nếu không có)

Khác biệt với List API: answerTimedurationnumber (không phải string như waitingTime/acdTime ở list). Field ghi âm là recordingUrl (detail) vs url (list). Thời điểm chuông là ringTime (detail) vs firstRingTime (list).

Error Codes

HTTP

error_code

Mô tả

FE xử lý

401

UNAUTHORIZED

Thiếu hoặc sai X-Api-Key

Redirect nhập lại key

403

INSUFFICIENT_SCOPE

Key không có scope report

Thông báo liên hệ admin

404

NOT_FOUND

Không tìm thấy call log với callId này

Thông báo "Không tìm thấy cuộc gọi"

400

INVALID_INPUT

callId sai format

Kiểm tra lại input

429

RATE_LIMIT_EXCEEDED

Vượt giới hạn request

Retry sau Retry-After giây

500

FAIL

Lỗi hệ thống

Toast lỗi chung

Rate Limit Headers

Header

Mô tả

X-RateLimit-Limit-Tenant

Giới hạn tenant/10s

X-RateLimit-Remaining-Tenant

Còn lại tenant/10s

X-RateLimit-Limit-Route

Giới hạn route/10s

X-RateLimit-Remaining-Route

Còn lại route/10s

Retry-After

Giây cần chờ khi bị 429


Bài viết này có hữu ích không?
Cập nhật: 2/6/2026