SMS providers
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.
Per-tenant/region SMS routing registry.
Endpoints
| Method | Path | Summary |
|---|---|---|
GET | /v1/sms/providers | SMS provider registry |
POST | /v1/sms/providers | Register an SMS provider |
GET | /v1/sms/providers/{id} | Fetch one provider |
PATCH | /v1/sms/providers/{id} | Update a provider (scope immutable) |
POST | /v1/sms/providers/{id}/retire | Retire a provider (rows never delete) |
SMS provider registry
GET /v1/sms/providersResponses
200
Own rows + inherited empresa-wide rows.
| Field | Type | Required | Description |
|---|---|---|---|
sms_providers | array of SmsProvider | yes | |
sms_providers[].id | string (uuid) | no | |
sms_providers[].account_id | string (uuid) | no | |
sms_providers[].tenant_id | string (uuid) | null | no | null = empresa-wide (shared) provider inherited by every sede. |
sms_providers[].scope | empresa · sede | no | Derived from tenant_id. |
sms_providers[].adapter | http · telnyx · mock | no | |
sms_providers[].region | us · mx · eu | no | |
sms_providers[].name | string | no | |
sms_providers[].base_url | string | null | no | |
sms_providers[].has_secret | boolean | no | The webhook secret NEVER rides the wire — this is the only signal a credential is stored. |
sms_providers[].status | active · disabled · retired | no | |
sms_providers[].created_at | string (date-time) | no | |
sms_providers[].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 an SMS provider
POST /v1/sms/providersCarriers conventions: scope: "empresa" creates an account-wide row (tenant_id null) and requires an account_admin user (see User.role) — a member or a machine key gets 403; account_id/tenant_id are injected from the session, never the body; the scope of a row is immutable after creation. webhook_secret is WRITE-ONLY — responses carry has_secret, never the secret. For telnyx, webhook_secret holds the account's Ed25519 PUBLIC key (base64) and sends authenticate with the deployment-wide TELNYX_API_KEY bearer. Retire-only — no DELETE route exists.
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
adapter | http · telnyx · mock | yes | |
region | us · mx · eu | yes | |
name | string | yes | |
base_url | string | no | Internal-contract (http) adapter endpoint. MUST be an https:// URL on port 443 whose host resolves only to PUBLIC addresses — loopback, RFC1918, CGNAT (100.64/10), link-local (169.254/16, cloud metadata) and their IPv6 equivalents are refused 422 (SSRF guard), and the same check re-runs at send time against a fresh resolution. A port other than 443 is refused 422 even when the host is public: a public address is not a public service, and reaching an arbitrary port of it is reachability we do not grant. Reaching a destination that legitimately serves elsewhere needs an operator allowlist entry, not a tenant field. Blank means "use the deployment-wide endpoint". |
webhook_secret | string | no | Write-only. HMAC secret (http/mock) or Ed25519 public key, base64 (telnyx). |
status | active · disabled · retired | no | |
scope | sede · empresa | no | Request-only field; responses derive it from tenant_id. |
{
"adapter": "http",
"region": "us",
"name": "example-sms-provider",
"base_url": "",
"webhook_secret": "example-hmac-secret-not-a-real-one"
}Responses
201
Registered provider (has_secret, never the secret).
| Field | Type | Required | Description |
|---|---|---|---|
sms_provider | object (SmsProvider) | yes | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = empresa-wide (shared) provider inherited by every sede. |
sms_provider.scope | empresa · sede | no | Derived from tenant_id. |
sms_provider.adapter | http · telnyx · mock | no | |
sms_provider.region | us · mx · eu | no | |
sms_provider.name | string | no | |
sms_provider.base_url | string | null | no | |
sms_provider.has_secret | boolean | no | The webhook secret NEVER rides the wire — this is the only signal a credential is stored. |
sms_provider.status | active · disabled · retired | no | |
sms_provider.created_at | string (date-time) | no | |
sms_provider.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 provider
GET /v1/sms/providers/{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 provider.
| Field | Type | Required | Description |
|---|---|---|---|
sms_provider | object (SmsProvider) | yes | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = empresa-wide (shared) provider inherited by every sede. |
sms_provider.scope | empresa · sede | no | Derived from tenant_id. |
sms_provider.adapter | http · telnyx · mock | no | |
sms_provider.region | us · mx · eu | no | |
sms_provider.name | string | no | |
sms_provider.base_url | string | null | no | |
sms_provider.has_secret | boolean | no | The webhook secret NEVER rides the wire — this is the only signal a credential is stored. |
sms_provider.status | active · disabled · retired | no | |
sms_provider.created_at | string (date-time) | no | |
sms_provider.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"
}
}Update a provider (scope immutable)
PATCH /v1/sms/providers/{id}Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Request body (JSON, required)
| Field | Type | Required | Description |
|---|---|---|---|
adapter | http · telnyx · mock | no | |
region | us · mx · eu | no | |
name | string | no | |
base_url | string | no | |
webhook_secret | string | no | Write-only. |
status | active · disabled · retired | no |
{
"name": "postman-sms-renamed",
"status": "disabled"
}Responses
200
Updated provider.
| Field | Type | Required | Description |
|---|---|---|---|
sms_provider | object (SmsProvider) | yes | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = empresa-wide (shared) provider inherited by every sede. |
sms_provider.scope | empresa · sede | no | Derived from tenant_id. |
sms_provider.adapter | http · telnyx · mock | no | |
sms_provider.region | us · mx · eu | no | |
sms_provider.name | string | no | |
sms_provider.base_url | string | null | no | |
sms_provider.has_secret | boolean | no | The webhook secret NEVER rides the wire — this is the only signal a credential is stored. |
sms_provider.status | active · disabled · retired | no | |
sms_provider.created_at | string (date-time) | no | |
sms_provider.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"
}
}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"
}
}Retire a provider (rows never delete)
POST /v1/sms/providers/{id}/retireParameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string (uuid) | yes | Resource UUID. Malformed or cross-tenant ids read as 404. |
Responses
200
The retired provider.
| Field | Type | Required | Description |
|---|---|---|---|
sms_provider | object (SmsProvider) | yes | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = empresa-wide (shared) provider inherited by every sede. |
sms_provider.scope | empresa · sede | no | Derived from tenant_id. |
sms_provider.adapter | http · telnyx · mock | no | |
sms_provider.region | us · mx · eu | no | |
sms_provider.name | string | no | |
sms_provider.base_url | string | null | no | |
sms_provider.has_secret | boolean | no | The webhook secret NEVER rides the wire — this is the only signal a credential is stored. |
sms_provider.status | active · disabled · retired | no | |
sms_provider.created_at | string (date-time) | no | |
sms_provider.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"
}
}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"
}
}