Community setup guide · Customer guide
Routing API contract
The HTTPS endpoint a network that keeps its own routing must implement. CEN calls it when someone dials a number in your area, then gives the caller a dial string for the PBX you name.
Need a working implementation? Download the self-hosted Community Router for CloudPanel →
Request
GET {your Routing API URL}?number=3151234
Accept: application/json
User-Agent: CEN-Hub/1.0
Authorization: Bearer cen_hubreq_… (only if you generated a token in CEN)
numberis always seven ASCII digits: your three-digit block and four-digit line. The area code is never included.- CEN calls your API while the caller waits, over HTTPS only, without following redirects, and gives up after 2 s to connect and 4 s in total. Respond in well under a second.
- CEN only calls public addresses. URLs that resolve to private, loopback or reserved ranges are refused.
Route response
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true,
"status": "route",
"destination": {
"protocol": "iax2",
"block": "315",
"number": "1234",
"host": "pbx.example.net",
"port": 4569
}
}
| Field | Rule |
|---|---|
| protocol | Must be iax2. |
| block | Must equal the first three digits of the request. |
| number | Must equal the last four digits. CEN dials this on your PBX. |
| host | A hostname or IPv4 address. Letters, digits, dots and hyphens only. |
| port | A JSON integer from 1 to 65535. Strings are rejected. |
Intercept response
For numbers you don’t serve, return {"success": true, "status": "intercept"}; the caller hears CEN-08 (number not found). Any other status code, malformed JSON, response over 64 KB or rule violation gives CEN-05 (network unavailable). Either way the call ends.
Example implementations
PHP
<?php
$token = getenv('CEN_TOKEN'); // the token you generated in CEN, if any
if ($token !== false && ! hash_equals('Bearer '.$token, $_SERVER['HTTP_AUTHORIZATION'] ?? '')) {
http_response_code(401); exit;
}
$number = $_GET['number'] ?? '';
header('Content-Type: application/json');
if (! preg_match('/\A[0-9]{7}\z/D', $number)) {
http_response_code(422); echo json_encode(['success' => false]); exit;
}
$blocks = ['315' => ['host' => 'pbx-north.example.net', 'port' => 4569]];
$block = substr($number, 0, 3);
echo json_encode(isset($blocks[$block])
? ['success' => true, 'status' => 'route', 'destination' => ['protocol' => 'iax2', 'block' => $block, 'number' => substr($number, 3)] + $blocks[$block]]
: ['success' => true, 'status' => 'intercept']);
Python (Flask)
import hmac, os, re
from flask import Flask, jsonify, request
app = Flask(__name__)
BLOCKS = {'315': ('pbx-north.example.net', 4569)}
@app.get('/cen/route')
def route():
token = os.environ.get('CEN_TOKEN')
if token and not hmac.compare_digest(request.headers.get('Authorization', ''), 'Bearer ' + token):
return '', 401
number = request.args.get('number', '')
if not re.fullmatch(r'[0-9]{7}', number):
return jsonify(success=False), 422
if number[:3] not in BLOCKS:
return jsonify(success=True, status='intercept')
host, port = BLOCKS[number[:3]]
return jsonify(success=True, status='route', destination={'protocol': 'iax2', 'block': number[:3], 'number': number[3:], 'host': host, 'port': port})
CEN-hosted networks
For CEN-hosted networks CEN operates this same contract at https://api.cenpbx.com/v1/networks/{area}/route, answering from the branches listed at manage.cenpbx.com. It requires a network API key; see the API reference.