Skip to content

Webhook events PBX

Đăng ký webhook

Webhook là cấu hình của khách hàng — đăng ký / xoá / xoay secret qua giao diện Admin (Admin Console). API công khai không expose CRUD subscription.

Tài liệu này document payload schema + HMAC verify để CRM khách hàng tự xử lý event nhận về.

Envelope chung

Mọi event đều có cấu trúc envelope:

FieldTypeMô tả
eventstringTên event (xem chi tiết bên dưới)
timestampdatetimeLúc Zorio publish event (ISO 8601 UTC)
dataobjectPayload event-specific

pbx.call.ringing

Cuộc gọi tới ext, ext đang đổ chuông chưa nhấc.

data fields

FieldTypeMô tảGiá trị
call_uuidstringUUID cuộc gọi
extensionstringSố máy nhánh đang đổ chuông
directionstringHướng cuộc gọiinbound / outbound / internal
caller_numberstringSố gọi đi (caller ID)
destination_numberstringSố đích (thường = extension)
timestampdatetimeLúc bắt đầu đổ chuôngISO 8601

Sample payload

json
{
  "event": "pbx.call.ringing",
  "timestamp": "2026-06-29T03:30:00Z",
  "data": {
    "call_uuid": "...",
    "extension": "1001",
    "direction": "inbound",
    "caller_number": "0987654321",
    "destination_number": "0900000020",
    "timestamp": "2026-06-29T03:30:00Z"
  }
}

pbx.call.answered

Ext đã nhấc máy.

data fields = giống pbx.call.ringing + thêm:

FieldTypeMô tả
answered_atdatetimeLúc nhấc máy (ISO 8601)

pbx.call.hangup

Cuộc gọi kết thúc — fire ngay lúc sự kiện kết thúc cuộc gọi từ Zorio PBX.

data fields

FieldTypeMô tảGiá trị hợp lệ
call_uuidstringUUID cuộc gọi
extensionstringMáy nhánh liên quan
directionstringHướng cuộc gọiinbound / outbound / internal
caller_numberstringCaller ID
destination_numberstringSố đích
started_atdatetime|nullLúc cuộc gọi bắt đầu (thời điểm bắt đầu cuộc gọi)ISO 8601
answered_atdatetime|nullLúc nhấc máy (null nếu không nhấc)ISO 8601
ended_atdatetimeLúc cúp máyISO 8601
duration_secintegerTổng thời lượng (giây)≥ 0
billsecintegerThời gian tính tiền (giây)≥ 0
hangup_causestringMã hangup chuẩn Q.850 từ Zorio PBXNORMAL_CLEARING / NO_ANSWER / USER_BUSY / CALL_REJECTED / ORIGINATOR_CANCEL / ...
call_resultstringKết quả phân loại nhanhanswered (billsec > 0) / no_answer (billsec = 0)
recording_urlstring|nullURL tải ghi âm — null ở event realtime (gửi ngay khi cúp), URL có giá trị ở pbx.cdr.created (sau khi pipeline ghi âm xong)

Sample payload

json
{
  "event": "pbx.call.hangup",
  "timestamp": "2026-06-29T03:30:45Z",
  "data": {
    "call_uuid": "...",
    "extension": "1001",
    "direction": "inbound",
    "caller_number": "0987654321",
    "destination_number": "0900000020",
    "started_at": "2026-06-29T03:30:00Z",
    "answered_at": "2026-06-29T03:30:03Z",
    "ended_at": "2026-06-29T03:30:45Z",
    "duration_sec": 45,
    "billsec": 42,
    "hangup_cause": "NORMAL_CLEARING",
    "call_result": "answered",
    "recording_url": null
  }
}

pbx.cdr.created

Fire SAU khi pipeline CDR insert row vào DB — có đầy đủ field từ A/B leg processed + recording_url.

data fields

FieldTypeMô tảGiá trị hợp lệ
call_uuidstringUUID cuộc gọi (= UUID cuộc gọi)
extensionstring|nullMáy nhánh (ưu tiên extension_number, fallback agent_extension)
directionstringHướnginbound / outbound / internal / local
caller_numberstringCaller ID
destination_numberstringSố đích
started_atdatetime|nullLúc bắt đầuISO 8601
answered_atdatetime|nullLúc nhấcISO 8601
ended_atdatetime|nullLúc cúpISO 8601
duration_secintegerTổng thời lượng≥ 0
billsecintegerThời gian tính tiền≥ 0
hangup_causestringMã hangup(như pbx.call.hangup)
resultstringKết quả phân loại đầy đủanswered / busy / no_answer / failed / cancelled / rejected / voicemail
recording_urlstring|nullURL nội bộ trỏ tới endpoint download (yêu cầu Bearer Token)https://app.zorio.vn/api/pbx/cdr/{uuid}/recording hoặc null

Khác biệt với pbx.call.hangup

  • pbx.call.hangup fire ngay từ sự kiện thời gian thực — result chỉ ở mức coarse (answered / no_answer).
  • pbx.cdr.created fire sau khi pipeline CDR xử lý xong → result phân loại chi tiết hơn + có recording_url.

Headers POST từ Zorio tới URL khách

HeaderÝ nghĩa
X-Zorio-Eventpbx.call.hangup
X-Zorio-Timestampepoch giây (UTC). Client reject nếu lệch >300s
X-Zorio-DeliveryUUID per delivery — dedupe khi retry
X-Zorio-Signaturesha256=<hex> HMAC-SHA256(secret, raw_body)
Content-Typeapplication/json; charset=utf-8

Verify HMAC ở client (mẫu Node.js)

js
const crypto = require('crypto');

function verify(req, secret) {
  const ts = parseInt(req.headers['x-zorio-timestamp'], 10);
  if (Math.abs(Date.now() / 1000 - ts) > 300) return false;
  const sig = req.headers['x-zorio-signature'];
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(req.rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Retry policy

Zorio kỳ vọng client trả 2xx trong 5 giây. Nếu không:

  • Lần 2: sau 30 giây
  • Lần 3: sau 5 phút
  • Lần 4: sau 30 phút
  • Max 4 lần → đánh dấu deadletter trong bảng nhật ký phân phối webhook

Client nên trả 200 ngay khi nhận event, xử lý async — tránh bị retry chồng.

Cấp phép theo điều khoản sử dụng của Zorio.