CEN/Docs
CEN Documentation

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)
  • number is 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
  }
}
FieldRule
protocolMust be iax2.
blockMust equal the first three digits of the request.
numberMust equal the last four digits. CEN dials this on your PBX.
hostA hostname or IPv4 address. Letters, digits, dots and hyphens only.
portA 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.

Download Integration API Explorer