Carriers (SIP trunks)
Generated from
DialerDigital/corecommit6e9f026f0a72— specopenapi/dialer-v1.yamlv0.36.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.
SIP trunk registry (BYOC/house) + SBC provisioning.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/carriers | List carriers (trunks) |
POST | /v1/carriers | Register a SIP trunk |
GET | /v1/carriers/{id} | Fetch one carrier |
POST | /v1/carriers/{id}/provision | Push the trunk to the SIP edge (Kamailio) |
POST | /v1/carriers/{id}/revoke | Remove the trunk from the SIP edge |
List carriers (trunks)
GET /v1/carriersResponses
200
Own trunks + inherited empresa-wide trunks.
| Field | Type | Required | Description |
|---|---|---|---|
carriers | array of Carrier | yes | |
carriers[].id | string (uuid) | no | |
carriers[].account_id | string (uuid) | no | |
carriers[].tenant_id | string (uuid) | null | no | null = empresa-wide (shared) trunk inherited by every sede. |
carriers[].scope | empresa · sede | no | Derived from tenant_id. |
carriers[].kind | house · byoc | no | |
carriers[].name | string | no | |
carriers[].sip_proxy | string | null | no | |
carriers[].source_ips | array of string | no | |
carriers[].status | active · disabled · retired | no | |
carriers[].created_at | string (date-time) | no | |
carriers[].updated_at | string (date-time) | no |
401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}Register a SIP trunk
POST /v1/carriersscope: "empresa" creates a shared trunk (tenant_id null) inherited by every sede of the account; scope: "sede" (default) creates a per-sede trunk. account_id/tenant_id are NEVER taken from the body — the router injects them from the session (a sede cannot forge another account's carrier).
scope: "empresa" additionally requires an account_admin user (see User.role) — it overrides the routing of every sibling sede, so a member or a machine key gets 403. The RLS policy enforces it, not only this route.
Since MT-SEC-49 MT.3b an unrecognized key is a 400 naming it. account_id is the one exception and is documented below: it is accepted and ignored. tenant_id is NOT — sending it is a cross-tenant forgery attempt and gets the 400.
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
kind | house · byoc | yes | |
name | string | yes | |
sip_proxy | string | no | |
source_ips | array of string | no | |
status | active · disabled · retired | no | |
scope | sede · empresa | no | Request-only field; responses derive it from tenant_id. |
account_id | string (uuid) | no | Accepted and IGNORED ON PURPOSE: the account always comes from the session, so a forged value has no effect. Declared so that THIS key does not become a 400 now that unknown keys are. It does NOT make the whole rendered trunk round-trip: id, created_at and updated_at are a 400, and tenant_id is a 400 DELIBERATELY — sending it is a cross-tenant forgery attempt and gets named, not dropped in silence. |
{
"kind": "byoc",
"name": "postman-trunk-1751600000",
"sip_proxy": "sip:pstn.example.test:5060",
"source_ips": [
"203.0.113.9"
]
}Responses
201
Registered trunk.
| Field | Type | Required | Description |
|---|---|---|---|
carrier | object (Carrier) | yes | |
carrier.id | string (uuid) | no | |
carrier.account_id | string (uuid) | no | |
carrier.tenant_id | string (uuid) | null | no | null = empresa-wide (shared) trunk inherited by every sede. |
carrier.scope | empresa · sede | no | Derived from tenant_id. |
carrier.kind | house · byoc | no | |
carrier.name | string | no | |
carrier.sip_proxy | string | null | no | |
carrier.source_ips | array of string | no | |
carrier.status | active · disabled · retired | no | |
carrier.created_at | string (date-time) | no | |
carrier.updated_at | string (date-time) | no |
400 — BadRequest
Malformed request (shape/type errors, invalid filters, bad timestamps).
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}403 — Forbidden
The tenant is suspended.
{
"error": {
"code": "forbidden",
"message": "tenant is suspended"
}
}Fetch one carrier
GET /v1/carriers/{id}Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The carrier.
| Field | Type | Required | Description |
|---|---|---|---|
carrier | object (Carrier) | yes | |
carrier.id | string (uuid) | no | |
carrier.account_id | string (uuid) | no | |
carrier.tenant_id | string (uuid) | null | no | null = empresa-wide (shared) trunk inherited by every sede. |
carrier.scope | empresa · sede | no | Derived from tenant_id. |
carrier.kind | house · byoc | no | |
carrier.name | string | no | |
carrier.sip_proxy | string | null | no | |
carrier.source_ips | array of string | no | |
carrier.status | active · disabled · retired | no | |
carrier.created_at | string (date-time) | no | |
carrier.updated_at | string (date-time) | no |
401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}Push the trunk to the SIP edge (Kamailio)
POST /v1/carriers/{id}/provisionOnly a BYOC carrier can be provisioned (422 otherwise). With no KAMAILIO_RPC_URL configured (dev without the telecom harness) the answer is 200 {"status": "sbc_disabled"} — the row's intent is recorded, it just is not pushed to a live edge.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
Provisioned (or SBC disabled in this environment).
| Field | Type | Required | Description |
|---|---|---|---|
status | provisioned · sbc_disabled | yes | sbc_disabled = no KAMAILIO_RPC_URL in this environment; the row's intent is recorded, not pushed. |
provisioned
{
"status": "provisioned"
}sbc_disabled
{
"status": "sbc_disabled"
}401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}422 — Unprocessable
Shape is fine, semantics are not (broken domain rule).
{
"error": {
"code": "unprocessable",
"message": "scheduled_at must be at least 10 minutes out"
}
}502 — SbcError
The SIP edge rejected the provisioning request.
{
"error": {
"code": "sbc_error",
"message": "the SIP edge rejected the provisioning request"
}
}Remove the trunk from the SIP edge
POST /v1/carriers/{id}/revokeParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
Revoked (or SBC disabled in this environment).
| Field | Type | Required | Description |
|---|---|---|---|
status | provisioned · sbc_disabled | yes | sbc_disabled = no KAMAILIO_RPC_URL in this environment; the row's intent is recorded, not pushed. |
401 — Unauthorized
Missing, unknown or revoked API key (or, on /v1/admin/*, a bad/unset admin token; on webhooks, a bad/missing signature).
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Unknown id, malformed (non-UUID) id OR another tenant's id — RLS returns zero rows, so all three are indistinguishable by design (no existence leak, never a 403 for foreign ids).
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}422 — Unprocessable
Shape is fine, semantics are not (broken domain rule).
{
"error": {
"code": "unprocessable",
"message": "scheduled_at must be at least 10 minutes out"
}
}502 — SbcError
The SIP edge rejected the provisioning request.
{
"error": {
"code": "sbc_error",
"message": "the SIP edge rejected the provisioning request"
}
}