English
English
Appearance
English
English
Appearance
Manage SIP extensions on the PBX: list, create, update, delete, fetch available numbers, and rotate the SIP password.
/api/pbx/extensions — List | Field | Type | Required | Description | Valid values |
|---|---|---|---|---|
search | string | optional | Match against extension_number or display_name (LIKE) | |
status | string | optional | Filter by admin status | active, disabled |
page | integer | optional | Page number | ≥ 1 (default 1) |
per_page | integer | optional | Records per page | 1-200 (default 50) |
data[]) | Field | Type | Description | Values |
|---|---|---|---|
extension_number | string | Extension number — SIP register name | 3-10 digits |
display_name | string|null | Display name (caller ID name for internal calls) | max 100 chars |
voicemail_enabled | bool | Whether voicemail is enabled | true / false |
outbound_caller_id | string|null | Default outbound caller ID | Must exist in /caller-ids |
recording_mode | string | Recording mode | none, inbound, outbound, all |
status | string | Admin configuration status | active, disabled |
team_id | integer|null | Team ID | |
department_id | integer|null | Department ID | |
max_concurrent | integer | Maximum concurrent calls | 1-10 |
tls_enabled | bool | Whether SIPS/TLS is enabled | true / false |
created_at | datetime | Creation timestamp (ISO 8601 + offset) | |
updated_at | datetime | Last update timestamp |
{
"current_page": 1,
"data": [
{
"extension_number": "1001",
"display_name": "Mac I5",
"voicemail_enabled": true,
"outbound_caller_id": null,
"recording_mode": "all",
"status": "active",
"team_id": 2,
"department_id": null,
"max_concurrent": 2,
"tls_enabled": false,
"created_at": "2026-04-06T12:19:13+00:00",
"updated_at": "2026-06-18T11:01:47+00:00"
}
],
"last_page": 2,
"per_page": 10,
"total": 17
}/api/pbx/extensions/{ext} — Detail | Field | Type | Description |
|---|---|---|
ext | string | extension_number (NOT id) |
Response = the 12 fields from the list + one extra realtime field sip_registration.
{
"data": {
"extension_number": "1001",
"display_name": "Mac I5",
"voicemail_enabled": true,
"outbound_caller_id": null,
"recording_mode": "all",
"status": "active",
"team_id": 2,
"department_id": null,
"max_concurrent": 2,
"tls_enabled": false,
"created_at": "2026-04-06T12:19:13+00:00",
"updated_at": "2026-06-18T11:01:47+00:00",
"sip_registration": "registered"
}
}| Field | Type | Description | Valid values |
|---|---|---|---|
status | string | Admin configuration | active, disabled |
sip_registration | string | Realtime SIP registration status — the CRM uses this to know whether the softphone is online | registered, unregistered, unknown |
/api/pbx/extensions — Create | Field | Type | Required | Description | Valid values |
|---|---|---|---|---|
extension_number | string | ✅ | Extension number — unique per account | Regex ^[0-9]{3,10}$ (3-10 digits) |
display_name | string | optional | Display name | max 100 chars |
team_id | integer | optional | Team ID | Must exist in teams |
sip_password | string | optional | SIP register password — if omitted, a 24-character alphanumeric password is auto-generated | min 8, max 100 chars |
voicemail_enabled | bool | optional | Enable voicemail | true / false (default false) |
voicemail_pin | string | optional | Voicemail PIN | max 20 chars |
recording_mode | string | optional | Recording mode | none / inbound / outbound / all (default none) |
max_concurrent | integer | optional | Maximum concurrent calls | 1-10 (default 2) |
outbound_caller_id | string | optional | Default outbound caller ID | Must exist in /api/pbx/caller-ids (active) |
{
"extension_number": "9001",
"display_name": "Sales 01",
"voicemail_enabled": true,
"recording_mode": "all",
"max_concurrent": 2,
"outbound_caller_id": "0900000020"
}| Field | Type | Description |
|---|---|---|
sip_password | string | SIP password — returned only once, copy into your softphone immediately |
generated_password | bool | true if Zorio auto-generated, false if the client supplied it |
{
"data": {
"extension_number": "9001",
"display_name": "Sales 01",
"voicemail_enabled": true,
"recording_mode": "all",
"status": "active",
"max_concurrent": 2,
"outbound_caller_id": "0900000020",
"team_id": null,
"department_id": null,
"tls_enabled": false,
"created_at": "2026-06-29T04:53:59+00:00",
"updated_at": "2026-06-29T04:53:59+00:00",
"sip_password": "<sip_password_shown_only_once>",
"generated_password": true
}
}/api/pbx/extensions/{ext} — Update | Field | Type | Description | Valid values |
|---|---|---|---|
display_name | string|null | Display name | max 100 chars |
team_id | integer|null | Team ID | |
voicemail_enabled | bool | Enable voicemail | true / false |
voicemail_pin | string|null | Voicemail PIN | max 20 |
recording_mode | string | Recording mode | none / inbound / outbound / all |
max_concurrent | integer | Maximum concurrent calls | 1-10 |
outbound_caller_id | string|null | Outbound caller ID | Must exist in /api/pbx/caller-ids (active) |
status | string | Configuration status | active / disabled |
Note
extension_number and sip_password cannot be changed through PUT. To rotate sip_password, use the /change-password endpoint.
{
"display_name": "Sales 01 (renamed)",
"voicemail_enabled": false,
"max_concurrent": 4,
"recording_mode": "all",
"outbound_caller_id": "0900000020"
}{
"data": {
"extension_number": "1001",
"display_name": "Sales 01 (renamed)",
"voicemail_enabled": false,
"outbound_caller_id": "0900000020",
"recording_mode": "all",
"status": "active",
"team_id": null,
"department_id": null,
"max_concurrent": 4,
"tls_enabled": false,
"created_at": "2026-04-06T12:19:13+00:00",
"updated_at": "2026-06-29T07:55:12+00:00"
}
}/api/pbx/extensions/{ext} — Delete No request body.
{
"data": { "deleted": true }
}Soft delete + flush FS directory cache.
/api/pbx/caller-ids — List available numbers Returns the outbound caller IDs with status=active for the customer — use this when picking outbound_caller_id for an extension or caller_id for a click-to-call.
| Field | Type | Description | Values |
|---|---|---|---|
search | string | Match number or display_name | |
page | integer | Page number | ≥ 1 |
per_page | integer | Records per page | 1-200 (default 50) |
| Field | Type | Description | Values |
|---|---|---|---|
number | string | Outbound number (E.164 or Vietnam domestic) | 8-15 digits |
display_name | string|null | Internal display name | |
carrier | string | Telco | viettel / mobifone / vinaphone / vietnamobile / landline / other |
cli_type | string | Number type | mobile / fixed_02x / hotline_1900 / hotline_1800 / brandname |
status | string | Status | active (always, since the query filters this) |
{
"current_page": 1,
"data": [
{ "number": "0900000020", "display_name": "POC", "carrier": "landline", "cli_type": "mobile", "status": "active" },
{ "number": "0900000021", "display_name": "POC", "carrier": "landline", "cli_type": "mobile", "status": "active" }
],
"last_page": 1, "per_page": 50, "total": 7
}When you POST/PUT an extension with an outbound_caller_id that is not in the list → HTTP 422:
{ "errors": { "outbound_caller_id": ["The selected outbound caller id is invalid."] } }/api/pbx/extensions/{ext}/change-password — Rotate SIP password | Field | Type | Required | Description | Values |
|---|---|---|---|---|
new_password | string | optional | New SIP password — if omitted, a 24-character alphanumeric password is auto-generated | min 8, max 100 |
{}{
"new_password": "MyNewStrongPwd123"
}| Field | Type | Description |
|---|---|---|
extension_number | string | Extension number that was updated |
sip_password | string | New password — returned only once |
generated_password | bool | true if Zorio auto-generated, false if the client supplied it |
{
"data": {
"extension_number": "1001",
"sip_password": "AbC123...",
"generated_password": true
}
}