API Basics
Warning: The API offers powerful capabilities that can significantly affect your system configuration. If not used with extreme care, there is a high potential to corrupt your setup. Restoring a system damaged due to improper API usage may incur additional costs. Please exercise caution when utilizing the API to prevent any unintended consequences.
The API is the REST API server, from which developers can build applications that configure the platform’s myriad services and functionalities.
Basic URI Structure
Section titled “Basic URI Structure”Requests follow this structure:
/{VERSION}/accounts/{ACCOUNT_ID}/resources/{RESOURCE_ID}Here’s the explanation:
{VERSION}— The version of the API you are calling. Currently the only supported value isv2.{ACCOUNT_ID}— Most requests operate against a specific account and thus require theaccount_idto route the request properly.{RESOURCE_ID}— When accessing a specific resource, like a device, user, or callflow,{RESOURCE_ID}points to the specific instance you’re accessing.
Resources
Section titled “Resources”There are two parts to how a request is routed in the API: the REST endpoint and the resource ID. Let’s break down a common URI and see how the API figures out what is an endpoint and what is a resource ID.
Given a URI of /v2/accounts/{ACCOUNT_ID}/devices/{DEVICE_ID}:
- First, strip the version off the URI:
- Version:
v2 - URI Remaining:
/accounts/{ACCOUNT_ID}/devices/{DEVICE_ID}
- Version:
- See if the next token is a REST endpoint module. It is, so track the module for later routing:
- Version:
v2 - Modules:
{accounts: []} - URI Remaining:
/{ACCOUNT_ID}/devices/{DEVICE_ID}
- Version:
- See if the next token is a REST endpoint module. It is not, so add the token to the last module’s data:
- Version:
v2 - Modules:
{accounts: [{ACCOUNT_ID}]} - URI Remaining:
/devices/{DEVICE_ID}
- Version:
- Repeat parsing.
devicesis a REST endpoint:- Version:
v2 - Modules:
{accounts: [{ACCOUNT_ID}], devices: []} - Remaining URI:
/{DEVICE_ID}
- Version:
- Repeat parsing.
{DEVICE_ID}is an argument:- Version:
v2 - Modules:
{accounts: [{ACCOUNT_ID}], devices: [{DEVICE_ID}]}
- Version:
So we have a request to account {ACCOUNT_ID} to do something with a device {DEVICE_ID}.
HTTP Verbs
Section titled “HTTP Verbs”The HTTP verb will determine the class of actions to take against the resource. Generically speaking, the verbs map thusly:
/v2/accounts/{ACCOUNT_ID}/resourcesGET: Fetches a summary of configured resourcesPUT: Creates a new instance of the resource
/v2/accounts/{ACCOUNT_ID}/resources/{RESOURCE_ID}GET: Fetches the full representation of the resourcePOST: Updates the full representation of the resourceDELETE: Deletes the resource
Some resources support the PATCH verb, allowing partial updates instead of requiring the request to include the full version of the document. /users/{USER_ID}, for instance, supports PATCH:
curl -v -X PATCH \ -H "Content-Type: application/json" \ -H "X-Auth-Token: {AUTH_TOKEN}" \ 'https://{SERVER_URL}:8443/v2/accounts/{ACCOUNT_ID}/users/{USER_ID}' \ -d '{"data":{"vm_to_email_enabled":true}}'This cURL request will patch the user’s document and set vm_to_email_enabled to true. All normal validation will occur after patching the document; this also means clients can PATCH documents with their own data only.
If a resource does not support PATCH yet, clients can expect to receive a 405 Method Not Allowed error.
Tunneling the HTTP Verb
Section titled “Tunneling the HTTP Verb”Some clients do not support the full range of HTTP verbs, and are typically limited to GET and POST. To access the functionalities of PUT and DELETE, you can tunnel the verb in a POST in a couple of ways:
- As part of the request envelope:
{"data":{...}, "verb":"PUT"} - As a query string parameter:
/v2/accounts/{ACCOUNT_ID}/resources?verb=PUT
Tunnelling the Accept Header
Section titled “Tunnelling the Accept Header”Some clients do not support the ability to set the Accept header in the request, meaning they will not necessarily receive the response in the format they wish. Clients can append accept=text/html to the request body or query string to indicate they’d like the response processed as if the Accept header was text/html.
Request Envelope
Section titled “Request Envelope”When issuing a PUT, POST, or DELETE, a request body is needed. When submitting JSON (the most common body), the API expects a request envelope with a few bits of metadata:
data: this top-level key will contain the object you wish to create/updateauth_token: optionally put your auth token in the envelopeverb: optionally tunnel aPUTorDELETEin aPOSTrequest
Sample Request Envelope:
{ "data": { "foo": "bar" }, "auth_token": "{AUTH_TOKEN}", "verb": "delete"}Request Data
Section titled “Request Data”When using PATCH to edit entities, if you want to remove a field from the entity, set it to null:
{ "data": { "update": "this", "exists": null }}This request would set update to "this" and would remove exists from the entity.
Response Envelope
Section titled “Response Envelope”When receiving JSON responses, clients will receive the response in an envelope. The response includes some duplicated data from the HTTP Response headers, since some clients do not have access to those headers.
data: contains the results of the request, if anyauth_token: contains theauth_tokenused on the requeststatus: One ofsuccess,error, orfatalmessage: Optional message that should clarify what happened on the requesterror: Error code, if anyrequest_id: ID of the request; usable for debugging the server-side processing of the request
Sample Response Envelope:
{ "data": { "the": "response", "data": "is here" }, "auth_token": "{AUTH_TOKEN}", "status": "success", "request_id": "{REQUEST_ID}"}Pagination
Section titled “Pagination”All listing APIs will be paginated by default. Let’s take a look at the CDRs API to see how to interpret pagination.
CDR Pagination
Section titled “CDR Pagination”We start with the typical CDR request for a listing of CDRs:
curl -v \ -H "X-Auth-Token: {AUTH_TOKEN}" \ -H "Content-Type: application/json" \ https://{SERVER_URL}:8443/v2/accounts/{ACCOUNT_ID}/cdrs{ "auth_token": "{AUTH_TOKEN}", "data": [ {CDR_OBJECT}, {CDR_OBJECT}, ... ], "next_start_key": "g2wAAAACbgUAvn1W1A5tAAAACDk4MDE2ODAwag", "page_size": 25, "request_id": "{REQUEST_ID}", "revision": "{REVISION}", "start_key": "g2wAAAACbgUAb0ZX1A5oAWpq", "status": "success"}The pagination response keys are next_start_key, page_size, and start_key.
next_start_key: used to get the next page of results from this API. Will not exist if this is the last page.start_key: used to get back to this page of results (or start pagination from this point)page_size: the number of results returned in this page
Assuming no changes are made to the underlying documents, start_key will get you this page of results, and next_start_key will give you a pointer to the next page (imagine a linked-list).
Encoded Start Keys
Section titled “Encoded Start Keys”As you can see from the response above, both the start_key and next_start_key are encoded as URL-safe Base64 strings of their Erlang term representation. A couple character substitutions (_ for / and _ for +) and one character removal (=) ensures a string that plays nice in URLs.
In practice, the client should treat these keys as opaque and supply them as-is in future requests.
Requesting next page
Section titled “Requesting next page”Using the next_start_key value, let’s request the next page of CDRs:
curl -v \ -H "X-Auth-Token: {AUTH_TOKEN}" \ -H "Content-Type: application/json" \ 'https://{SERVER_URL}:8443/v2/accounts/{ACCOUNT_ID}/cdrs?start_key=g2wAAAACbgUAb0ZX1A5oAWpq'{ "auth_token": "{AUTH_TOKEN}", "data": [ {CDR_OBJECT}, {CDR_OBJECT}, ... ], "next_start_key": "g2wAAAACbgUAbyYO1A5tAAAACDYwMTIzYjdiag", "page_size": 25, "request_id": "{REQUEST_ID}", "revision": "{REVISION}", "start_key": "g2wAAAACbgUAb0ZX1A5oAWpq", "status": "success"}Observe now that start_key is the requested start_key and next_start_key points to the start of the next page of results.
You can also choose to receive pages in bigger or smaller increments by specifying page_size on the request. Do take care, as the next_start_key will probably vary if you use the same start_key but differing page_size values.
Setting Page Size
Section titled “Setting Page Size”By default, API requests have a page size of 50 results. For individual API requests, you can also include a page_size query string parameter. For example: https://{SERVER}:8443/v2/{API_URL}?page_size=25.
Setting sorting order
Section titled “Setting sorting order”By default, the API returns the results in descending order. To get results in ascending order either set ascending=true or descending=false in the request query string.
Disabling Pagination
Section titled “Disabling Pagination”If you want to disable pagination for a request, simply include paginate=false on the query string.
Protecting from (un)intentional abuse
Section titled “Protecting from (un)intentional abuse”Since pagination can be turned off by a client-supplied query string parameter, it is important that the platform still protect itself from overly large datasets being loaded. Examples seen include large CDR listings, call recording listings, and ledger listings.
Therefore, during a non-paginated request, the platform monitors memory consumption of the handling server process and will abort the request if the processing is exceeding a high watermark setting (configured by the system operator). The client can expect to receive an HTTP 416 Range Not Satisfiable error as a result of exceeding the limit.
Chunked Response
Section titled “Chunked Response”Most of the summary API endpoints can send chunked responses. Some known APIs, which tend to have larger datasets, are chunked by default (e.g. /cdrs/interaction and /ledgers/{LEDGER}).
The query string parameter is_chunked (boolean value) can be used to enable or disable chunking per-request.
To set the default chunk size, you can use chunk_size in the query string. Default value is 50.
Pretty Printing
Section titled “Pretty Printing”If the JSON response needs to be pretty printed, the server can do so. Include the pretty print flag inside the header:
curl -v \ -H "X-Auth-Token: {AUTH_TOKEN}" \ -H "Content-Type: application/json" \ -H "X-Pretty-Print:true" \ https://{SERVER_URL}:8443/v2/accounts/{ACCOUNT_ID}/If the client cannot use headers, the options can be included inside the URI:
curl -v \ -H "X-Auth-Token: {AUTH_TOKEN}" \ -H "Content-Type: application/json" \ 'https://{SERVER_URL}:8443/v2/accounts/{ACCOUNT_ID}?pretty_print=true'Requesting a range of binary data
Section titled “Requesting a range of binary data”It is useful to be able to get just a section of a file when streaming or resuming a download. This can be accomplished with the Range header, e.g.:
curl -v \ -H "X-Auth-Token: {AUTH_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: audio/mpeg" \ -H "Range: bytes={START_BYTE}-{END_BYTE}" \ https://{SERVER_URL}:8443/v2/accounts/{ACCOUNT_ID}/vmboxes/{VMBOX_ID}/messages/{MESSAGE_ID}/rawRequesting data in CSV format
Section titled “Requesting data in CSV format”In some cases (e.g. CDR) it’s possible to request data in CSV format. You must define the Content-Type in the header. You can define the file name in the request header or URL (optional):
curl -v -X GET \ -H "Accept: text/csv" \ -H "X-Auth-Token: {AUTH_TOKEN}" \ -H "X-File-Name: {FILE_NAME}" \ https://{SERVER}:8443/v2/accounts/{ACCOUNT_ID}/cdrsor
curl -v -X GET \ -H "Accept: text/csv" \ -H "X-Auth-Token: {AUTH_TOKEN}" \ 'https://{SERVER}:8443/v2/accounts/{ACCOUNT_ID}/cdrs?file_name={FILE_NAME}'Timestamps
Section titled “Timestamps”Unless explicitly stated, times are represented in Gregorian seconds. Conversion with UNIX timestamps is straightforward:
UnixEpochInGregorian = 62167219200gregorian_to_unix($greg) -> $greg - 62167219200unix_to_gregorian($unix) -> $unix + 62167219200