StratusTalk Avion
Versioned JSON API for the Avion control plane. The GUI uses same-origin session auth; MCP and external agents will use Bearer tokens (Sanctum personal access tokens) once issued for superadmins.
All endpoints are under /api/v1. Current host: https://avion.stratustalk.com.
GET https://avion.stratustalk.com/api/v1/...
Log in to Avion in the browser, then call the API with credentials: 'same-origin'
so the session cookie is sent. Same-origin only; not for cross-site agents.
Planned: Laravel Sanctum personal access tokens issued to superadmins.
Send Authorization: Bearer <token>. Token issuance UI/API is not shipped in this release;
use session auth for GUI integrations today.
| Header | Value |
|---|---|
Accept |
application/json (required) |
X-XSRF-TOKEN / CSRF |
Required for cookie-auth mutations later; not needed for GET reads |
Authorization |
Bearer … when token auth is available |
60 requests per minute per authenticated user (or IP if unauthenticated).
Path hostnames must match ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$.
Shell metacharacters are rejected (422).
Responses use a consistent envelope:
{
"data": { ... } | null,
"meta": { ... },
"error": { "message": "...", "code": "..." } | null
}
| Status | Meaning |
|---|---|
| 401 | Not authenticated |
| 403 | Authenticated but not allowed for this PBX |
| 404 | PBX not found (or not visible) |
| 406 | Missing Accept: application/json |
| 422 | Invalid hostname |
| 503 | Live collectors failed (partial DB data may still be in data) |
secret fields includedNon-superadmins do not receive secret fields on PBX or provision records.
GET /api/v1/pbx/{hostname}
Accept: application/json
Example (browser / same-origin):
fetch('/api/v1/pbx/customer1.example', {
credentials: 'same-origin',
headers: { 'Accept': 'application/json' }
}).then(r => r.json())
data shape:
{
"pbx": { "name", "hostname", "privip", "pop", "has_secret", "secret?", "contactCompany", "contactName", "contactEmail", "contactPhone", "tz" },
"seats": [ { "ext", "name", "dssgroup", "paginggroup", "directory", "reception", "dss", "sortorder" } ],
"peers": [ { "peer", "ip", "status" } ],
"numbers": [ { "did", "forward", "pbx", "state", "comments", "gateway" } ],
"provision": [ { "mac", "displayname", "sipname", "model", "..." } ],
"softphones": [ { "meid", "number", "sip_callerid", "provision_login_username", "model" } ],
"perf": { "uptime", "pod_uptime?", "pod_start_time?", "pod_status?", "alerts", "ifconfig", "routes" },
"collectors": { "perf": "ok|error", "peers": "ok|error", "k8s": "ok|error|missing|skipped", "messages": [] }
}
getPBX.php / peers on port 22022).
For pop=K8S, pod_uptime comes from stcontroller STATUS (container startedAt).
DB sections still return when collectors partially fail.
has_secret is always present; raw secret remains superadmin-only.
POST /api/v1/pbx/{hostname}/activate-trunk
Accept: application/json
Reseller+. K8S only. Generates a SIP secret, stores it on pbx.secret, and pushes it into FreePBX trunk id=1 over SSH (parity with dashboard activateTrunk.php). Border1 picks up the peer on the next SipAuto regen (~5 minutes).
{
"hostname": "customer1",
"activated": true,
"has_secret": true,
"message": "Trunk activated successfully. Allow up to 5 minutes before routes are available.",
"secret?": "…superadmin only…"
}
PUT /api/v1/pbx/{hostname}
Accept: application/json
Content-Type: application/json
Updates contact fields + timezone on pbx, and upserts/deletes seats on extensions (parity with putPBX.php). Soft-removed seats send removed: true (delete by originalExt or ext). Renames delete the old ext then upsert the new one.
// PUT body
{
"contactCompany": "...",
"contactName": "...",
"contactEmail": "...",
"contactPhone": "...",
"tz": "America/Chicago",
"seats": [
{
"ext": "101",
"originalExt": "101",
"name": "Front Desk",
"dssgroup": "",
"paginggroup": "",
"directory": true,
"reception": false,
"dss": false,
"removed": false
}
]
}
Response data: refreshed pbx contact/tz fields and seats list.
GET /api/v1/numbers/{did}
PUT /api/v1/numbers/{did}
POST /api/v1/numbers
POST /api/v1/numbers/{did}/release
DELETE /api/v1/numbers/{did}
Accept: application/json
Content-Type: application/json
GET and PUT return general number fields plus pbx_options (Target list: hosted PBX hostnames and SIP trunk usernames the actor may assign). PUT updates general fields; ingress gateway is set automatically (border1/CLUSTER for K8S PBXs and trunks, ast01/OLD otherwise). Rate decks are preserved. POST creates a DID (technician+). Release clears routing fields and sets pbx=AVAILABLE. DELETE removes the row.
// PUT body
{
"forward": "...",
"present": "...",
"sms": "...",
"pbx": "customer1",
"comments": "...",
"state": "ACTIVE"
}
// POST body (create)
{
"did": "13125551212",
"forward": "",
"present": "",
"sms": "",
"pbx": "AVAILABLE",
"comments": ""
}
GET /api/v1/dns/records
Authorization: Bearer <WIREGUARD_SYNC_TOKEN>
Machine pull for ns1.stratustalk.com. Same shared secret as WireGuard peer sync (Authorization: Bearer or X-Avion-Token). Replaces dashboard getDNS.php and keeps that response shape. Each item is a PBX hostname and its privip. Rows with an empty or non-IP address (including PENDING) are omitted. Apply the list only when status is OK — an error returns data: [] and must not be treated as "delete every name."
{
"status": "OK",
"message": "DNS Info",
"data": [
{ "hostname": "customer1", "privip": "10.200.1.20" }
]
}
GET /api/v1/sms/destinations/{did}
Authorization: Bearer <WIREGUARD_SYNC_TOKEN>
Accept: application/json
Machine pull for the sms app. Same shared secret as WireGuard peer sync. Replaces dashboard getNumber.php. Returns only the destination configured on the DID (email address or webhook URL). Unknown DIDs return 404.
{
"data": { "did": "13125551212", "sms": "alerts@example.com" },
"meta": {},
"error": null
}
POST /api/v1/sms/alerts
Authorization: Bearer <WIREGUARD_SYNC_TOKEN>
Accept: application/json
Content-Type: application/json
{
"to": "alerts@example.com",
"from_number": "+15551212",
"to_number": "13125551212",
"text": "hello",
"media": ""
}
Sends the inbound SMS alert through Avion's Settings → SMTP relay (Amazon SES). The From address is the relay's configured from address. Returns 503 when SMTP is not enabled.
← Back to login