Skip to content

Click-to-Call

Originate a two-leg call from the API: A-leg dials the agent extension → on pickup → B-leg dials the customer number → bridge.

POST /api/pbx/calls/click-to-call

Request body fields

FieldTypeRequiredDescriptionValid values
from_extensionstringAgent extension (A-leg)Must exist + status=active. Regex ^[0-9]{3,10}$
to_phonestringDestination number (B-leg)Regex ^[0-9+]+$, 3-32 chars
caller_idstringoptionalNumber to present when dialing outFalls back to extension.outbound_caller_id or from_extension. Ideally pick a value from /api/pbx/caller-ids
trunk_idintegeroptionalOutbound trunk ID (takes priority over trunk_name)Must exist + status=active. If omitted → falls back to the default dialplan (Zorio PBX picks a trunk via LCR/number-pool)
trunk_namestringoptionalTrunk name alternative to trunk_idmax 100 chars
headersobjectoptionalCustom SIP headers — Zorio prefixes them with X- and attaches to the B-leg INVITEKey regex [A-Za-z0-9_-], value max 200 chars

Request Body (JSON) — Mode 1: auto routing (no trunk)

json
{
  "from_extension": "1001",
  "to_phone": "0987654321"
}

Request Body (JSON) — Mode 2: force trunk + caller-id + CRM tracking header

json
{
  "from_extension": "1001",
  "to_phone": "0987654321",
  "caller_id": "0900000020",
  "trunk_id": 4,
  "headers": { "CRM-Lead-Id": "LEAD-42" }
}

Response body fields — 202 (Accepted, call enqueued)

FieldTypeDescription
call_uuidstringLogical UUID of the call (the CRM uses it to track across webhook events)
a_leg_uuidstringA-leg UUID (channel to the agent extension)
b_leg_uuidstringB-leg UUID (channel to the customer number)
from_extensionstringEchoed from the request
to_phonestringEchoed from the request
caller_idstringThe caller ID that was actually resolved
trunk_idinteger|nullTrunk ID chosen (null if the default dialplan was used)
trunk_namestring|nullTrunk name chosen (null if the default dialplan was used)
routing_modestringdirect_gateway (a trunk was chosen) or dialplan_default (default dialplan routing)
statusstringqueued (not yet connected). The CRM then tracks progress via webhooks pbx.call.ringing / pbx.call.answered / pbx.call.hangup

Response Body (JSON) — 202

json
{
  "data": {
    "call_uuid": "1ac30fff-0968-452f-9a9f-56c21fc8fe3f",
    "a_leg_uuid": "fc22be63-271d-4842-859d-0ebba9f13c8a",
    "b_leg_uuid": "64486cf6-0577-46a4-81e9-23ca31f46249",
    "from_extension": "1001",
    "to_phone": "0987654321",
    "caller_id": "1001",
    "trunk_id": 4,
    "trunk_name": "POC",
    "routing_mode": "direct_gateway",
    "status": "queued"
  }
}

Rate limit

10 req / minute / token (this group only — guards against spam-call abuse).

How it works

A-leg dials the agent extension → on pickup → B-leg dials the customer number → bridge. The customer CRM first receives pbx.call.answered for the A-leg, then pbx.call.answered for the B-leg.

1. Client calls   POST /api/pbx/calls/click-to-call → 202 with call_uuid
2. Zorio          Webhook pbx.call.ringing → agent extension rings
3. Agent picks up Webhook pbx.call.answered (A-leg)
4. Zorio          Bridges by dialing the B-leg to the customer number
5. Customer picks up Webhook pbx.call.answered (B-leg)
6. Conversation in progress
7. Hangup         Webhook pbx.call.hangup + pbx.cdr.created

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