Skip to content

SMS providers

Generated from DialerDigital/core commit 6e9f026f0a72 — spec openapi/dialer-v1.yaml v0.36.0. Do not edit by hand; see How this reference is built. Download the OpenAPI spec.

Per-tenant/region SMS routing registry.

Endpoints

MethodPathSummary
GET/v1/sms/providersSMS provider registry
POST/v1/sms/providersRegister 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}/retireRetire a provider (rows never delete)

SMS provider registry

http
GET /v1/sms/providers

Responses

200

Own rows + inherited empresa-wide rows.

FieldTypeRequiredDescription
sms_providersarray of SmsProvideryes
sms_providers[].idstring (uuid)no
sms_providers[].account_idstring (uuid)no
sms_providers[].tenant_idstring (uuid) | nullnonull = empresa-wide (shared) provider inherited by every sede.
sms_providers[].scopeempresa · sedenoDerived from tenant_id.
sms_providers[].adapterhttp · telnyx · mockno
sms_providers[].regionus · mx · euno
sms_providers[].namestringno
sms_providers[].base_urlstring | nullno
sms_providers[].has_secretbooleannoThe webhook secret NEVER rides the wire — this is the only signal a credential is stored.
sms_providers[].statusactive · disabled · retiredno
sms_providers[].created_atstring (date-time)no
sms_providers[].updated_atstring (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).

json
{
  "error": {
    "code": "unauthorized",
    "message": "invalid or revoked API key"
  }
}

Register an SMS provider

http
POST /v1/sms/providers

Carriers 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)

FieldTypeRequiredDescription
adapterhttp · telnyx · mockyes
regionus · mx · euyes
namestringyes
base_urlstringnoInternal-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_secretstringnoWrite-only. HMAC secret (http/mock) or Ed25519 public key, base64 (telnyx).
statusactive · disabled · retiredno
scopesede · empresanoRequest-only field; responses derive it from tenant_id.
json
{
  "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).

FieldTypeRequiredDescription
sms_providerobject (SmsProvider)yes
sms_provider.idstring (uuid)no
sms_provider.account_idstring (uuid)no
sms_provider.tenant_idstring (uuid) | nullnonull = empresa-wide (shared) provider inherited by every sede.
sms_provider.scopeempresa · sedenoDerived from tenant_id.
sms_provider.adapterhttp · telnyx · mockno
sms_provider.regionus · mx · euno
sms_provider.namestringno
sms_provider.base_urlstring | nullno
sms_provider.has_secretbooleannoThe webhook secret NEVER rides the wire — this is the only signal a credential is stored.
sms_provider.statusactive · disabled · retiredno
sms_provider.created_atstring (date-time)no
sms_provider.updated_atstring (date-time)no

400 — BadRequest

Malformed request (shape/type errors, invalid filters, bad timestamps).

json
{
  "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).

json
{
  "error": {
    "code": "unauthorized",
    "message": "invalid or revoked API key"
  }
}

403 — Forbidden

The tenant is suspended.

json
{
  "error": {
    "code": "forbidden",
    "message": "tenant is suspended"
  }
}

Fetch one provider

http
GET /v1/sms/providers/{id}

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Responses

200

The provider.

FieldTypeRequiredDescription
sms_providerobject (SmsProvider)yes
sms_provider.idstring (uuid)no
sms_provider.account_idstring (uuid)no
sms_provider.tenant_idstring (uuid) | nullnonull = empresa-wide (shared) provider inherited by every sede.
sms_provider.scopeempresa · sedenoDerived from tenant_id.
sms_provider.adapterhttp · telnyx · mockno
sms_provider.regionus · mx · euno
sms_provider.namestringno
sms_provider.base_urlstring | nullno
sms_provider.has_secretbooleannoThe webhook secret NEVER rides the wire — this is the only signal a credential is stored.
sms_provider.statusactive · disabled · retiredno
sms_provider.created_atstring (date-time)no
sms_provider.updated_atstring (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).

json
{
  "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).

json
{
  "error": {
    "code": "not_found",
    "message": "resource not found for this tenant"
  }
}

Update a provider (scope immutable)

http
PATCH /v1/sms/providers/{id}

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Request body (JSON, required)

FieldTypeRequiredDescription
adapterhttp · telnyx · mockno
regionus · mx · euno
namestringno
base_urlstringno
webhook_secretstringnoWrite-only.
statusactive · disabled · retiredno
json
{
  "name": "postman-sms-renamed",
  "status": "disabled"
}

Responses

200

Updated provider.

FieldTypeRequiredDescription
sms_providerobject (SmsProvider)yes
sms_provider.idstring (uuid)no
sms_provider.account_idstring (uuid)no
sms_provider.tenant_idstring (uuid) | nullnonull = empresa-wide (shared) provider inherited by every sede.
sms_provider.scopeempresa · sedenoDerived from tenant_id.
sms_provider.adapterhttp · telnyx · mockno
sms_provider.regionus · mx · euno
sms_provider.namestringno
sms_provider.base_urlstring | nullno
sms_provider.has_secretbooleannoThe webhook secret NEVER rides the wire — this is the only signal a credential is stored.
sms_provider.statusactive · disabled · retiredno
sms_provider.created_atstring (date-time)no
sms_provider.updated_atstring (date-time)no

400 — BadRequest

Malformed request (shape/type errors, invalid filters, bad timestamps).

json
{
  "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).

json
{
  "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).

json
{
  "error": {
    "code": "not_found",
    "message": "resource not found for this tenant"
  }
}

Retire a provider (rows never delete)

http
POST /v1/sms/providers/{id}/retire

Parameters

NameInTypeRequiredDescription
idpathstring (uuid)yesResource UUID. Malformed or cross-tenant ids read as 404.

Responses

200

The retired provider.

FieldTypeRequiredDescription
sms_providerobject (SmsProvider)yes
sms_provider.idstring (uuid)no
sms_provider.account_idstring (uuid)no
sms_provider.tenant_idstring (uuid) | nullnonull = empresa-wide (shared) provider inherited by every sede.
sms_provider.scopeempresa · sedenoDerived from tenant_id.
sms_provider.adapterhttp · telnyx · mockno
sms_provider.regionus · mx · euno
sms_provider.namestringno
sms_provider.base_urlstring | nullno
sms_provider.has_secretbooleannoThe webhook secret NEVER rides the wire — this is the only signal a credential is stored.
sms_provider.statusactive · disabled · retiredno
sms_provider.created_atstring (date-time)no
sms_provider.updated_atstring (date-time)no

400 — BadRequest

Malformed request (shape/type errors, invalid filters, bad timestamps).

json
{
  "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).

json
{
  "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).

json
{
  "error": {
    "code": "not_found",
    "message": "resource not found for this tenant"
  }
}

Nothing in these docs is legal advice — always confirm compliance posture with your own counsel.