Skip to content

PBX API — Overview

Public REST API for the PBX Module (Extensions / CDR / Click-to-Call / Queue / Webhooks). Authentication: Bearer Token (user session). Base URL: provisioned per customer — see the Base URL section.

Scope

The PBX API lets a customer CRM:

  • Manage SIP extensions: CRUD + change SIP password.
  • Query call history (CDR) + download recordings.
  • Trigger a two-leg Click-to-Call (agent → customer).
  • Manage queues + agent tiers.
  • Register webhooks to receive realtime events (pbx.call.ringing / answered / hangup / cdr.created).

Glossary

TermDescription
ExtensionA SIP extension — registers to Zorio PBX using extension_number + sip_password
AccountEach customer has fully isolated data
CDRCall Detail Record — one record per call (in/out/internal/local)
Click-to-CallOriginate a two-leg call from the API: A-leg dials the agent extension, B-leg dials the customer number
QueueA queue — agents (Tier) answer based on a strategy (round-robin, longest-idle, ...)
TierPriority level within a queue (tier_level 1-9); tier_position orders agents within the same level
WebhookAn HTTPS URL where Zorio POSTs events to the customer CRM (pbx.call.ringing / pbx.call.answered / pbx.call.hangup / pbx.cdr.created)
HMACHeader X-Zorio-Signature: sha256=hex(hmac_sha256(secret, body)) for verification
IdempotencyHeader X-Zorio-Delivery: <UUID> — clients use this to dedupe on retry

End-to-end workflow

1. Login                  POST /api/auth/login       → Bearer token
2. Create extension       POST /api/pbx/extensions   → returns sip_password once
3. Register webhook       Admin Console UI (NOT via API)
4. Click-to-call          POST /api/pbx/calls/click-to-call → 202 call_uuid
5. Receive events         Zorio POSTs to your URL: pbx.call.ringing → pbx.call.answered → pbx.call.hangup
6. Query CDR              GET  /api/pbx/cdr?from=&to=&extension=
7. Download recording     GET  /api/pbx/cdr/{uuid}/recording → 302 signed URL TTL 30 minutes

Authentication

Login

Endpoint: POST /api/auth/login

Request Body (JSON)

json
{
  "username": "admin",
  "password": "<password>"
}

Response Body (JSON) — 200

json
{
  "data": {
    "user": {
      "id": 1,
      "username": "admin",
      "email": "admin@example.com",
      "role": "admin",
      "tenant_id": 1
    }
  },
  "token": "1|abcdefghijklmnopqrstuvwxyz0123456789"
}

Every request must include

Authorization: Bearer <token>
Accept: application/json

Required permission

The user must have the pbx_api_access permission (built into the admin role).

Endpoint groups

GroupDocumentationDescription
ExtensionsGo to pageCRUD + change SIP password + list available numbers
Call history (CDR)Go to pageQuery CDR with filters + signed-URL recording download
Click-to-CallGo to pageOriginate a two-leg call from the API
QueueGo to pageCRUD queues + manage agent tiers
PBX webhook eventsGo to pagePayload schema + HMAC verification + retry policy

Pagination & Response shape

Pagination

Every list endpoint uses ?page=1&per_page=50 (max 200). Response:

json
{
  "current_page": 1,
  "data": [],
  "last_page": 5,
  "per_page": 50,
  "total": 234
}

Single resource / action

json
{ "data": {} }

Error

json
{
  "message": "Short error description",
  "errors": { "field_name": ["Detailed description"] }
}

Timezone

All datetimes are returned as ISO 8601 with offset (+00:00 = UTC).

Rate Limit

Endpoint groupLimit
/api/pbx/calls/click-to-call10 req/min/token
/api/pbx/* (every other endpoint)60 req/min/token

Exceeding the limit returns HTTP 429 with header Retry-After: <seconds>.

HTTP Status Codes

HTTPWhen
200OK
201Created (new resource)
202Accepted (click-to-call enqueued)
401Token missing / invalid / expired — re-login
403Token is valid but missing permission pbx_api_access
404Resource does not exist within the token's account scope
409Conflict (e.g. extension already in the queue)
422Validation failure (see errors for field details) or business-rule violation
429Rate limit hit
500Server error (report to the Zorio team)
502Click-to-call: Zorio PBX refused to originate

Base URL

URL
Productionhttps://app.zorio.vn/api/pbx/ (provisioned per customer)

FAQ

Q1: My webhook URL is temporarily blocked (e.g. CDN). How long does Zorio retry?

A: 4 attempts, total ~36 minutes. After that the delivery moves to the deadletter queue — you must re-register the webhook after fixing the issue.

Q2: Click-to-call failed — how do I distinguish "agent did not pick up" vs "customer did not answer"?

A: After pbx.call.hangup fires, check hangup_cause:

  • NORMAL_CLEARING + billsec > 0: both parties picked up; call succeeded.
  • NO_ANSWER: one of the two parties did not pick up.
  • USER_BUSY: the destination number was busy.

Q3: I only want events for a specific extension, not the whole account.

A: Webhook subscriptions are currently account-wide. Per-extension filtering is not yet supported.

Q4: I need a test account before integrating with production.

A: Contact Zorio to be provisioned a separate test account.

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