The Internet Centre VoIP and SMS APIs provide a programming interface to work with our telephony platform: check number availability, order and route DIDs, manage CNAM and e911, port numbers in (LNP), and send/receive SMS. Everything below is live on portal.incentre.net.
This document is regularly updated as we add functionality based on customer requests. If there is a feature you would like added, please email support@incentre.com with the subject "VoIP API addition".
The VoIP engine is a RESTful API that operates over HTTPS. The engine is stateless; each request carries all data required for processing, and each request must bear the authentication credentials issued by the Internet Centre platform.
Requests and responses are JSON objects. A standard response (or error) consists of three parts:
The status code returned in the response indicates whether the request was accepted.
| Code | Meaning |
|---|---|
| 200 | Request was successfully accepted |
| 400 | Bad request due to format mismatch, e.g. a parameter containing invalid characters |
| 401 | Access denied. Likely a wrong user/password, or wrong authentication for the data being accessed |
| 403 | Unauthorized. The requested operation is not available for this user |
| 406 | Failed business-logic validation, e.g. a mandatory parameter is missing for the requested operation |
| 409 | Too many requests. May be returned if rate limits are set up for the account |
| 5xx | Server error. Indicates an exception in processing due to a failure in the API engine, or a malformed request |
Login is standard HTTP Basic authentication, where the username is your login email to portal.incentre.net and the password is your portal password.
$ch = curl_init('https://portal.incentre.net/api/did/availability/?npa=780');
curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $password);
GET Returns a JSON object listing rate centers available for porting (LNP) or new ordering (NEW).
https://portal.incentre.net/api/did/availability/?npanxx=780436
| Field | Description |
|---|---|
| npa | 3-digit area code |
| nxx | 3-digit local calling code |
| npanxx | Combined NPANXX |
| ratecenter | Rate center, e.g. TORONTO |
| region | Two-letter province/state |
| type | LNP (port-in) or NEW (ordering) |
{
"operation": "availability",
"ratecenters": [
{
"npa": "780", // Area code
"nxx": "436", // Local calling code
"npanxx": "780436", // Combined NPANXX
"ratecenter": "EDMONTON",// Rate center
"region": "AB", // Two-letter province/state
"type": "LNP", // LNP (port-in) or NEW (ordering) available
"carrier": "8083" // Optional: originating carrier of NXX
},
{
"npa": "780",
"nxx": "436",
"npanxx": "780436",
"ratecenter": "EDMONTON",
"region": "AB",
"type": "NEW",
"carrier": "8083"
}
]
}
$ch = curl_init('https://portal.incentre.net/api/did/availability/?npanxx=780436');
curl_setopt($ch, CURLOPT_USERPWD, "you@example.com:YOUR_PASSWORD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_PORT, 443);
curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
$response = json_decode(curl_exec($ch));
print '<pre>'.print_r($response, true);
curl_close($ch);
POST to place an order; GET to check status.
https://portal.incentre.net/api/did/order/new/
{
"subscriber_id": XXX,
"rate_center": "EDMONTON",
"quantity": 2,
"carrier_reference": "order101-uuid"
}
| Field | Description |
|---|---|
| subscriber_id | integer, required. The VoIP subscriber (= trunk) where the DID will be assigned |
| rate_center | string(100), required. Name of the rate center in which DIDs are requested. Must be a valid short name as defined in the NAALEND database |
| npa | string(10), optional. Three digits representing the NPA if a specific NPA is requested. If present, must be exactly 3 digits |
| quantity | integer, required. Quantity of numbers requested. Must be in the 1-1000 range |
| carrier_reference | string(100), optional. Optional reference field. May contain any string. Not used for processing |
{
"id": "0bdaea5f-97f4-4f6d-a13b-1a6109c927da", // Transaction ID for reference
"status": "new", // Status
"errors": [], // Array of errors
"order": { // Order object
"rate_center": "EDMONTON",
"quantity": 2,
"carrier_reference": "order101-uuid"
}
}
$data_encoded = json_encode(array(
'rate_center' => 'EDMONTON',
'quantity' => 2,
'carrier_reference' => 'order101-uuid'
));
$ch = curl_init('https://portal.incentre.net/api/did/order/new/');
curl_setopt($ch, CURLOPT_USERPWD, "you@example.com:YOUR_PASSWORD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_PORT, 443);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_encoded);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: '.strlen($data_encoded)));
$raw = curl_exec($ch);
$info = curl_getinfo($ch); // http_code 200 is an OK reply
$response = json_decode($raw);
print json_encode($response, JSON_PRETTY_PRINT)."\n";
curl_close($ch);
https://portal.incentre.net/api/did/order/status/?uuid={$transactionid}
{$transactionid} is the UUID returned in the original order, e.g. 0bdaea5f-97f4-4f6d-a13b-1a6109c927da.
{
"id": "0bdaea5f-9806-4821-ab98-f00e34cdc329",
"status": "new",
"errors": [],
"order": {
"rate_center": "EDMONTON",
"quantity": 1,
"carrier_reference": "order101-uuid"
}
}
| Status | Description |
|---|---|
| New | The order was created inside the portal and is ready for processing. Being the initial state, it is unlikely to be observed due to its temporary nature |
| Processing | The order is being processed by the portal. In most cases it is being processed by the carrier |
| Completed | Processing is complete and numbers were successfully issued. Final state; no further actions are allowed |
| Error | Processing is complete but no numbers were issued due to an error. The error field of the order object contains details. Final state |
| Field | Description |
|---|---|
| order_id | string(50), required. Human-readable order ID (typical format NO-XXX; may vary by carrier). This is not the request ID (available as api_id inside the order) |
| quantity | int, required. Number of DIDs requested |
| rate_center | varchar(50), required. Rate center short name |
| carrier | varchar(10), required. Carrier code |
| status | varchar(50), required. Current status of the order |
| error | string(1000), optional. Carrier-specific string containing error details |
| carrier_reference_order | string(100), optional. The carrier_reference value submitted during the request |
| api_id | string(50), optional. ID of the API request associated with the order. Should not be empty for any request created via the API |
| dids | Array of string(20), optional. For completed orders, the list of DIDs reserved during fulfillment. Its size should match the quantity field |
POST to place a new port-in request.
https://portal.incentre.net/api/did/lnp/new/
{
"subscriber_id": XXX, // Replace with your Trunk ID
"type": "lnp",
"parameters": {
"address": {
"name": "Incentre office 7807015617",
"building": "",
"floor": "",
"room": "",
"city": "Edmonton",
"region": "AB",
"street_name": "95",
"street_type": "Street",
"street_directional": "NW",
"street_number": "4130",
"postal_code": "T6E 6H5",
"descriptive_location": ""
},
"dids": [ "17807015617" ],
"provider_type": "wireline",
"requested_due_date": "2020-11-07T00:00:00.000Z",
"existing_account_num": "58674207",
"esn_meid": "",
"end_user_name": "Example Corp",
"local_reseller": "Example Corp",
"comment_carrier_winning": "",
"comment_carrier_loosing": "",
"did_ranges": [],
"cancellation_requested": false,
"loa_date": "2020-10-29",
"customer_specific_object": {
"subscriber_id": 2,
"client_id": 3
}
}
}
| Field | Description |
|---|---|
| subscriber_id | integer, required. The VoIP subscriber (= trunk) where the DID will be assigned |
| type | static = lnp |
| parameters | object. The LNP request goes here |
| address | object. Customer address; stored by "name" in the DB |
| name | string, optional. Name of the address entity for your reference |
| building / floor / room | string, optional |
| city | string, required. City name, e.g. Edmonton |
| region | string, required. Two-letter province/state, e.g. AB |
| street_number | string, required. Street number, e.g. "3434" |
| street_name | string, required. Street name, e.g. "West" |
| street_type | string, required. Street type, e.g. "Landing" |
| street_directional | string, required. Directional, e.g. "NW" |
| postal_code | string, required. 7 characters with space, e.g. "T6W 0T4" |
| descriptive_location | string, optional. For rural addresses |
| dids | string array. This or did_ranges is required, e.g. 17804506787 |
| provider_type | string, required. wireline or wireless |
| requested_due_date | date, required. Timestamp format, e.g. 2020-10-29T00:00:00.000Z |
| existing_account_num | string, required. Existing customer account number |
| esn_meid | string, optional. ESN / MEID if applicable |
| local_service_provider | string, optional. OCN of the losing carrier |
| end_user_name | string, required. Existing customer name |
| local_reseller | string, required. Losing carrier name |
| comment_carrier_winning | string, optional. Comment to the winning carrier (usually blank) |
| comment_carrier_loosing | string, optional. Comment from the losing carrier (usually blank) |
| did_ranges | object, optional. This or dids is required. Contains npa, nxx, start, end (called/caller number range; end can equal start) |
| cancellation_requested | bool, optional. Used to update an order when a cancellation is requested |
| loa_date | date, required. Letter of Authorization date, e.g. 2020-10-29 |
| customer_specific_object | object, optional. Client object to be passed on the order |
{
"has_error": false,
"http_code": 200,
"http_status": "OK",
"http_message": "5780e813-c0d4-4807-bb2a-0d34630ecf3d" // Transaction ID for reference
}
Example of an error during submission:
{
"has_error": true,
"http_code": 401,
"http_status": "Unauthorized",
"http_message": ""
}
$date = new DateTime();
$authdate = $date->format('Y-m-d');
$date->modify('+9 days');
$reqdate = $date->format('Y-m-d');
$data_encoded = json_encode(array(
"subscriber_id" => 194,
"type" => "lnp",
"parameters" => array(
"address" => array(
"name" => "Incentre office 7807015617",
"city" => "Edmonton",
"region" => "AB",
"street_name" => "95 Street NW",
"street_number" => "4130",
"postal_code" => "T6E 6H5"
),
"dids" => array("17807015617"),
"provider_type" => "Wireline",
"requested_due_date" => $reqdate."T00:00:00.000Z",
"existing_account_num" => "58674207",
"end_user_name" => "Example Corp",
"local_reseller" => "Example Corp",
"did_ranges" => array(),
"cancellation_requested" => false,
"loa_date" => $authdate,
"customer_specific_object" => array("subscriber_id" => 2, "client_id" => 3)
)
));
$ch = curl_init('https://portal.incentre.net/api/did/lnp/new/');
curl_setopt($ch, CURLOPT_USERPWD, "you@example.com:YOUR_PASSWORD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_PORT, 443);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_encoded);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: '.strlen($data_encoded)));
$raw = curl_exec($ch);
$response = json_decode($raw);
print json_encode($response, JSON_PRETTY_PRINT)."\n";
curl_close($ch);
| Status | Description |
|---|---|
| New | Order is received by the API platform |
| Draft | Order passed initial validation and was submitted to the Incentre VoIP platform. It becomes visible inside the portal at this stage |
| Pending | Order is submitted and being processed by the Incentre VoIP backend, pending submission to the selected carrier |
| Processing | Order is submitted to the carrier. A carrier reference ID is available |
| Confirmed | Positive confirmation received from the carrier. Carrier processing is complete; Incentre VoIP is performing internal activation of the number with the new carrier |
| Completed / Closed | Final state. Successful completion; DID(s) are ported in, active, and ready for use |
| Cancelled | Final state. The order was cancelled |
| Error | Final state. Error in processing (not related to the carrier) |
| Rejected | Final state. The order was rejected by the carrier |
View or update the CNAM (caller ID name) for a DID. The GET form can also be used by a customer PBX (e.g. FreePBX) to look up caller-ID name information when it is not passed via the SIP header.
https://portal.incentre.net/api/did/cnam/7806688400
This also queries the public CNAM database.
$data_encoded = json_encode(array("cnam" => "Example Name"));
$ch = curl_init('https://portal.incentre.net/api/did/cnam/7806688400');
curl_setopt($ch, CURLOPT_USERPWD, "you@example.com:YOUR_PASSWORD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_PORT, 443);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_encoded);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: '.strlen($data_encoded)));
$raw = curl_exec($ch);
$response = json_decode($raw);
print json_encode($response, JSON_PRETTY_PRINT)."\n";
curl_close($ch);
| Field | Description |
|---|---|
| cnam | 3 - 15 character alphanumeric caller-ID name. This is in addition to what is passed by the client's PBX |
View, update, or delete the e911 registration for a DID.
View: https://portal.incentre.net/api/did/e911/7806688400
Delete: https://portal.incentre.net/api/did/e911/7806688400?action=delete
$data_encoded = json_encode(array(
'first_name' => 'Jane',
'last_name' => 'Doe',
'street_number' => '3434',
'unit' => '',
'street_name' => 'West Landing NW',
'city' => 'Edmonton',
'province' => 'AB',
'postal' => 'T6W 0T4',
'other' => '',
'special' => 'N'
));
$ch = curl_init('https://portal.incentre.net/api/did/e911/7806688400');
curl_setopt($ch, CURLOPT_USERPWD, "you@example.com:YOUR_PASSWORD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_PORT, 443);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_encoded);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: '.strlen($data_encoded)));
$raw = curl_exec($ch);
$response = json_decode($raw);
print json_encode($response, JSON_PRETTY_PRINT)."\n";
curl_close($ch);
| Field | Description |
|---|---|
| first_name | First name |
| last_name | Last name |
| unit | Unit / suite / apt number |
| street_number | Street number |
| street_name | Street name, including directional where appropriate |
| city | City |
| province | 2-letter province, e.g. "AB" |
| postal | Postal code |
| other | Descriptive address information or other info for the 911 operator |
| special | Enhanced-911 capable (generally "N") |
SMS is available on all DIDs across our network. It uses the same authentication as the rest of the API (your portal.incentre.net login over HTTP Basic auth). Inbound routing is configured per DID from the portal, in the same place you manage CNAM and e911.
POST a JSON body to the send endpoint. The from number must be one of your own DIDs.
https://portal.incentre.net/api/did/smssend
{
"from": "7806688400",
"to": "7809168202",
"text": "Hello this is dog."
}
| Field | Description |
|---|---|
| from | required. The sending number. Must be one of your DIDs |
| to | required. The destination number |
| text | required. The message body |
$data_encoded = json_encode(array(
'from' => '7806688400',
'to' => '7809168202',
'text' => 'Hello this is dog.'
));
$ch = curl_init('https://portal.incentre.net/api/did/smssend');
curl_setopt($ch, CURLOPT_USERPWD, "you@example.com:YOUR_PASSWORD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_PORT, 443);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_encoded);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: '.strlen($data_encoded)));
$raw = curl_exec($ch);
$response = json_decode($raw);
print json_encode($response, JSON_PRETTY_PRINT)."\n";
curl_close($ch);
Each DID can route inbound SMS one of several ways. You choose the action per DID from the portal, alongside the CNAM / e911 / 3CX options:
| Action | Behavior |
|---|---|
| store | Log only, viewable in the portal UI (the default when nothing else is set) |
| Deliver the message to an email address (SMS-to-email) | |
| forward | Re-send the message as an outbound SMS to another number |
| webhook | HTTP POST a JSON payload to a URL of your choice (see below) |
| 3cx | Deliver to a 3CX generic SMS endpoint |
When a DID is set to webhook, we HTTP POST a JSON object to your URL for each inbound message. The useful fields are:
| Field | Description |
|---|---|
| src | Sender's number |
| dst | Destination number (your DID) |
| msg | Message body |
| did | Your DID that received the message |
| dir | Direction, "in" for inbound |
| ts | Timestamp the message was received |
{
"did": "17806688400",
"dir": "in",
"ts": "2026-07-06 09:31:00",
"src": "17809168202",
"dst": "17806688400",
"msg": "Hello this is dog."
}
Your endpoint should return an HTTP 2xx to acknowledge receipt. A 5xx is retried (up to 3 attempts); a 4xx is treated as a permanent failure. The URL also supports {field} token substitution, so you can build the target from message fields, e.g. https://example.com/sms?to={dst}&from={src}.