OpenAPI: Difference between revisions
No edit summary |
No edit summary |
||
| (15 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
== Overview == | == Overview == | ||
== Overview == | |||
<code>openapi.php</code> is the JSON API endpoint based on the OpenAPI specification. | |||
The API uses the existing API keys: | |||
* Full API key: <code>APIKEY</code> | |||
* Read-only API key: <code>READONLYAPIKEY</code> | |||
Both global and tenant-level keys are supported. | Both global and tenant-level keys are supported. | ||
The | The implemented API objects are <code>extension</code>, <code>tenant</code>, <code>user</code>, <code>userprofile</code>, <code>routingprofile</code>, <code>voicemail</code>, <code>condition</code>, <code>huntlist</code>, <code>did</code>, <code>queue</code>, <code>ivr</code>, <code>customdestination</code>, <code>setting</code>, <code>mediafile</code>, <code>musiconhold</code>, <code>paginggroup</code>, <code>conferenceroom</code>, <code>flow</code>, <code>tenantvariable</code>, <code>disa</code>, <code>calleridblacklist</code>, <code>campaign</code>, <code>campaignnumber</code>, <code>cronjob</code>, <code>featurecode</code>, <code>shortnumber</code>, and <code>provisioningphone</code>. They provide endpoints for listing, retrieving, creating, modifying, and deleting configuration records. | ||
== OpenAPI Specification == | |||
The OpenAPI specification is available from: | The OpenAPI specification is available from: | ||
<pre> | |||
openapi.php | openapi.php | ||
openapi.php?spec=1 | openapi.php?spec=1 | ||
openapi.php/openapi.json | openapi.php/openapi.json | ||
openapi.php/swagger.json | openapi.php/swagger.json | ||
</pre> | |||
The response is an OpenAPI 3.0.3 JSON document. | The response is an OpenAPI 3.0.3 JSON document. | ||
== Authentication == | |||
The API key can be provided in any of these ways | The API key can be provided in any of these ways. | ||
=== Query Parameter === | |||
<pre> | |||
openapi.php/extensions?tenant=TENANTCODE&key=APIKEY | openapi.php/extensions?tenant=TENANTCODE&key=APIKEY | ||
</pre> | |||
=== Header === | |||
<pre> | |||
X-API-Key: APIKEY | X-API-Key: APIKEY | ||
</pre> | |||
=== Bearer Token === | |||
<pre> | |||
Authorization: Bearer APIKEY | |||
</pre> | |||
== API Key Scope == | |||
=== Tenant API Key === | |||
When using a tenant-level API key, the <code>tenant</code> parameter is required. | |||
<pre> | |||
openapi.php/extensions?tenant=TENANTCODE&key=TENANT_API_KEY | |||
</pre> | |||
=== Global API Key === | |||
When using a global API key, <code>tenant</code> is optional. | |||
If <code>tenant</code> is provided, only that tenant's records are returned. | |||
If <code>tenant</code> is omitted, records from all tenants are returned for list and get requests. | |||
<pre> | |||
openapi.php/extensions?key=GLOBAL_API_KEY | |||
</pre> | |||
Some objects can be edited at global level by adding <code>global=yes</code>. This is supported for global settings, global custom destinations, global media files, global music on hold, global caller ID blacklist entries, global cron jobs, global feature codes, and global short numbers. | |||
The <code>tenant</code>, <code>user</code>, <code>userprofile</code>, and <code>routingprofile</code> objects require an Admin API key. Tenant API keys are rejected for these objects. For users, adding <code>tenant=TENANTCODE</code> with an Admin API key filters list and get requests to users assigned to that tenant. | |||
<pre> | |||
openapi.php/featurecodes?global=yes&key=GLOBAL_API_KEY | |||
</pre> | |||
== List Extensions == | |||
=== Endpoint === | |||
<pre> | |||
GET openapi.php/extensions | |||
</pre> | |||
Alternative compatibility format: | |||
<pre> | |||
openapi.php?object=extension&action=list | |||
</pre> | |||
=== Parameters === | |||
{| class="wikitable" | |||
! Name | |||
! Required | |||
! Description | |||
|- | |||
| <code>key</code> | |||
| Yes, unless using header authentication | |||
| Full or read-only API key | |||
|- | |||
| <code>tenant</code> | |||
| Required for tenant keys | |||
| Tenant code or tenant name | |||
|} | |||
=== Example Request === | |||
<pre> | |||
curl "https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE&key=APIKEY" | |||
</pre> | |||
Using header authentication: | |||
<pre> | |||
curl \ | |||
-H "X-API-Key: APIKEY" \ | |||
"https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE" | |||
</pre> | |||
Using bearer authentication: | |||
<pre> | |||
curl \ | |||
-H "Authorization: Bearer APIKEY" \ | |||
"https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE" | |||
</pre> | |||
=== Example Response === | |||
<pre> | |||
[ | |||
{ | |||
"id": 101, | |||
"number": "100", | |||
"name": "Reception", | |||
"tech": "PJSIP" | |||
}, | |||
{ | |||
"id": 102, | |||
"number": "101", | |||
"name": "Office", | |||
"tech": "SIP" | |||
} | |||
] | |||
</pre> | |||
== Response Fields == | |||
{| class="wikitable" | |||
! Field | |||
! Type | |||
! Description | |||
|- | |||
| <code>id</code> | |||
| integer | |||
| Extension internal ID | |||
|- | |||
| <code>number</code> | |||
| string | |||
| Extension number | |||
|- | |||
| <code>name</code> | |||
| string | |||
| Extension display name | |||
|- | |||
| <code>tech</code> | |||
| string | |||
| Extension technology, for example <code>SIP</code>, <code>PJSIP</code>, <code>VIRTUAL</code>, or <code>CUSTOM</code> | |||
|} | |||
== Get Extension Information == | |||
This endpoint returns detailed information for one extension. | |||
The extension can be selected by internal extension ID or by extension number. | |||
When using the global full API key, the response also includes the extension password when a password exists for the extension technology. | |||
Tenant API keys and read-only API keys do not return the extension password. | |||
=== Endpoints === | |||
Get an extension by ID: | |||
<pre> | |||
GET openapi.php/extension?id=EXTENSION_ID | |||
</pre> | |||
Alternative path format: | |||
<pre> | |||
GET openapi.php/extensions/EXTENSION_ID | |||
</pre> | |||
Get an extension by number: | |||
<pre> | |||
GET openapi.php/extension?number=EXTENSION_NUMBER | |||
</pre> | |||
Alternative path format: | |||
<pre> | |||
GET openapi.php/extensions/number/EXTENSION_NUMBER | |||
</pre> | |||
Alternative compatibility format: | |||
<pre> | |||
openapi.php?object=extension&action=info&id=EXTENSION_ID | |||
openapi.php?object=extension&action=info&number=EXTENSION_NUMBER | |||
</pre> | |||
=== Parameters === | |||
{| class="wikitable" | |||
! Name | |||
! Required | |||
! Description | |||
|- | |||
| <code>key</code> | |||
| Yes, unless using header authentication | |||
| Full or read-only API key | |||
|- | |||
| <code>tenant</code> | |||
| Required for tenant keys | |||
| Tenant code or tenant name | |||
|- | |||
| <code>id</code> | |||
| Required if <code>number</code> is not provided | |||
| Extension internal ID | |||
|- | |||
| <code>number</code> | |||
| Required if <code>id</code> is not provided | |||
| Extension number | |||
|} | |||
Use either <code>id</code> or <code>number</code>, not both. | |||
When using a global API key without the <code>tenant</code> parameter, selecting by extension number can match more than one tenant. In that case the request returns an error and the request should be repeated using the <code>tenant</code> parameter or the extension ID. | |||
=== Example Requests === | |||
Get by ID: | |||
<pre> | |||
curl "https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE&key=APIKEY" | |||
</pre> | |||
Get by number: | |||
<pre> | |||
curl "https://pbx.example.com/openapi.php/extension?number=100&tenant=TENANTCODE&key=APIKEY" | |||
</pre> | |||
Using header authentication: | |||
<pre> | |||
curl \ | |||
-H "X-API-Key: APIKEY" \ | |||
"https://pbx.example.com/openapi.php/extension?number=100&tenant=TENANTCODE" | |||
</pre> | |||
=== Example Response === | |||
The response includes all fields from the extension table, the normalized fields <code>id</code>, <code>number</code>, <code>name</code>, and <code>tech</code>, the current state when available, the technology username, technology-specific details, and related records. | |||
Related records are returned in the <code>related</code> object. Depending on the extension configuration, this can include state information, registrations, PJSIP contacts, call groups, pickup groups, destinations, queue membership, allowed queue membership, user profile, routing profiles, client rate, caller ID regex, music on hold, parking lot, conditions, media files, and associated phones. | |||
The <code>me_data</code> binary field from media files is not returned in this response. | |||
<pre> | |||
{ | |||
"ex_id": "101", | |||
"ex_te_id": "1", | |||
"ex_name": "Reception", | |||
"ex_number": "100", | |||
"ex_tech": "PJSIP", | |||
"ex_tech_id": "55", | |||
"tenant_code": "TENANTCODE", | |||
"tenant_name": "Tenant Name", | |||
"id": 101, | |||
"number": "100", | |||
"name": "Reception", | |||
"tech": "PJSIP", | |||
"username": "100", | |||
"state": "NOT_INUSE", | |||
"st_state": "NOT_INUSE", | |||
"tech_details": { | |||
"endpoint": { | |||
"id": "100", | |||
"tech_id": "55", | |||
"te_id": "1" | |||
}, | |||
"aor": { | |||
"id": "100", | |||
"max_contacts": "99" | |||
}, | |||
"auth": { | |||
"id": "100", | |||
"username": "100" | |||
} | |||
}, | |||
"related": { | |||
"state": { | |||
"st_extension": "100", | |||
"st_state": "NOT_INUSE" | |||
}, | |||
"callgroups": [], | |||
"pickupgroups": [], | |||
"destinations": [], | |||
"referenced_by_destinations": [], | |||
"queue_members": [], | |||
"allowed_queue_members": [], | |||
"userprofile": { | |||
"up_id": "3", | |||
"up_name": "Basic user panel" | |||
}, | |||
"routing_profile": { | |||
"rp_id": "1", | |||
"rp_name": "Default" | |||
}, | |||
"sms_routing_profile": false, | |||
"client_rate": false, | |||
"callerid_regex": false, | |||
"callerid_regex_rules": [], | |||
"music_on_hold": false, | |||
"parkinglot": false, | |||
"conditions": [], | |||
"mediafiles": [], | |||
"phones": [] | |||
} | |||
} | |||
</pre> | |||
When the global full API key is used, the response can also include: | |||
<pre> | |||
{ | |||
"password": "extension_password" | |||
} | |||
</pre> | |||
== Create Extension == | |||
This endpoint creates one extension. A full API key is required. Read-only API keys are rejected. | |||
The request is checked against the installed license before the extension is created. | |||
=== Endpoint === | |||
<pre> | |||
POST openapi.php/extensions | |||
</pre> | |||
Alternative compatibility format: | |||
<pre> | |||
POST openapi.php?object=extension&action=add | |||
POST openapi.php?object=extension&action=create | |||
</pre> | |||
=== Parameters === | |||
{| class="wikitable" | |||
! Name | |||
! Required | |||
! Description | |||
|- | |||
| <code>key</code> | |||
| Yes, unless using header authentication | |||
| Full API key | |||
|- | |||
| <code>tenant</code> | |||
| Yes | |||
| Tenant code or tenant name | |||
|} | |||
=== Request Body === | |||
The body is JSON. The API accepts the extension table fields used by the web page, such as <code>ex_number</code>, <code>ex_name</code>, <code>ex_tech</code>, and the technology table fields for <code>sipfriends</code>, <code>ps_endpoints</code>, <code>ps_aors</code>, <code>ps_auths</code>, <code>ce_customextensions</code>, and <code>ve_virtualextensions</code>. | |||
Short aliases are also accepted: | |||
{| class="wikitable" | |||
! Alias | |||
! Field | |||
|- | |||
| <code>number</code> | |||
| <code>ex_number</code> | |||
|- | |||
| <code>name</code> | |||
| <code>ex_name</code> | |||
|- | |||
| <code>tech</code> | |||
| <code>ex_tech</code> | |||
|- | |||
| <code>password</code> | |||
| SIP <code>secret</code> or PJSIP auth <code>password</code> | |||
|- | |||
| <code>username</code> | |||
| Technology username | |||
|- | |||
| <code>sipusername</code> | |||
| Technology username, matching the web page field | |||
|- | |||
| <code>mailbox</code> | |||
| <code>ex_mailbox</code> and PJSIP <code>mailboxes</code> | |||
|} | |||
Supported technologies are <code>SIP</code>, <code>PJSIP</code>, <code>CUSTOM</code>, and <code>VIRTUAL</code>. If <code>tech</code> is omitted, <code>PJSIP</code> is used. | |||
=== Example Request === | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"number":"100","name":"Reception","tech":"PJSIP","password":"secret-password"}' \ | |||
"https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE" | |||
</pre> | |||
Nested technology fields can also be supplied: | |||
<pre> | |||
{ | |||
"ex_number": "100", | |||
"ex_name": "Reception", | |||
"ex_tech": "PJSIP", | |||
"ps_aors": { | |||
"max_contacts": 99 | |||
}, | |||
"ps_endpoints": { | |||
"allow": "alaw:20;ulaw:20" | |||
}, | |||
"ps_auths": { | |||
"password": "secret-password" | |||
} | |||
} | |||
</pre> | |||
=== Example Response === | |||
The response is the same detailed extension object returned by the get endpoint, with HTTP status <code>201</code>. | |||
== Modify Extension == | |||
This endpoint modifies an existing extension. A full API key is required. Read-only API keys are rejected. | |||
The extension can be selected by internal ID or extension number. Use either <code>id</code> or <code>number</code>, not both. | |||
=== Endpoints === | |||
<pre> | |||
PUT openapi.php/extension?id=EXTENSION_ID | |||
PATCH openapi.php/extension?id=EXTENSION_ID | |||
PATCH openapi.php/extensions/EXTENSION_ID | |||
</pre> | |||
Alternative compatibility format: | |||
<pre> | |||
PUT openapi.php?object=extension&action=update&objectid=EXTENSION_ID | |||
PATCH openapi.php?object=extension&action=modify&objectid=EXTENSION_ID | |||
</pre> | |||
=== Request Body === | |||
The body is JSON and can contain the same table fields accepted by the create endpoint. Only fields included in the body are updated. | |||
Changing the extension technology is not supported. To change technology, delete and recreate the extension. | |||
=== Example Request === | |||
<pre> | |||
curl \ | |||
-X PATCH \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"ex_name":"Reception Desk","ex_callgroup":"1,2","ex_pickupgroup":"1,2"}' \ | |||
"https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE" | |||
</pre> | |||
== Delete Extension == | |||
This endpoint deletes an extension and its related technology rows. A full API key is required. Read-only API keys are rejected. | |||
=== Endpoints === | |||
<pre> | |||
DELETE openapi.php/extension?id=EXTENSION_ID | |||
DELETE openapi.php/extensions/EXTENSION_ID | |||
</pre> | |||
Alternative compatibility format: | |||
<pre> | |||
DELETE openapi.php?object=extension&action=delete&objectid=EXTENSION_ID | |||
</pre> | |||
=== Example Request === | |||
<pre> | |||
curl \ | |||
-X DELETE \ | |||
-H "X-API-Key: APIKEY" \ | |||
"https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE" | |||
</pre> | |||
=== Example Response === | |||
<pre> | |||
{ | |||
"deleted": true, | |||
"id": 101, | |||
"number": "100" | |||
} | |||
</pre> | |||
== Extension Busy Destination == | |||
The busy destination for an extension can be set with the <code>onbusy</code> alias. | |||
Destination values use the same <code>TYPE-ID</code> format returned in <code>related.destinations</code>. For example, use <code>VOICEMAIL-12</code> for voicemail ID 12 or <code>EXT-45</code> for extension internal ID 45. Extension destinations use the extension internal ID, not the extension number. | |||
To send busy calls to an existing voicemail: | |||
<pre> | |||
curl \ | |||
-X PATCH \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"onbusy":["VOICEMAIL-12"]}' \ | |||
"https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE" | |||
</pre> | |||
The same destination can also be supplied with the explicit destination type: | |||
<pre> | |||
{ | |||
"destinations": { | |||
"EXT-BUSY": ["VOICEMAIL-12"] | |||
} | |||
} | |||
</pre> | |||
To use the extension same-number voicemail and create it automatically when missing: | |||
<pre> | |||
{ | |||
"onbusy": ["SAMENUMBERVM"] | |||
} | |||
</pre> | |||
Sending an empty array clears the busy destination: | |||
<pre> | |||
{ | |||
"onbusy": [] | |||
} | |||
</pre> | |||
== Additional Configuration Objects == | |||
The following objects use the same authentication and HTTP behavior as extensions. | |||
{| class="wikitable" | |||
! Object | |||
! List Endpoint | |||
! Single Endpoint | |||
! ID Field | |||
! Main Table | |||
|- | |||
| <code>voicemail</code> | |||
| <code>GET openapi.php/voicemails</code> | |||
| <code>openapi.php/voicemail?id=ID</code> | |||
| <code>uniqueid</code> | |||
| <code>voicemail</code> | |||
|- | |||
| <code>tenant</code> | |||
| <code>GET openapi.php/tenants</code> | |||
| <code>openapi.php/tenant?id=ID</code> | |||
| <code>te_id</code> | |||
| <code>te_tenants</code> | |||
|- | |||
| <code>user</code> | |||
| <code>GET openapi.php/users</code> | |||
| <code>openapi.php/user?id=ID</code> | |||
| <code>us_id</code> | |||
| <code>us_users</code> | |||
|- | |||
| <code>userprofile</code> | |||
| <code>GET openapi.php/userprofiles</code> | |||
| <code>openapi.php/userprofile?id=ID</code> | |||
| <code>up_id</code> | |||
| <code>up_userprofiles</code> | |||
|- | |||
| <code>routingprofile</code> | |||
| <code>GET openapi.php/routingprofiles</code> | |||
| <code>openapi.php/routingprofile?id=ID</code> | |||
| <code>rp_id</code> | |||
| <code>rp_routingprofiles</code> | |||
|- | |||
| <code>condition</code> | |||
| <code>GET openapi.php/conditions</code> | |||
| <code>openapi.php/condition?id=ID</code> | |||
| <code>co_id</code> | |||
| <code>co_conditions</code> | |||
|- | |||
| <code>ivr</code> | |||
| <code>GET openapi.php/ivrs</code> | |||
| <code>openapi.php/ivr?id=ID</code> | |||
| <code>iv_id</code> | |||
| <code>iv_ivrs</code> | |||
|- | |||
| <code>customdestination</code> | |||
| <code>GET openapi.php/customdestinations</code> | |||
| <code>openapi.php/customdestination?id=ID</code> | |||
| <code>cu_id</code> | |||
| <code>cu_customs</code> | |||
|- | |||
| <code>huntlist</code> | |||
| <code>GET openapi.php/huntlists</code> | |||
| <code>openapi.php/huntlist?id=ID</code> | |||
| <code>hu_id</code> | |||
| <code>hu_huntlists</code> | |||
|- | |||
| <code>did</code> | |||
| <code>GET openapi.php/dids</code> | |||
| <code>openapi.php/did?id=ID</code> | |||
| <code>di_id</code> | |||
| <code>di_dids</code> | |||
|- | |||
| <code>queue</code> | |||
| <code>GET openapi.php/queues</code> | |||
| <code>openapi.php/queue?id=ID</code> | |||
| <code>qu_id</code> | |||
| <code>qu_queues</code> | |||
|- | |||
| <code>setting</code> | |||
| <code>GET openapi.php/settings</code> | |||
| <code>openapi.php/setting?id=ID</code> | |||
| <code>se_id</code> | |||
| <code>se_settings</code> | |||
|- | |||
| <code>mediafile</code> | |||
| <code>GET openapi.php/mediafiles</code> | |||
| <code>openapi.php/mediafile?id=ID</code> | |||
| <code>me_id</code> | |||
| <code>me_mediafiles</code> | |||
|- | |||
| <code>musiconhold</code> | |||
| <code>GET openapi.php/musiconholds</code> | |||
| <code>openapi.php/musiconhold?id=ID</code> | |||
| <code>mu_id</code> | |||
| <code>mu_musiconholds</code> | |||
|- | |||
| <code>paginggroup</code> | |||
| <code>GET openapi.php/paginggroups</code> | |||
| <code>openapi.php/paginggroup?id=ID</code> | |||
| <code>pa_id</code> | |||
| <code>pa_paginggroups</code> | |||
|- | |||
| <code>conferenceroom</code> | |||
| <code>GET openapi.php/conferencerooms</code> | |||
| <code>openapi.php/conferenceroom?id=ID</code> | |||
| <code>cr_id</code> | |||
| <code>cr_conferencerooms</code> | |||
|- | |||
| <code>flow</code> | |||
| <code>GET openapi.php/flows</code> | |||
| <code>openapi.php/flow?id=ID</code> | |||
| <code>fl_id</code> | |||
| <code>fl_flows</code> | |||
|- | |||
| <code>tenantvariable</code> | |||
| <code>GET openapi.php/tenantvariables</code> | |||
| <code>openapi.php/tenantvariable?id=ID</code> | |||
| <code>tv_id</code> | |||
| <code>tv_tenantvariables</code> | |||
|- | |||
| <code>disa</code> | |||
| <code>GET openapi.php/disas</code> | |||
| <code>openapi.php/disa?id=ID</code> | |||
| <code>ds_id</code> | |||
| <code>ds_disas</code> | |||
|- | |||
| <code>calleridblacklist</code> | |||
| <code>GET openapi.php/calleridblacklists</code> | |||
| <code>openapi.php/calleridblacklist?id=ID</code> | |||
| <code>bl_id</code> | |||
| <code>bl_blacklists</code> | |||
|- | |||
| <code>campaign</code> | |||
| <code>GET openapi.php/campaigns</code> | |||
| <code>openapi.php/campaign?id=ID</code> | |||
| <code>ca_id</code> | |||
| <code>ca_campaigns</code> | |||
|- | |||
| <code>campaignnumber</code> | |||
| <code>GET openapi.php/campaignnumbers</code> | |||
| <code>openapi.php/campaignnumber?id=ID</code> | |||
| <code>cn_id</code> | |||
| <code>cn_campaignnumbers</code> | |||
|- | |||
| <code>cronjob</code> | |||
| <code>GET openapi.php/cronjobs</code> | |||
| <code>openapi.php/cronjob?id=ID</code> | |||
| <code>cr_id</code> | |||
| <code>cr_cronjobs</code> | |||
|- | |||
| <code>featurecode</code> | |||
| <code>GET openapi.php/featurecodes</code> | |||
| <code>openapi.php/featurecode?id=ID</code> | |||
| <code>fe_id</code> | |||
| <code>fe_features</code> | |||
|- | |||
| <code>shortnumber</code> | |||
| <code>GET openapi.php/shortnumbers</code> | |||
| <code>openapi.php/shortnumber?id=ID</code> | |||
| <code>sn_id</code> | |||
| <code>sn_shortnumbers</code> | |||
|- | |||
| <code>provisioningphone</code> | |||
| <code>GET openapi.php/provisioningphones</code> | |||
| <code>openapi.php/provisioningphone?id=ID</code> | |||
| <code>ph_id</code> | |||
| <code>ph_phones</code> | |||
|} | |||
=== Generic Endpoints === | |||
Use the plural path for list and create operations: | |||
<pre> | |||
GET openapi.php/voicemails | |||
POST openapi.php/voicemails | |||
GET openapi.php/tenants | |||
POST openapi.php/tenants | |||
GET openapi.php/users | |||
POST openapi.php/users | |||
GET openapi.php/userprofiles | |||
POST openapi.php/userprofiles | |||
GET openapi.php/routingprofiles | |||
POST openapi.php/routingprofiles | |||
GET openapi.php/conditions | |||
POST openapi.php/conditions | |||
GET openapi.php/ivrs | |||
POST openapi.php/ivrs | |||
GET openapi.php/customdestinations | |||
POST openapi.php/customdestinations | |||
GET openapi.php/huntlists | |||
POST openapi.php/huntlists | |||
GET openapi.php/dids | |||
POST openapi.php/dids | |||
GET openapi.php/queues | |||
POST openapi.php/queues | |||
GET openapi.php/settings | |||
POST openapi.php/settings | |||
GET openapi.php/mediafiles | |||
POST openapi.php/mediafiles | |||
GET openapi.php/musiconholds | |||
POST openapi.php/musiconholds | |||
GET openapi.php/paginggroups | |||
POST openapi.php/paginggroups | |||
GET openapi.php/conferencerooms | |||
POST openapi.php/conferencerooms | |||
GET openapi.php/flows | |||
POST openapi.php/flows | |||
GET openapi.php/tenantvariables | |||
POST openapi.php/tenantvariables | |||
GET openapi.php/disas | |||
POST openapi.php/disas | |||
GET openapi.php/calleridblacklists | |||
POST openapi.php/calleridblacklists | |||
GET openapi.php/campaigns | |||
POST openapi.php/campaigns | |||
GET openapi.php/campaignnumbers | |||
POST openapi.php/campaignnumbers | |||
GET openapi.php/cronjobs | |||
POST openapi.php/cronjobs | |||
GET openapi.php/featurecodes | |||
POST openapi.php/featurecodes | |||
GET openapi.php/shortnumbers | |||
POST openapi.php/shortnumbers | |||
GET openapi.php/provisioningphones | |||
POST openapi.php/provisioningphones | |||
</pre> | |||
Use either the singular endpoint with an <code>id</code> parameter or the plural path with the ID: | |||
<pre> | |||
GET openapi.php/voicemail?id=ID | |||
PATCH openapi.php/voicemail?id=ID | |||
DELETE openapi.php/voicemail?id=ID | |||
GET openapi.php/voicemails/ID | |||
PATCH openapi.php/voicemails/ID | |||
DELETE openapi.php/voicemails/ID | |||
</pre> | |||
The same pattern applies to all generic objects listed in the table above. | |||
Alternative compatibility format: | |||
<pre> | |||
openapi.php?object=voicemail&action=list | |||
openapi.php?object=voicemail&action=info&id=ID | |||
openapi.php?object=voicemail&action=create | |||
openapi.php?object=voicemail&action=modify&id=ID | |||
openapi.php?object=voicemail&action=delete&id=ID | |||
</pre> | |||
=== Generic Request Body === | |||
The body is JSON. Fields can be supplied using the database column names used by the web pages. | |||
For the <code>user</code> object, <code>password</code>, <code>_password</code>, and <code>us_password</code> are treated as clear text input and are stored using the same SHA-256 hash used by the web page. To provide a precomputed hash, use <code>password_hash</code> or <code>us_password_hash</code>. | |||
Short aliases are supported where they are unambiguous: | |||
{| class="wikitable" | |||
! Object | |||
! Alias | |||
! Field | |||
|- | |||
| <code>voicemail</code> | |||
| <code>number</code> | |||
| <code>mailbox</code> | |||
|- | |||
| <code>voicemail</code> | |||
| <code>name</code> | |||
| <code>fullname</code> | |||
|- | |||
| <code>tenant</code> | |||
| <code>name</code> | |||
| <code>te_name</code> | |||
|- | |||
| <code>tenant</code> | |||
| <code>code</code> | |||
| <code>te_code</code> | |||
|- | |||
| <code>user</code> | |||
| <code>username</code> | |||
| <code>us_username</code> | |||
|- | |||
| <code>user</code> | |||
| <code>password</code> | |||
| <code>us_password</code> | |||
|- | |||
| <code>user</code> | |||
| <code>profile_id</code> | |||
| <code>us_up_id</code> | |||
|- | |||
| <code>userprofile</code> | |||
| <code>name</code> | |||
| <code>up_name</code> | |||
|- | |||
| <code>userprofile</code> | |||
| <code>reserved</code> | |||
| <code>up_reserved</code> | |||
|- | |||
| <code>routingprofile</code> | |||
| <code>name</code> | |||
| <code>rp_name</code> | |||
|- | |||
| <code>routingprofile</code> | |||
| <code>type</code> | |||
| <code>rp_type</code> | |||
|- | |||
| <code>condition</code> | |||
| <code>name</code> | |||
| <code>co_name</code> | |||
|- | |||
| <code>condition</code> | |||
| <code>type</code> | |||
| <code>co_type</code> | |||
|- | |||
| <code>ivr</code> | |||
| <code>name</code> | |||
| <code>iv_name</code> | |||
|- | |||
| <code>customdestination</code> | |||
| <code>name</code> | |||
| <code>cu_name</code> | |||
|- | |||
| <code>huntlist</code> | |||
| <code>name</code> | |||
| <code>hu_name</code> | |||
|- | |||
| <code>huntlist</code> | |||
| <code>number</code> | |||
| <code>hu_number</code> | |||
|- | |||
| <code>did</code> | |||
| <code>number</code> | |||
| <code>di_number</code> | |||
|- | |||
| <code>queue</code> | |||
| <code>name</code> | |||
| <code>qu_name</code> | |||
|- | |||
| <code>setting</code> | |||
| <code>code</code> | |||
| <code>se_code</code> | |||
|- | |||
| <code>setting</code> | |||
| <code>value</code> | |||
| <code>se_value</code> | |||
|- | |||
| <code>mediafile</code> | |||
| <code>name</code> | |||
| <code>me_name</code> | |||
|- | |||
| <code>mediafile</code> | |||
| <code>data_base64</code> | |||
| <code>me_data</code> | |||
|- | |||
| <code>musiconhold</code> | |||
| <code>name</code> | |||
| <code>mu_name</code> | |||
|- | |||
| <code>musiconhold</code> | |||
| <code>custom</code> | |||
| <code>mu_custom</code> | |||
|- | |||
| <code>paginggroup</code> | |||
| <code>number</code> | |||
| <code>pa_number</code> | |||
|- | |||
| <code>paginggroup</code> | |||
| <code>name</code> | |||
| <code>pa_name</code> | |||
|- | |||
| <code>conferenceroom</code> | |||
| <code>name</code> | |||
| <code>cr_name</code> | |||
|- | |||
| <code>conferenceroom</code> | |||
| <code>number</code> | |||
| <code>cr_number</code> | |||
|- | |||
| <code>flow</code> | |||
| <code>name</code> | |||
| <code>fl_name</code> | |||
|- | |||
| <code>flow</code> | |||
| <code>variable_name</code> | |||
| <code>fl_variable_name</code> | |||
|- | |||
| <code>tenantvariable</code> | |||
| <code>variable_id</code> | |||
| <code>tv_al_id</code> | |||
|- | |||
| <code>tenantvariable</code> | |||
| <code>value</code> | |||
| <code>tv_value</code> | |||
|- | |||
| <code>disa</code> | |||
| <code>name</code> | |||
| <code>ds_name</code> | |||
|- | |||
| <code>calleridblacklist</code> | |||
| <code>callerid</code> | |||
| <code>bl_callerid</code> | |||
|- | |||
| <code>campaign</code> | |||
| <code>name</code> | |||
| <code>ca_name</code> | |||
|- | |||
| <code>campaign</code> | |||
| <code>state</code> | |||
| <code>ca_state</code> | |||
|- | |||
| <code>campaignnumber</code> | |||
| <code>campaign_id</code> | |||
| <code>cn_ca_id</code> | |||
|- | |||
| <code>campaignnumber</code> | |||
| <code>number</code> | |||
| <code>cn_number</code> | |||
|- | |||
| <code>cronjob</code> | |||
| <code>name</code> | |||
| <code>cr_name</code> | |||
|- | |||
| <code>cronjob</code> | |||
| <code>run</code> | |||
| <code>cr_run</code> | |||
|- | |||
| <code>featurecode</code> | |||
| <code>code</code> | |||
| <code>fe_code</code> | |||
|- | |||
| <code>shortnumber</code> | |||
| <code>number</code> | |||
| <code>sn_number</code> | |||
|- | |||
| <code>provisioningphone</code> | |||
| <code>name</code> | |||
| <code>ph_name</code> | |||
|- | |||
| <code>provisioningphone</code> | |||
| <code>mac</code> | |||
| <code>ph_mac</code> | |||
|} | |||
=== Destinations === | |||
Objects that use destinations accept a <code>destinations</code> object. Each destination item can be either a string in <code>TYPE-ID</code> format or an object with <code>type</code> and <code>id</code>. | |||
<pre> | |||
{ | |||
"di_number": "390212345678", | |||
"di_comment": "Main number", | |||
"destinations": { | |||
"DID": ["EXT-101"], | |||
"DID-UNCONDITIONAL": [ | |||
{ "type": "VOICEMAIL", "id": 10 } | |||
] | |||
} | |||
} | |||
</pre> | |||
Supported destination keys: | |||
{| class="wikitable" | |||
! Object | |||
! Destination Keys | |||
|- | |||
| <code>voicemail</code> | |||
| <code>VOICEMAIL-OPERATOR</code>, <code>VOICEMAIL-FOLLOW</code>, <code>VOICEMAIL-BROADCAST</code> | |||
|- | |||
| <code>condition</code> | |||
| <code>CONDITION</code>, <code>NOTCONDITION</code>, and <code>CONDITION1</code> through <code>CONDITION20</code> | |||
|- | |||
| <code>ivr</code> | |||
| <code>IVR_1</code> through <code>IVR_9</code>, <code>IVR_0</code>, <code>IVR_STAR</code>, <code>IVR_SHARP</code>, <code>IVR_WRONG</code>, <code>IVR_TIMEOUT</code>, <code>IVR_HANGUP</code>, <code>IVR_FEATURE</code>, <code>IVR_EXTENSION</code>, <code>IVR_MEDIAFILE</code>, <code>IVR_OPTIONSMEDIAFILE</code>, and custom keys beginning with <code>CUSTOMIVR_</code> | |||
|- | |||
| <code>customdestination</code> | |||
| <code>PRIVACY-DONTCALL</code>, <code>PRIVACY-TORTURE</code>, <code>CTONANSWER</code>, <code>CALLBACK-CONNECTED</code>, <code>CTONCALLERHANGUP</code>, <code>SPLITCHANNELACTION-CALLER</code>, <code>SPLITCHANNELACTION-CALLED</code>, and <code>RANDOMDESTINATION</code> keys | |||
|- | |||
| <code>musiconhold</code> | |||
| <code>MUSICONHOLD</code>. Plain numeric values are treated as media file IDs. | |||
|- | |||
| <code>paginggroup</code> | |||
| <code>PAGING</code>. Plain numeric values are treated as extension IDs. | |||
|- | |||
| <code>huntlist</code> | |||
| <code>HUNTLIST</code>, <code>HUNTLIST-TIMEOUT</code> | |||
|- | |||
| <code>did</code> | |||
| <code>DID</code>, <code>DID-UNCONDITIONAL</code>, <code>DID-SMS</code>, <code>DID-FAXSUCCESS</code> | |||
|- | |||
| <code>queue</code> | |||
| <code>QUEUE-FULL</code>, <code>QUEUE-TIMEOUT</code>, <code>QUEUE-EXITKEY</code>, <code>QUEUE-ONCALLBACK</code>, <code>QUEUE-NOBODYHOME</code>, <code>QUEUE-NOFREEMEMBER</code>, <code>QUEUE-PERIODICANNOUNCE</code>, <code>QUEUE-BEFORERINGING</code>, <code>QUEUE-ONAUTOPAUSE</code>, <code>QUEUE-ONABANDONEDCALL</code> | |||
|- | |||
| <code>flow</code> | |||
| <code>FLOW</code> | |||
|- | |||
| <code>campaign</code> | |||
| <code>CAMPAIGN-ONCONNECT</code> and <code>CAMPAIGN-DONOTCALL</code>. Plain numeric values for <code>CAMPAIGN-DONOTCALL</code> are treated as do-not-call IDs. | |||
|- | |||
| <code>cronjob</code> | |||
| <code>CRONJOB</code> | |||
|- | |||
| <code>featurecode</code> | |||
| <code>FEATURE</code> | |||
|} | |||
=== Related Records === | |||
Get responses include a <code>related</code> object when the object has related configuration. | |||
For users, <code>related.profile</code> contains the selected main user profile. <code>related.tenants</code>, <code>related.routing_profiles</code>, <code>related.allowed_userprofiles</code>, <code>related.client_rates</code>, and the restriction lists show the assignments used by the user page. Create and modify requests can replace these assignments by sending <code>tenants</code>, <code>routingprofiles</code>, <code>allowed_userprofiles</code>, <code>clientrates</code>, <code>queue_restrictions</code>, <code>extension_restrictions</code>, or <code>provider_restrictions</code> as arrays of IDs. | |||
For user profiles, <code>related.privileges</code> contains the assigned privilege rows. Create and modify requests can replace the assigned privileges by sending <code>privileges</code> as an array of privilege IDs or objects containing <code>ug_id</code> and optional <code>param1</code> through <code>param5</code>. | |||
For conditions, <code>related.extended_infos</code> contains rows from <code>ce_conditions_extended</code>. Create and modify requests can replace these rows by sending <code>extended_infos</code>. | |||
For queues, <code>related.realtime</code> contains the realtime <code>queue</code> row. Create and modify requests can send realtime queue fields either at the top level or nested under <code>queue</code> or <code>realtime</code>. Queue members can be replaced by sending <code>members</code>, <code>queue_member</code>, or <code>queue_members</code>. Allowed queue members can be replaced by sending <code>allowed_members</code>, <code>aq_allowed_queue_member</code>, or <code>allowed_queue_members</code>. | |||
For hunt lists, create and modify requests update the matching follow-me records used by the dialplan. | |||
For custom destinations, <code>related.extended_infos</code> contains rows from <code>ce_customs_extended</code> and <code>related.binary_files</code> lists stored binary records without returning the binary payload. | |||
For music on hold, <code>related.realtime</code> contains the linked <code>musiconhold</code> row and <code>related.entries</code> contains the generated playlist entries. Create and modify requests can send <code>mediafiles</code> as media file IDs or <code>MEDIAFILE-ID</code> strings. Sending <code>entries</code> replaces the raw <code>musiconhold_entry</code> rows directly. | |||
For conference rooms, <code>related.meetme</code> contains the linked realtime conference row. Creating a conference room also creates the linked <code>meetme</code> row, and deleting it removes that row. | |||
For flows, sending <code>status</code>, <code>state</code>, or <code>st_state</code> updates the matching <code>st_states</code> row when the flow has a number. | |||
For campaigns, <code>related.numbers_count</code>, <code>related.numbers_by_disposition</code>, and <code>related.binary_files</code> summarize linked campaign number and fax file records. Campaign fax files can be replaced by sending <code>binary_files</code> with <code>name</code> and <code>data_base64</code>. Campaign numbers are managed through the separate <code>campaignnumber</code> object. The list endpoint accepts <code>campaign_id</code> or <code>caid</code> to limit numbers to one campaign. | |||
For cron jobs, setting <code>run</code> to <code>yes</code> schedules a run in the same way as setting <code>cr_run</code>. | |||
For provisioning phones, <code>related.button_layouts</code> and <code>related.phonebooks</code> contain the linked phone layout and phonebook rows. | |||
=== Examples === | |||
Create a voicemail: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"mailbox":"200","fullname":"Sales","password":"1234","email":"sales@example.com"}' \ | |||
"https://pbx.example.com/openapi.php/voicemails?tenant=TENANTCODE" | |||
</pre> | |||
Modify a DID destination: | |||
<pre> | |||
curl \ | |||
-X PATCH \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"destinations":{"DID":["EXT-101"]}}' \ | |||
"https://pbx.example.com/openapi.php/did?id=25&tenant=TENANTCODE" | |||
</pre> | |||
Create a queue with realtime fields: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"qu_name":"Support","qu_number":"700","queue":{"strategy":"ringall","timeout":20},"members":[{"membername":"100","interface":"Local/AG-000-NF-101@fromotherpbx/n","state_interface":"Custom:100","member_device":"100","penalty":0,"paused":0}]}' \ | |||
"https://pbx.example.com/openapi.php/queues?tenant=TENANTCODE" | |||
</pre> | |||
Create a global feature code: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: GLOBAL_APIKEY" \ | |||
-d '{"code":"*56","comment":"Pickup"}' \ | |||
"https://pbx.example.com/openapi.php/featurecodes?global=yes" | |||
</pre> | |||
Create a conference room: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"name":"Weekly Meeting","number":"900","pin":"1234","adminpin":"4321","maxusers":10}' \ | |||
"https://pbx.example.com/openapi.php/conferencerooms?tenant=TENANTCODE" | |||
</pre> | |||
Create a music on hold playlist: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"name":"Support Hold","mediafiles":[12,15],"default":"on"}' \ | |||
"https://pbx.example.com/openapi.php/musiconholds?tenant=TENANTCODE" | |||
</pre> | |||
Create a campaign number: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"campaign_id":5,"number":"390212345678","description":"Lead A"}' \ | |||
"https://pbx.example.com/openapi.php/campaignnumbers?tenant=TENANTCODE" | |||
</pre> | |||
Run a cron job: | |||
<pre> | |||
curl \ | |||
-X PATCH \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: APIKEY" \ | |||
-d '{"run":"yes"}' \ | |||
"https://pbx.example.com/openapi.php/cronjob?id=8&tenant=TENANTCODE" | |||
</pre> | |||
Create a user and assign tenants, routing profiles, and allowed user profiles: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: GLOBAL_APIKEY" \ | |||
-d '{"username":"operator","password":"change-me","profile_id":3,"tenants":[1],"routingprofiles":[2,4],"allowed_userprofiles":[5]}' \ | |||
"https://pbx.example.com/openapi.php/users" | |||
</pre> | |||
Create a user profile with privileges: | |||
<pre> | |||
curl \ | |||
-X POST \ | |||
-H "Content-Type: application/json" \ | |||
-H "X-API-Key: GLOBAL_APIKEY" \ | |||
-d '{"name":"Helpdesk","description":"Helpdesk operators","privileges":[12,18,25]}' \ | |||
"https://pbx.example.com/openapi.php/userprofiles" | |||
</pre> | |||
== Change Logging == | |||
Create, modify, and delete operations write a process log entry and a user activity log entry using the OpenAPI user label. Related destination, user assignment, user profile privilege, condition, queue member, and queue realtime changes are also logged where applicable. | |||
=== Additional Error Responses === | |||
==== Missing Identifier ==== | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "missing_identifier", | |||
"message": "Provide an extension id or number." | |||
} | |||
} | |||
</pre> | |||
==== Invalid Identifier ==== | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "invalid_identifier", | |||
"message": "Use either id or number, not both." | |||
} | |||
} | |||
</pre> | |||
==== Extension Not Found ==== | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "extension_not_found", | |||
"message": "Extension not found." | |||
} | |||
} | |||
</pre> | |||
==== Multiple Extensions Found ==== | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "multiple_extensions_found", | |||
"message": "Multiple extensions match the requested number. Use the tenant parameter or the extension id." | |||
} | |||
} | |||
</pre> | |||
== Error Responses == | |||
Errors are returned as JSON. | |||
=== Missing API Key === | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "missing_api_key", | |||
"message": "Missing API key." | |||
} | |||
} | |||
</pre> | |||
=== Invalid API Key === | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "invalid_api_key", | |||
"message": "Invalid API key." | |||
} | |||
} | |||
</pre> | |||
=== Tenant Not Found === | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "tenant_not_found", | |||
"message": "Tenant not found." | |||
} | |||
} | |||
</pre> | |||
=== Endpoint Not Found === | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "not_found", | |||
"message": "Endpoint not found." | |||
} | |||
} | |||
</pre> | |||
=== Method Not Allowed === | |||
Supported methods are <code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>PATCH</code>, and <code>DELETE</code>. | |||
<pre> | |||
{ | |||
"error": { | |||
"code": "method_not_allowed", | |||
"message": "Supported methods are GET, POST, PUT, PATCH and DELETE." | |||
} | |||
} | |||
</pre> | |||
== Notes == | |||
* Read-only API keys are allowed for list and get endpoints. | |||
* A full API key is required for create, modify, and delete endpoints. | |||
* Sensitive fields such as passwords, API keys, tokens, and media binary data are hidden unless the global full API key is used. | |||
* The endpoint does not create a web session. | |||
* Responses are always JSON. | |||
* CORS is enabled with <code>Access-Control-Allow-Origin: *</code>. | |||
* <code>OPTIONS</code> requests return HTTP <code>204</code> for browser preflight support. | |||
Latest revision as of 12:05, 31 May 2026
Overview
Overview
openapi.php is the JSON API endpoint based on the OpenAPI specification.
The API uses the existing API keys:
- Full API key:
APIKEY - Read-only API key:
READONLYAPIKEY
Both global and tenant-level keys are supported.
The implemented API objects are extension, tenant, user, userprofile, routingprofile, voicemail, condition, huntlist, did, queue, ivr, customdestination, setting, mediafile, musiconhold, paginggroup, conferenceroom, flow, tenantvariable, disa, calleridblacklist, campaign, campaignnumber, cronjob, featurecode, shortnumber, and provisioningphone. They provide endpoints for listing, retrieving, creating, modifying, and deleting configuration records.
OpenAPI Specification
The OpenAPI specification is available from:
openapi.php openapi.php?spec=1 openapi.php/openapi.json openapi.php/swagger.json
The response is an OpenAPI 3.0.3 JSON document.
Authentication
The API key can be provided in any of these ways.
Query Parameter
openapi.php/extensions?tenant=TENANTCODE&key=APIKEY
Header
X-API-Key: APIKEY
Bearer Token
Authorization: Bearer APIKEY
API Key Scope
Tenant API Key
When using a tenant-level API key, the tenant parameter is required.
openapi.php/extensions?tenant=TENANTCODE&key=TENANT_API_KEY
Global API Key
When using a global API key, tenant is optional.
If tenant is provided, only that tenant's records are returned.
If tenant is omitted, records from all tenants are returned for list and get requests.
openapi.php/extensions?key=GLOBAL_API_KEY
Some objects can be edited at global level by adding global=yes. This is supported for global settings, global custom destinations, global media files, global music on hold, global caller ID blacklist entries, global cron jobs, global feature codes, and global short numbers.
The tenant, user, userprofile, and routingprofile objects require an Admin API key. Tenant API keys are rejected for these objects. For users, adding tenant=TENANTCODE with an Admin API key filters list and get requests to users assigned to that tenant.
openapi.php/featurecodes?global=yes&key=GLOBAL_API_KEY
List Extensions
Endpoint
GET openapi.php/extensions
Alternative compatibility format:
openapi.php?object=extension&action=list
Parameters
| Name | Required | Description |
|---|---|---|
key
|
Yes, unless using header authentication | Full or read-only API key |
tenant
|
Required for tenant keys | Tenant code or tenant name |
Example Request
curl "https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE&key=APIKEY"
Using header authentication:
curl \ -H "X-API-Key: APIKEY" \ "https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE"
Using bearer authentication:
curl \ -H "Authorization: Bearer APIKEY" \ "https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE"
Example Response
[
{
"id": 101,
"number": "100",
"name": "Reception",
"tech": "PJSIP"
},
{
"id": 102,
"number": "101",
"name": "Office",
"tech": "SIP"
}
]
Response Fields
| Field | Type | Description |
|---|---|---|
id
|
integer | Extension internal ID |
number
|
string | Extension number |
name
|
string | Extension display name |
tech
|
string | Extension technology, for example SIP, PJSIP, VIRTUAL, or CUSTOM
|
Get Extension Information
This endpoint returns detailed information for one extension.
The extension can be selected by internal extension ID or by extension number.
When using the global full API key, the response also includes the extension password when a password exists for the extension technology.
Tenant API keys and read-only API keys do not return the extension password.
Endpoints
Get an extension by ID:
GET openapi.php/extension?id=EXTENSION_ID
Alternative path format:
GET openapi.php/extensions/EXTENSION_ID
Get an extension by number:
GET openapi.php/extension?number=EXTENSION_NUMBER
Alternative path format:
GET openapi.php/extensions/number/EXTENSION_NUMBER
Alternative compatibility format:
openapi.php?object=extension&action=info&id=EXTENSION_ID openapi.php?object=extension&action=info&number=EXTENSION_NUMBER
Parameters
| Name | Required | Description |
|---|---|---|
key
|
Yes, unless using header authentication | Full or read-only API key |
tenant
|
Required for tenant keys | Tenant code or tenant name |
id
|
Required if number is not provided
|
Extension internal ID |
number
|
Required if id is not provided
|
Extension number |
Use either id or number, not both.
When using a global API key without the tenant parameter, selecting by extension number can match more than one tenant. In that case the request returns an error and the request should be repeated using the tenant parameter or the extension ID.
Example Requests
Get by ID:
curl "https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE&key=APIKEY"
Get by number:
curl "https://pbx.example.com/openapi.php/extension?number=100&tenant=TENANTCODE&key=APIKEY"
Using header authentication:
curl \ -H "X-API-Key: APIKEY" \ "https://pbx.example.com/openapi.php/extension?number=100&tenant=TENANTCODE"
Example Response
The response includes all fields from the extension table, the normalized fields id, number, name, and tech, the current state when available, the technology username, technology-specific details, and related records.
Related records are returned in the related object. Depending on the extension configuration, this can include state information, registrations, PJSIP contacts, call groups, pickup groups, destinations, queue membership, allowed queue membership, user profile, routing profiles, client rate, caller ID regex, music on hold, parking lot, conditions, media files, and associated phones.
The me_data binary field from media files is not returned in this response.
{
"ex_id": "101",
"ex_te_id": "1",
"ex_name": "Reception",
"ex_number": "100",
"ex_tech": "PJSIP",
"ex_tech_id": "55",
"tenant_code": "TENANTCODE",
"tenant_name": "Tenant Name",
"id": 101,
"number": "100",
"name": "Reception",
"tech": "PJSIP",
"username": "100",
"state": "NOT_INUSE",
"st_state": "NOT_INUSE",
"tech_details": {
"endpoint": {
"id": "100",
"tech_id": "55",
"te_id": "1"
},
"aor": {
"id": "100",
"max_contacts": "99"
},
"auth": {
"id": "100",
"username": "100"
}
},
"related": {
"state": {
"st_extension": "100",
"st_state": "NOT_INUSE"
},
"callgroups": [],
"pickupgroups": [],
"destinations": [],
"referenced_by_destinations": [],
"queue_members": [],
"allowed_queue_members": [],
"userprofile": {
"up_id": "3",
"up_name": "Basic user panel"
},
"routing_profile": {
"rp_id": "1",
"rp_name": "Default"
},
"sms_routing_profile": false,
"client_rate": false,
"callerid_regex": false,
"callerid_regex_rules": [],
"music_on_hold": false,
"parkinglot": false,
"conditions": [],
"mediafiles": [],
"phones": []
}
}
When the global full API key is used, the response can also include:
{
"password": "extension_password"
}
Create Extension
This endpoint creates one extension. A full API key is required. Read-only API keys are rejected.
The request is checked against the installed license before the extension is created.
Endpoint
POST openapi.php/extensions
Alternative compatibility format:
POST openapi.php?object=extension&action=add POST openapi.php?object=extension&action=create
Parameters
| Name | Required | Description |
|---|---|---|
key
|
Yes, unless using header authentication | Full API key |
tenant
|
Yes | Tenant code or tenant name |
Request Body
The body is JSON. The API accepts the extension table fields used by the web page, such as ex_number, ex_name, ex_tech, and the technology table fields for sipfriends, ps_endpoints, ps_aors, ps_auths, ce_customextensions, and ve_virtualextensions.
Short aliases are also accepted:
| Alias | Field |
|---|---|
number
|
ex_number
|
name
|
ex_name
|
tech
|
ex_tech
|
password
|
SIP secret or PJSIP auth password
|
username
|
Technology username |
sipusername
|
Technology username, matching the web page field |
mailbox
|
ex_mailbox and PJSIP mailboxes
|
Supported technologies are SIP, PJSIP, CUSTOM, and VIRTUAL. If tech is omitted, PJSIP is used.
Example Request
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"number":"100","name":"Reception","tech":"PJSIP","password":"secret-password"}' \
"https://pbx.example.com/openapi.php/extensions?tenant=TENANTCODE"
Nested technology fields can also be supplied:
{
"ex_number": "100",
"ex_name": "Reception",
"ex_tech": "PJSIP",
"ps_aors": {
"max_contacts": 99
},
"ps_endpoints": {
"allow": "alaw:20;ulaw:20"
},
"ps_auths": {
"password": "secret-password"
}
}
Example Response
The response is the same detailed extension object returned by the get endpoint, with HTTP status 201.
Modify Extension
This endpoint modifies an existing extension. A full API key is required. Read-only API keys are rejected.
The extension can be selected by internal ID or extension number. Use either id or number, not both.
Endpoints
PUT openapi.php/extension?id=EXTENSION_ID PATCH openapi.php/extension?id=EXTENSION_ID PATCH openapi.php/extensions/EXTENSION_ID
Alternative compatibility format:
PUT openapi.php?object=extension&action=update&objectid=EXTENSION_ID PATCH openapi.php?object=extension&action=modify&objectid=EXTENSION_ID
Request Body
The body is JSON and can contain the same table fields accepted by the create endpoint. Only fields included in the body are updated.
Changing the extension technology is not supported. To change technology, delete and recreate the extension.
Example Request
curl \
-X PATCH \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"ex_name":"Reception Desk","ex_callgroup":"1,2","ex_pickupgroup":"1,2"}' \
"https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE"
Delete Extension
This endpoint deletes an extension and its related technology rows. A full API key is required. Read-only API keys are rejected.
Endpoints
DELETE openapi.php/extension?id=EXTENSION_ID DELETE openapi.php/extensions/EXTENSION_ID
Alternative compatibility format:
DELETE openapi.php?object=extension&action=delete&objectid=EXTENSION_ID
Example Request
curl \ -X DELETE \ -H "X-API-Key: APIKEY" \ "https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE"
Example Response
{
"deleted": true,
"id": 101,
"number": "100"
}
Extension Busy Destination
The busy destination for an extension can be set with the onbusy alias.
Destination values use the same TYPE-ID format returned in related.destinations. For example, use VOICEMAIL-12 for voicemail ID 12 or EXT-45 for extension internal ID 45. Extension destinations use the extension internal ID, not the extension number.
To send busy calls to an existing voicemail:
curl \
-X PATCH \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"onbusy":["VOICEMAIL-12"]}' \
"https://pbx.example.com/openapi.php/extension?id=101&tenant=TENANTCODE"
The same destination can also be supplied with the explicit destination type:
{
"destinations": {
"EXT-BUSY": ["VOICEMAIL-12"]
}
}
To use the extension same-number voicemail and create it automatically when missing:
{
"onbusy": ["SAMENUMBERVM"]
}
Sending an empty array clears the busy destination:
{
"onbusy": []
}
Additional Configuration Objects
The following objects use the same authentication and HTTP behavior as extensions.
| Object | List Endpoint | Single Endpoint | ID Field | Main Table |
|---|---|---|---|---|
voicemail
|
GET openapi.php/voicemails
|
openapi.php/voicemail?id=ID
|
uniqueid
|
voicemail
|
tenant
|
GET openapi.php/tenants
|
openapi.php/tenant?id=ID
|
te_id
|
te_tenants
|
user
|
GET openapi.php/users
|
openapi.php/user?id=ID
|
us_id
|
us_users
|
userprofile
|
GET openapi.php/userprofiles
|
openapi.php/userprofile?id=ID
|
up_id
|
up_userprofiles
|
routingprofile
|
GET openapi.php/routingprofiles
|
openapi.php/routingprofile?id=ID
|
rp_id
|
rp_routingprofiles
|
condition
|
GET openapi.php/conditions
|
openapi.php/condition?id=ID
|
co_id
|
co_conditions
|
ivr
|
GET openapi.php/ivrs
|
openapi.php/ivr?id=ID
|
iv_id
|
iv_ivrs
|
customdestination
|
GET openapi.php/customdestinations
|
openapi.php/customdestination?id=ID
|
cu_id
|
cu_customs
|
huntlist
|
GET openapi.php/huntlists
|
openapi.php/huntlist?id=ID
|
hu_id
|
hu_huntlists
|
did
|
GET openapi.php/dids
|
openapi.php/did?id=ID
|
di_id
|
di_dids
|
queue
|
GET openapi.php/queues
|
openapi.php/queue?id=ID
|
qu_id
|
qu_queues
|
setting
|
GET openapi.php/settings
|
openapi.php/setting?id=ID
|
se_id
|
se_settings
|
mediafile
|
GET openapi.php/mediafiles
|
openapi.php/mediafile?id=ID
|
me_id
|
me_mediafiles
|
musiconhold
|
GET openapi.php/musiconholds
|
openapi.php/musiconhold?id=ID
|
mu_id
|
mu_musiconholds
|
paginggroup
|
GET openapi.php/paginggroups
|
openapi.php/paginggroup?id=ID
|
pa_id
|
pa_paginggroups
|
conferenceroom
|
GET openapi.php/conferencerooms
|
openapi.php/conferenceroom?id=ID
|
cr_id
|
cr_conferencerooms
|
flow
|
GET openapi.php/flows
|
openapi.php/flow?id=ID
|
fl_id
|
fl_flows
|
tenantvariable
|
GET openapi.php/tenantvariables
|
openapi.php/tenantvariable?id=ID
|
tv_id
|
tv_tenantvariables
|
disa
|
GET openapi.php/disas
|
openapi.php/disa?id=ID
|
ds_id
|
ds_disas
|
calleridblacklist
|
GET openapi.php/calleridblacklists
|
openapi.php/calleridblacklist?id=ID
|
bl_id
|
bl_blacklists
|
campaign
|
GET openapi.php/campaigns
|
openapi.php/campaign?id=ID
|
ca_id
|
ca_campaigns
|
campaignnumber
|
GET openapi.php/campaignnumbers
|
openapi.php/campaignnumber?id=ID
|
cn_id
|
cn_campaignnumbers
|
cronjob
|
GET openapi.php/cronjobs
|
openapi.php/cronjob?id=ID
|
cr_id
|
cr_cronjobs
|
featurecode
|
GET openapi.php/featurecodes
|
openapi.php/featurecode?id=ID
|
fe_id
|
fe_features
|
shortnumber
|
GET openapi.php/shortnumbers
|
openapi.php/shortnumber?id=ID
|
sn_id
|
sn_shortnumbers
|
provisioningphone
|
GET openapi.php/provisioningphones
|
openapi.php/provisioningphone?id=ID
|
ph_id
|
ph_phones
|
Generic Endpoints
Use the plural path for list and create operations:
GET openapi.php/voicemails POST openapi.php/voicemails GET openapi.php/tenants POST openapi.php/tenants GET openapi.php/users POST openapi.php/users GET openapi.php/userprofiles POST openapi.php/userprofiles GET openapi.php/routingprofiles POST openapi.php/routingprofiles GET openapi.php/conditions POST openapi.php/conditions GET openapi.php/ivrs POST openapi.php/ivrs GET openapi.php/customdestinations POST openapi.php/customdestinations GET openapi.php/huntlists POST openapi.php/huntlists GET openapi.php/dids POST openapi.php/dids GET openapi.php/queues POST openapi.php/queues GET openapi.php/settings POST openapi.php/settings GET openapi.php/mediafiles POST openapi.php/mediafiles GET openapi.php/musiconholds POST openapi.php/musiconholds GET openapi.php/paginggroups POST openapi.php/paginggroups GET openapi.php/conferencerooms POST openapi.php/conferencerooms GET openapi.php/flows POST openapi.php/flows GET openapi.php/tenantvariables POST openapi.php/tenantvariables GET openapi.php/disas POST openapi.php/disas GET openapi.php/calleridblacklists POST openapi.php/calleridblacklists GET openapi.php/campaigns POST openapi.php/campaigns GET openapi.php/campaignnumbers POST openapi.php/campaignnumbers GET openapi.php/cronjobs POST openapi.php/cronjobs GET openapi.php/featurecodes POST openapi.php/featurecodes GET openapi.php/shortnumbers POST openapi.php/shortnumbers GET openapi.php/provisioningphones POST openapi.php/provisioningphones
Use either the singular endpoint with an id parameter or the plural path with the ID:
GET openapi.php/voicemail?id=ID PATCH openapi.php/voicemail?id=ID DELETE openapi.php/voicemail?id=ID GET openapi.php/voicemails/ID PATCH openapi.php/voicemails/ID DELETE openapi.php/voicemails/ID
The same pattern applies to all generic objects listed in the table above.
Alternative compatibility format:
openapi.php?object=voicemail&action=list openapi.php?object=voicemail&action=info&id=ID openapi.php?object=voicemail&action=create openapi.php?object=voicemail&action=modify&id=ID openapi.php?object=voicemail&action=delete&id=ID
Generic Request Body
The body is JSON. Fields can be supplied using the database column names used by the web pages.
For the user object, password, _password, and us_password are treated as clear text input and are stored using the same SHA-256 hash used by the web page. To provide a precomputed hash, use password_hash or us_password_hash.
Short aliases are supported where they are unambiguous:
| Object | Alias | Field |
|---|---|---|
voicemail
|
number
|
mailbox
|
voicemail
|
name
|
fullname
|
tenant
|
name
|
te_name
|
tenant
|
code
|
te_code
|
user
|
username
|
us_username
|
user
|
password
|
us_password
|
user
|
profile_id
|
us_up_id
|
userprofile
|
name
|
up_name
|
userprofile
|
reserved
|
up_reserved
|
routingprofile
|
name
|
rp_name
|
routingprofile
|
type
|
rp_type
|
condition
|
name
|
co_name
|
condition
|
type
|
co_type
|
ivr
|
name
|
iv_name
|
customdestination
|
name
|
cu_name
|
huntlist
|
name
|
hu_name
|
huntlist
|
number
|
hu_number
|
did
|
number
|
di_number
|
queue
|
name
|
qu_name
|
setting
|
code
|
se_code
|
setting
|
value
|
se_value
|
mediafile
|
name
|
me_name
|
mediafile
|
data_base64
|
me_data
|
musiconhold
|
name
|
mu_name
|
musiconhold
|
custom
|
mu_custom
|
paginggroup
|
number
|
pa_number
|
paginggroup
|
name
|
pa_name
|
conferenceroom
|
name
|
cr_name
|
conferenceroom
|
number
|
cr_number
|
flow
|
name
|
fl_name
|
flow
|
variable_name
|
fl_variable_name
|
tenantvariable
|
variable_id
|
tv_al_id
|
tenantvariable
|
value
|
tv_value
|
disa
|
name
|
ds_name
|
calleridblacklist
|
callerid
|
bl_callerid
|
campaign
|
name
|
ca_name
|
campaign
|
state
|
ca_state
|
campaignnumber
|
campaign_id
|
cn_ca_id
|
campaignnumber
|
number
|
cn_number
|
cronjob
|
name
|
cr_name
|
cronjob
|
run
|
cr_run
|
featurecode
|
code
|
fe_code
|
shortnumber
|
number
|
sn_number
|
provisioningphone
|
name
|
ph_name
|
provisioningphone
|
mac
|
ph_mac
|
Destinations
Objects that use destinations accept a destinations object. Each destination item can be either a string in TYPE-ID format or an object with type and id.
{
"di_number": "390212345678",
"di_comment": "Main number",
"destinations": {
"DID": ["EXT-101"],
"DID-UNCONDITIONAL": [
{ "type": "VOICEMAIL", "id": 10 }
]
}
}
Supported destination keys:
| Object | Destination Keys |
|---|---|
voicemail
|
VOICEMAIL-OPERATOR, VOICEMAIL-FOLLOW, VOICEMAIL-BROADCAST
|
condition
|
CONDITION, NOTCONDITION, and CONDITION1 through CONDITION20
|
ivr
|
IVR_1 through IVR_9, IVR_0, IVR_STAR, IVR_SHARP, IVR_WRONG, IVR_TIMEOUT, IVR_HANGUP, IVR_FEATURE, IVR_EXTENSION, IVR_MEDIAFILE, IVR_OPTIONSMEDIAFILE, and custom keys beginning with CUSTOMIVR_
|
customdestination
|
PRIVACY-DONTCALL, PRIVACY-TORTURE, CTONANSWER, CALLBACK-CONNECTED, CTONCALLERHANGUP, SPLITCHANNELACTION-CALLER, SPLITCHANNELACTION-CALLED, and RANDOMDESTINATION keys
|
musiconhold
|
MUSICONHOLD. Plain numeric values are treated as media file IDs.
|
paginggroup
|
PAGING. Plain numeric values are treated as extension IDs.
|
huntlist
|
HUNTLIST, HUNTLIST-TIMEOUT
|
did
|
DID, DID-UNCONDITIONAL, DID-SMS, DID-FAXSUCCESS
|
queue
|
QUEUE-FULL, QUEUE-TIMEOUT, QUEUE-EXITKEY, QUEUE-ONCALLBACK, QUEUE-NOBODYHOME, QUEUE-NOFREEMEMBER, QUEUE-PERIODICANNOUNCE, QUEUE-BEFORERINGING, QUEUE-ONAUTOPAUSE, QUEUE-ONABANDONEDCALL
|
flow
|
FLOW
|
campaign
|
CAMPAIGN-ONCONNECT and CAMPAIGN-DONOTCALL. Plain numeric values for CAMPAIGN-DONOTCALL are treated as do-not-call IDs.
|
cronjob
|
CRONJOB
|
featurecode
|
FEATURE
|
Related Records
Get responses include a related object when the object has related configuration.
For users, related.profile contains the selected main user profile. related.tenants, related.routing_profiles, related.allowed_userprofiles, related.client_rates, and the restriction lists show the assignments used by the user page. Create and modify requests can replace these assignments by sending tenants, routingprofiles, allowed_userprofiles, clientrates, queue_restrictions, extension_restrictions, or provider_restrictions as arrays of IDs.
For user profiles, related.privileges contains the assigned privilege rows. Create and modify requests can replace the assigned privileges by sending privileges as an array of privilege IDs or objects containing ug_id and optional param1 through param5.
For conditions, related.extended_infos contains rows from ce_conditions_extended. Create and modify requests can replace these rows by sending extended_infos.
For queues, related.realtime contains the realtime queue row. Create and modify requests can send realtime queue fields either at the top level or nested under queue or realtime. Queue members can be replaced by sending members, queue_member, or queue_members. Allowed queue members can be replaced by sending allowed_members, aq_allowed_queue_member, or allowed_queue_members.
For hunt lists, create and modify requests update the matching follow-me records used by the dialplan.
For custom destinations, related.extended_infos contains rows from ce_customs_extended and related.binary_files lists stored binary records without returning the binary payload.
For music on hold, related.realtime contains the linked musiconhold row and related.entries contains the generated playlist entries. Create and modify requests can send mediafiles as media file IDs or MEDIAFILE-ID strings. Sending entries replaces the raw musiconhold_entry rows directly.
For conference rooms, related.meetme contains the linked realtime conference row. Creating a conference room also creates the linked meetme row, and deleting it removes that row.
For flows, sending status, state, or st_state updates the matching st_states row when the flow has a number.
For campaigns, related.numbers_count, related.numbers_by_disposition, and related.binary_files summarize linked campaign number and fax file records. Campaign fax files can be replaced by sending binary_files with name and data_base64. Campaign numbers are managed through the separate campaignnumber object. The list endpoint accepts campaign_id or caid to limit numbers to one campaign.
For cron jobs, setting run to yes schedules a run in the same way as setting cr_run.
For provisioning phones, related.button_layouts and related.phonebooks contain the linked phone layout and phonebook rows.
Examples
Create a voicemail:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"mailbox":"200","fullname":"Sales","password":"1234","email":"sales@example.com"}' \
"https://pbx.example.com/openapi.php/voicemails?tenant=TENANTCODE"
Modify a DID destination:
curl \
-X PATCH \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"destinations":{"DID":["EXT-101"]}}' \
"https://pbx.example.com/openapi.php/did?id=25&tenant=TENANTCODE"
Create a queue with realtime fields:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"qu_name":"Support","qu_number":"700","queue":{"strategy":"ringall","timeout":20},"members":[{"membername":"100","interface":"Local/AG-000-NF-101@fromotherpbx/n","state_interface":"Custom:100","member_device":"100","penalty":0,"paused":0}]}' \
"https://pbx.example.com/openapi.php/queues?tenant=TENANTCODE"
Create a global feature code:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: GLOBAL_APIKEY" \
-d '{"code":"*56","comment":"Pickup"}' \
"https://pbx.example.com/openapi.php/featurecodes?global=yes"
Create a conference room:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"name":"Weekly Meeting","number":"900","pin":"1234","adminpin":"4321","maxusers":10}' \
"https://pbx.example.com/openapi.php/conferencerooms?tenant=TENANTCODE"
Create a music on hold playlist:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"name":"Support Hold","mediafiles":[12,15],"default":"on"}' \
"https://pbx.example.com/openapi.php/musiconholds?tenant=TENANTCODE"
Create a campaign number:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"campaign_id":5,"number":"390212345678","description":"Lead A"}' \
"https://pbx.example.com/openapi.php/campaignnumbers?tenant=TENANTCODE"
Run a cron job:
curl \
-X PATCH \
-H "Content-Type: application/json" \
-H "X-API-Key: APIKEY" \
-d '{"run":"yes"}' \
"https://pbx.example.com/openapi.php/cronjob?id=8&tenant=TENANTCODE"
Create a user and assign tenants, routing profiles, and allowed user profiles:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: GLOBAL_APIKEY" \
-d '{"username":"operator","password":"change-me","profile_id":3,"tenants":[1],"routingprofiles":[2,4],"allowed_userprofiles":[5]}' \
"https://pbx.example.com/openapi.php/users"
Create a user profile with privileges:
curl \
-X POST \
-H "Content-Type: application/json" \
-H "X-API-Key: GLOBAL_APIKEY" \
-d '{"name":"Helpdesk","description":"Helpdesk operators","privileges":[12,18,25]}' \
"https://pbx.example.com/openapi.php/userprofiles"
Change Logging
Create, modify, and delete operations write a process log entry and a user activity log entry using the OpenAPI user label. Related destination, user assignment, user profile privilege, condition, queue member, and queue realtime changes are also logged where applicable.
Additional Error Responses
Missing Identifier
{
"error": {
"code": "missing_identifier",
"message": "Provide an extension id or number."
}
}
Invalid Identifier
{
"error": {
"code": "invalid_identifier",
"message": "Use either id or number, not both."
}
}
Extension Not Found
{
"error": {
"code": "extension_not_found",
"message": "Extension not found."
}
}
Multiple Extensions Found
{
"error": {
"code": "multiple_extensions_found",
"message": "Multiple extensions match the requested number. Use the tenant parameter or the extension id."
}
}
Error Responses
Errors are returned as JSON.
Missing API Key
{
"error": {
"code": "missing_api_key",
"message": "Missing API key."
}
}
Invalid API Key
{
"error": {
"code": "invalid_api_key",
"message": "Invalid API key."
}
}
Tenant Not Found
{
"error": {
"code": "tenant_not_found",
"message": "Tenant not found."
}
}
Endpoint Not Found
{
"error": {
"code": "not_found",
"message": "Endpoint not found."
}
}
Method Not Allowed
Supported methods are GET, POST, PUT, PATCH, and DELETE.
{
"error": {
"code": "method_not_allowed",
"message": "Supported methods are GET, POST, PUT, PATCH and DELETE."
}
}
Notes
- Read-only API keys are allowed for list and get endpoints.
- A full API key is required for create, modify, and delete endpoints.
- Sensitive fields such as passwords, API keys, tokens, and media binary data are hidden unless the global full API key is used.
- The endpoint does not create a web session.
- Responses are always JSON.
- CORS is enabled with
Access-Control-Allow-Origin: *. OPTIONSrequests return HTTP204for browser preflight support.