Appearance
Proveedores de SMS
Generado desde
DialerDigital/corecommit0fc18008b3c8— especificaciónopenapi/dialer-v1.yamlv0.134.0. No se edita a mano; consulta Cómo se construye esta referencia. Descargar la especificación OpenAPI.
Traducción en curso
Esta referencia se genera desde la especificación OpenAPI. Las cadenas que todavía no tienen traducción aparecen en inglés.
Qué es hoy el SMS
El envío de SMS a través de tu propio proveedor está disponible hoy a nivel de API; el producto completo de mensajería de cobranza está en la hoja de ruta.
Registro de enrutamiento de SMS por tenant/región.
Endpoints
| Método | Ruta | Resumen |
|---|---|---|
GET | /v1/sms/providers | Registro de proveedores de SMS |
POST | /v1/sms/providers | Registrar un proveedor de SMS |
GET | /v1/sms/providers/{id} | Obtener un proveedor |
PATCH | /v1/sms/providers/{id} | Actualizar un proveedor (alcance inmutable) |
POST | /v1/sms/providers/{id}/retire | Retirar un proveedor (las filas nunca se borran) |
Registro de proveedores de SMS
http
GET /v1/sms/providersRespuestas
200
Filas propias + filas heredadas de toda la empresa.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
sms_providers | arreglo de SmsProvider | sí | |
sms_providers[].id | string (uuid) | no | |
sms_providers[].account_id | string (uuid) | no | |
sms_providers[].tenant_id | string (uuid) | null | no | null = proveedor de toda la empresa (compartido), heredado por cada sede. |
sms_providers[].scope | empresa · sede | no | Derivado de 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[].default_from_e164 | string | null | no | Línea remitente usada cuando POST /v1/sms/messages no trae from; null = ninguna (un envío así da 422 from_required). |
sms_providers[].has_secret | boolean | no | El secreto del webhook NUNCA viaja por el cable: esta es la única señal de que hay una credencial almacenada. |
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
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}Registrar un proveedor de SMS
http
POST /v1/sms/providersConvenciones de los carriers: scope: "empresa" crea una fila de toda la cuenta (tenant_id null) y requiere un usuario account_admin (véase User.role): un member o una clave de máquina recibe 403; account_id/tenant_id se inyectan desde la sesión, nunca desde el cuerpo; el alcance de una fila es inmutable tras la creación. webhook_secret es SOLO DE ESCRITURA: las respuestas llevan has_secret, nunca el secreto. Para telnyx, webhook_secret contiene la clave PÚBLICA Ed25519 de la cuenta (base64) y los envíos se autentican con el bearer TELNYX_API_KEY de todo el despliegue. El adaptador mock (arnés de pruebas/e2e) se rechaza con 400 salvo que el despliegue lo permita. Solo se retira: no existe ruta DELETE.
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
adapter | http · telnyx · mock | sí | |
region | us · mx · eu | sí | |
name | string | sí | |
default_from_e164 | string | null | no | Línea remitente usada por POST /v1/sms/messages cuando la petición no trae from. E.164; cualquier otra cosa da 422. null = ninguna declarada. |
base_url | string | no | Endpoint del adaptador de contrato interno (http). DEBE ser una URL https:// en el puerto 443 cuyo host se resuelva solo a direcciones PÚBLICAS: loopback, RFC1918, CGNAT (100.64/10), enlace local (169.254/16, metadatos de la nube) y sus equivalentes IPv6 se rechazan con 422 (protección SSRF), y la misma comprobación se repite en el momento del envío con una resolución nueva. Un puerto distinto del 443 se rechaza con 422 aunque el host sea público: una dirección pública no es un servicio público, y llegar a un puerto arbitrario de ella es una alcanzabilidad que no concedemos. Llegar a un destino que legítimamente sirve en otro puerto requiere una entrada en la lista de permitidos del operador, no un campo del tenant. En blanco significa «usar el endpoint de todo el despliegue». |
webhook_secret | string | no | Solo de escritura. Secreto HMAC (http/mock) o clave pública Ed25519, en base64 (telnyx). |
status | active · disabled · retired | no | |
scope | sede · empresa | no | Campo solo de petición; las respuestas lo derivan de tenant_id. |
json
{
"adapter": "http",
"region": "us",
"name": "example-sms-provider",
"base_url": "",
"webhook_secret": "example-hmac-secret-not-a-real-one"
}Respuestas
201
Proveedor registrado (has_secret, nunca el secreto).
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
sms_provider | object (SmsProvider) | sí | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = proveedor de toda la empresa (compartido), heredado por cada sede. |
sms_provider.scope | empresa · sede | no | Derivado de 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.default_from_e164 | string | null | no | Línea remitente usada cuando POST /v1/sms/messages no trae from; null = ninguna (un envío así da 422 from_required). |
sms_provider.has_secret | boolean | no | El secreto del webhook NUNCA viaja por el cable: esta es la única señal de que hay una credencial almacenada. |
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
Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).
json
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}403 — Forbidden
El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.
json
{
"error": {
"code": "forbidden",
"message": "tenant is suspended"
}
}422
El default_from_e164 de un proveedor con alcance de sede no es E.164 (code: sms_from_invalid) o no es un número ACTIVO del tenant (code: sms_from_not_owned; palanca por tenant sms_from_ownership_enforced, por defecto true, core#2329). Una fila de toda la empresa no se comprueba al escribir: cada envío la comprueba contra su propia sede.
429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}Obtener un proveedor
http
GET /v1/sms/providers/{id}Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | UUID del recurso. Los ids mal formados o de otro tenant se leen como 404. |
Respuestas
200
El proveedor.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
sms_provider | object (SmsProvider) | sí | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = proveedor de toda la empresa (compartido), heredado por cada sede. |
sms_provider.scope | empresa · sede | no | Derivado de 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.default_from_e164 | string | null | no | Línea remitente usada cuando POST /v1/sms/messages no trae from; null = ninguna (un envío así da 422 from_required). |
sms_provider.has_secret | boolean | no | El secreto del webhook NUNCA viaja por el cable: esta es la única señal de que hay una credencial almacenada. |
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
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}Actualizar un proveedor (alcance inmutable)
http
PATCH /v1/sms/providers/{id}Editar una fila de toda la empresa (scope: "empresa", heredada por cada sede de la cuenta) requiere una sesión account_admin, igual que crearla: un member o una clave de máquina recibe 403. Cambiar al adaptador mock (arnés de pruebas/e2e) se rechaza con 400 salvo que el despliegue lo permita.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | UUID del recurso. Los ids mal formados o de otro tenant se leen como 404. |
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
adapter | http · telnyx · mock | no | |
region | us · mx · eu | no | |
name | string | no | |
base_url | string | no | |
default_from_e164 | string | null | no | Línea remitente para los envíos sin from; null la borra. |
webhook_secret | string | no | Solo de escritura. |
status | active · disabled · retired | no |
json
{
"name": "postman-sms-renamed",
"status": "disabled"
}Respuestas
200
Proveedor actualizado.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
sms_provider | object (SmsProvider) | sí | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = proveedor de toda la empresa (compartido), heredado por cada sede. |
sms_provider.scope | empresa · sede | no | Derivado de 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.default_from_e164 | string | null | no | Línea remitente usada cuando POST /v1/sms/messages no trae from; null = ninguna (un envío así da 422 from_required). |
sms_provider.has_secret | boolean | no | El secreto del webhook NUNCA viaja por el cable: esta es la única señal de que hay una credencial almacenada. |
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
Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).
json
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}403 — Forbidden
El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.
json
{
"error": {
"code": "forbidden",
"message": "tenant is suspended"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}422
El default_from_e164 de un proveedor con alcance de sede no es E.164 (code: sms_from_invalid) o no es un número ACTIVO del tenant (code: sms_from_not_owned; palanca por tenant sms_from_ownership_enforced, por defecto true, core#2329).
429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}Retirar un proveedor (las filas nunca se borran)
http
POST /v1/sms/providers/{id}/retireRetirar una fila de toda la empresa (scope: "empresa") requiere una sesión account_admin: un member o una clave de máquina recibe 403.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | UUID del recurso. Los ids mal formados o de otro tenant se leen como 404. |
Respuestas
200
El proveedor retirado.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
sms_provider | object (SmsProvider) | sí | |
sms_provider.id | string (uuid) | no | |
sms_provider.account_id | string (uuid) | no | |
sms_provider.tenant_id | string (uuid) | null | no | null = proveedor de toda la empresa (compartido), heredado por cada sede. |
sms_provider.scope | empresa · sede | no | Derivado de 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.default_from_e164 | string | null | no | Línea remitente usada cuando POST /v1/sms/messages no trae from; null = ninguna (un envío así da 422 from_required). |
sms_provider.has_secret | boolean | no | El secreto del webhook NUNCA viaja por el cable: esta es la única señal de que hay una credencial almacenada. |
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
Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).
json
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}403 — Forbidden
El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.
json
{
"error": {
"code": "forbidden",
"message": "tenant is suspended"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}