Apariencia
DID (identificadores de llamada)
Generado desde
DialerDigital/corecommitbbb8e373d900— especificaciónopenapi/dialer-v1.yamlv0.151.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.
Registro de DID, salud calculada a partir del CDR, lista de verificación de lanzamiento y tickets del carrier.
Endpoints
| Método | Ruta | Resumen |
|---|---|---|
GET | /v1/port-requests | Solicitudes de portabilidad entrante del tenant |
POST | /v1/port-requests | Portar números a la plataforma (port-in) |
GET | /v1/port-requests/{id} | Consultar una solicitud de portabilidad entrante |
GET | /v1/dids | Registro de DID |
POST | /v1/dids | Registrar un número propio del tenant |
GET | /v1/dids/{id} | Obtener un DID |
PATCH | /v1/dids/{id} | Actualizar metadatos/estado (e164 inmutable) |
DELETE | /v1/dids/{id} | Retirar un DID (las filas nunca se borran) |
GET | /v1/dids/{id}/health | Salud del DID calculada a partir del CDR |
GET | /v1/dids/{id}/launch-checklist | Lista de verificación de lanzamiento de un número |
POST | /v1/dids/{id}/launch-checklist/{step}/confirmations | Confirmar (o desconfirmar) un paso manual del lanzamiento |
GET | /v1/dids/{id}/carrier-tickets | Tickets del carrier de un número |
POST | /v1/dids/{id}/carrier-tickets | Abrir un ticket del carrier para un número |
POST | /v1/dids/{id}/carrier-tickets/{ticket_id}/events | Añadir una nota y/o cambiar el estado de un ticket del carrier |
Solicitudes de portabilidad entrante del tenant
http
GET /v1/port-requestsLa más reciente primero, 50 como máximo. Los documentos nunca se devuelven, solo su hash y su tipo.
Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
status | query | pending · scheduled · rejected · completed | no |
Respuestas
200
Las solicitudes.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
port_requests | arreglo de PortRequest | sí | |
port_requests[].id | string (uuid) | sí | |
port_requests[].numbers | arreglo de string | sí | |
port_requests[].account_holder | string | sí | |
port_requests[].status | pending · scheduled · rejected · completed | sí | |
port_requests[].reject_reason | string,null | no | |
port_requests[].foc_date | string,null (date) | no | Fecha firme fijada por el operador. |
port_requests[].carrier | string | sí | |
port_requests[].loa | object (PortDocumentRef) | sí | |
port_requests[].loa.sha256 | string | sí | |
port_requests[].loa.content_type | string | sí | |
port_requests[].invoice | object (PortDocumentRef) | sí | |
port_requests[].invoice.sha256 | string | sí | |
port_requests[].invoice.content_type | string | sí | |
port_requests[].completed_at | string,null (date-time) | no | |
port_requests[].created_at | string (date-time) | sí | |
port_requests[].updated_at | string (date-time) | sí |
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"
}
}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 (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"
}
}Portar números a la plataforma (port-in)
http
POST /v1/port-requestsRegistra una solicitud de portabilidad entrante y la envía al operador de la casa. Los documentos viajan en base64 en el cuerpo JSON (cada uno de hasta 2 MiB; application/pdf, image/png o image/jpeg, comprobados contra sus magic bytes) y se almacenan CIFRADOS, nunca se devuelven. Falla en cerrado antes de llamar al operador: plan inactivo (402 plan_inactive), entrada inválida (400), un número ya presente en el registro o en una solicitud viva (409 number_in_use). Una clave test se rechaza (403 test_environment). Que el operador rechace el envío NO es un error: la solicitud se guarda con status: rejected y su reject_reason. 503 carrier_unavailable: el operador no respondió; la solicitud se conserva como rejected (carrier_unavailable_at_submission) y sus números quedan libres para reintentar. 409 port_in_busy: otra solicitud del tenant se está registrando (reintenta en breve; no se guardó ni se envió nada). 429 port_request_limit: el tenant ya tiene port_request_max_live (por defecto 20) solicitudes vivas; no se guardó ni se envió nada. 503 port_in_unavailable: este despliegue no tiene operador de portabilidad entrante configurado; no se guardó ni se envió nada.
El estado sigue al operador (pending → scheduled con foc_date → completed, o rejected con reject_reason). En completed los números pasan a ser DID origin: house del tenant (devengan la renta mensual) y se envía el webhook firmado port_request.ported.
Reglas de rol: una clave dd_ o un login account_admin (en otro caso 403 role_forbidden).
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
numbers | arreglo de string | sí | |
account_holder | string | sí | Nombre del titular de la cuenta en el operador actual. |
loa | object (PortDocument) | sí | |
loa.content_type | application/pdf · image/png · image/jpeg | sí | |
loa.content_base64 | string | sí | Base64 del archivo, 2 MiB como máximo una vez decodificado. |
invoice | object (PortDocument) | sí | |
invoice.content_type | application/pdf · image/png · image/jpeg | sí | |
invoice.content_base64 | string | sí | Base64 del archivo, 2 MiB como máximo una vez decodificado. |
Respuestas
201
La solicitud almacenada.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
port_request | object (PortRequest) | sí | Una solicitud de portabilidad entrante; también el data del webhook port_request.ported. |
port_request.id | string (uuid) | sí | |
port_request.numbers | arreglo de string | sí | |
port_request.account_holder | string | sí | |
port_request.status | pending · scheduled · rejected · completed | sí | |
port_request.reject_reason | string,null | no | |
port_request.foc_date | string,null (date) | no | Fecha firme fijada por el operador. |
port_request.carrier | string | sí | |
port_request.loa | object (PortDocumentRef) | sí | |
port_request.loa.sha256 | string | sí | |
port_request.loa.content_type | string | sí | |
port_request.invoice | object (PortDocumentRef) | sí | |
port_request.invoice.sha256 | string | sí | |
port_request.invoice.content_type | string | sí | |
port_request.completed_at | string,null (date-time) | no | |
port_request.created_at | string (date-time) | sí | |
port_request.updated_at | string (date-time) | sí |
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"
}
}402 — PlanInactive
El plan del tenant se LEYÓ y no está efectivamente active, por lo que la acción queda bloqueada (code plan_inactive). En la superficie de SUPERVISIÓN este estado significa que el plan realmente se leyó: un plan que NO se pudo leer pasa en lugar de rechazar. Es deliberadamente lo opuesto a la postura fail-CLOSED de la compuerta de entrantes — una pierna de supervisión va al registrar propio del tenant y no compra minutos de carrier, así que el costo de un falso rechazo (un oficial de cumplimiento a ciegas durante una llamada en vivo) supera el costo de una falsa admisión.
Nota sobre qué verbos pueden devolverlo: solo los tres modos EAVESDROP. takeover está exento y nunca devuelve plan_inactive, bajo la regla "bloquea lo que AGREGA exposición, nunca lo que la CORRIGE" — listen/whisper/barge abren cada uno una pierna nueva, mientras que takeover le quita la llamada al agente y mata la pierna del agente. Un plan que caduca a mitad de turno no debe dejar varada una llamada en vivo que el supervisor intenta terminar. La exención es estrecha, no una laguna de facturación: un tenant apagado sigue sin poder abrir supervisión NUEVA, solo conserva la palanca para terminar correctamente lo que ya está en marcha.
json
{
"error": {
"code": "plan_inactive",
"message": "tenant plan is not active; traffic is gated"
}
}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 (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. Ningún pago lo cambia.
json
{
"error": {
"code": "forbidden",
"message": "tenant is suspended"
}
}409 — Conflict
Transición de estado no válida, conflicto de unicidad, o un asiento que está ocupado/reservado.
json
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}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 (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"
}
}503
El operador no respondió (carrier_unavailable) o este despliegue no tiene configurado un operador de portabilidad entrante (port_in_unavailable); no se almacenó ni se envió nada.
Consultar una solicitud de portabilidad entrante
http
GET /v1/port-requests/{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
La solicitud con el estado del operador.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
port_request | object (PortRequest) | sí | Una solicitud de portabilidad entrante; también el data del webhook port_request.ported. |
port_request.id | string (uuid) | sí | |
port_request.numbers | arreglo de string | sí | |
port_request.account_holder | string | sí | |
port_request.status | pending · scheduled · rejected · completed | sí | |
port_request.reject_reason | string,null | no | |
port_request.foc_date | string,null (date) | no | Fecha firme fijada por el operador. |
port_request.carrier | string | sí | |
port_request.loa | object (PortDocumentRef) | sí | |
port_request.loa.sha256 | string | sí | |
port_request.loa.content_type | string | sí | |
port_request.invoice | object (PortDocumentRef) | sí | |
port_request.invoice.sha256 | string | sí | |
port_request.invoice.content_type | string | sí | |
port_request.completed_at | string,null (date-time) | no | |
port_request.created_at | string (date-time) | sí | |
port_request.updated_at | string (date-time) | sí |
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 (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"
}
}Registro de DID
http
GET /v1/didsParámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
status | query | active · quarantine · retired | no |
Respuestas
200
Filas del registro ordenadas por e164.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dids | arreglo de DID | sí | |
dids[].id | string (uuid) | no | |
dids[].tenant_id | string (uuid) | no | |
dids[].e164 | string | no | Inmutable tras la creación. |
dids[].npa | string | null | no | |
dids[].us_state | string | null | no | |
dids[].attestation | A · B · C · unknown | no | Nivel STIR/SHAKEN que firma el carrier. Solo lectura para el tenant: solo lo fija el admin de la plataforma. |
dids[].status | active · quarantine · retired | no | |
dids[].verified_at | string (date-time) | null | no | Prueba de titularidad. null = autodeclarado, nunca probado; los DID house nacen verificados. |
dids[].verification_method | house · otp · admin | null | no | Cómo se probó la titularidad; null mientras verified_at sea null. |
dids[].origin | house · customer | no | Las filas house son inventario de la plataforma emitido por el admin; la superficie del tenant solo crea customer. |
dids[].labels | arreglo de string | no | |
dids[].notes | string | null | no | |
dids[].created_at | string (date-time) | no | |
dids[].updated_at | string (date-time) | no | |
truncated | boolean | sí | true cuando hay más filas que los 2 000 números que devuelve el listado: la respuesta es un prefijo en el orden documentado, no el conjunto completo. |
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"
}
}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 (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 número propio del tenant
http
POST /v1/didse164 es único por tenant → 409 conflict si se duplica; npa se deriva de los números +1 cuando se omite. La superficie del tenant solo puede crear filas con origin: customer; el inventario house lo emite el admin (POST /v1/admin/tenants/{id}/dids).
Reglas de rol: una clave dd_ o un inicio de sesión account_admin; un inicio de sesión member recibe 403 role_forbidden (opción por tenant telephony_config_admin_only, activada por defecto). El GET de este recurso no se ve afectado.
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
e164 | string | sí | E.164 (inmutable tras la creación). |
npa | string | no | |
us_state | string | no | |
attestation | A · B · C · unknown | no | Se acepta e IGNORA: la atestación STIR/SHAKEN es una afirmación que solo registra el admin de la plataforma (POST /v1/admin/tenants/{id}/dids/{did_id}/verify); nunca cambia por esta ruta, que responde como si la clave estuviera ausente. |
status | active · quarantine · retired | no | |
labels | arreglo de string | no | |
notes | string | no | |
origin | house · customer | no | Se acepta e IGNORA POR SEGURIDAD: un tenant nunca puede emitir origin: house, así que cualquier valor aquí se sobrescribe con customer. El enum refleja el esquema de la respuesta porque un GET de un DID house devuelve house: reenviar ese valor no falla, no tiene efecto. Se declara para que ESTA clave no pase a ser un 400 ahora que las claves desconocidas lo son. NO hace que todo el objeto renderizado sea reenviable tal cual: id, tenant_id, created_at y updated_at no se aceptan y SÍ dan el 400. |
json
{
"e164": "+13125550142",
"us_state": "IL"
}Respuestas
201
DID registrado.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did | object (DID) | sí | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Inmutable tras la creación. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | Nivel STIR/SHAKEN que firma el carrier. Solo lectura para el tenant: solo lo fija el admin de la plataforma. |
did.status | active · quarantine · retired | no | |
did.verified_at | string (date-time) | null | no | Prueba de titularidad. null = autodeclarado, nunca probado; los DID house nacen verificados. |
did.verification_method | house · otp · admin | null | no | Cómo se probó la titularidad; null mientras verified_at sea null. |
did.origin | house · customer | no | Las filas house son inventario de la plataforma emitido por el admin; la superficie del tenant solo crea customer. |
did.labels | arreglo de string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.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"
}
}409 — Conflict
Transición de estado no válida, conflicto de unicidad, o un asiento que está ocupado/reservado.
json
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}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 (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 DID
http
GET /v1/dids/{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 DID.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did | object (DID) | sí | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Inmutable tras la creación. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | Nivel STIR/SHAKEN que firma el carrier. Solo lectura para el tenant: solo lo fija el admin de la plataforma. |
did.status | active · quarantine · retired | no | |
did.verified_at | string (date-time) | null | no | Prueba de titularidad. null = autodeclarado, nunca probado; los DID house nacen verificados. |
did.verification_method | house · otp · admin | null | no | Cómo se probó la titularidad; null mientras verified_at sea null. |
did.origin | house · customer | no | Las filas house son inventario de la plataforma emitido por el admin; la superficie del tenant solo crea customer. |
did.labels | arreglo de string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.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 (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 metadatos/estado (e164 inmutable)
http
PATCH /v1/dids/{id}Un número distinto es un DID distinto; el historial del CDR nunca se reatribuye.
Reglas de rol: una clave dd_ o un inicio de sesión account_admin; un inicio de sesión member recibe 403 role_forbidden (opción por tenant telephony_config_admin_only, activada por defecto). El GET de este recurso no se ve afectado.
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 |
|---|---|---|---|
npa | string | no | |
us_state | string | no | |
attestation | A · B · C · unknown | no | Se acepta e IGNORA: la atestación STIR/SHAKEN es una afirmación que solo registra el admin de la plataforma (POST /v1/admin/tenants/{id}/dids/{did_id}/verify); nunca cambia por esta ruta, que responde como si la clave estuviera ausente. |
status | active · quarantine · retired | no | |
labels | arreglo de string | no | |
notes | string | no | |
origin | house · customer | no | Se acepta e IGNORA POR SEGURIDAD, igual que en POST /v1/dids: origin es inmutable y nunca se convierte, así que cualquier valor aquí no tiene efecto. Reenviar el valor que devolvió un GET no falla; el resto del objeto renderizado sí (id, tenant_id, e164, created_at, updated_at dan un 400). |
json
{
"attestation": "A",
"labels": [
"postman"
],
"notes": "postman smoke"
}Respuestas
200
DID actualizado.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did | object (DID) | sí | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Inmutable tras la creación. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | Nivel STIR/SHAKEN que firma el carrier. Solo lectura para el tenant: solo lo fija el admin de la plataforma. |
did.status | active · quarantine · retired | no | |
did.verified_at | string (date-time) | null | no | Prueba de titularidad. null = autodeclarado, nunca probado; los DID house nacen verificados. |
did.verification_method | house · otp · admin | null | no | Cómo se probó la titularidad; null mientras verified_at sea null. |
did.origin | house · customer | no | Las filas house son inventario de la plataforma emitido por el admin; la superficie del tenant solo crea customer. |
did.labels | arreglo de string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.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"
}
}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 (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 DID (las filas nunca se borran)
http
DELETE /v1/dids/{id}Fija el estado retired, idempotente. Las filas nunca salen del registro (DELETE está revocado en Postgres): la procedencia de from_number del CDR debe seguir resolviéndose para el Defense Packet.
Reglas de rol: una clave dd_ o un inicio de sesión account_admin; un inicio de sesión member recibe 403 role_forbidden (opción por tenant telephony_config_admin_only, activada por defecto). El GET de este recurso no se ve afectado.
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 DID retirado.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did | object (DID) | sí | |
did.id | string (uuid) | no | |
did.tenant_id | string (uuid) | no | |
did.e164 | string | no | Inmutable tras la creación. |
did.npa | string | null | no | |
did.us_state | string | null | no | |
did.attestation | A · B · C · unknown | no | Nivel STIR/SHAKEN que firma el carrier. Solo lectura para el tenant: solo lo fija el admin de la plataforma. |
did.status | active · quarantine · retired | no | |
did.verified_at | string (date-time) | null | no | Prueba de titularidad. null = autodeclarado, nunca probado; los DID house nacen verificados. |
did.verification_method | house · otp · admin | null | no | Cómo se probó la titularidad; null mientras verified_at sea null. |
did.origin | house · customer | no | Las filas house son inventario de la plataforma emitido por el admin; la superficie del tenant solo crea customer. |
did.labels | arreglo de string | no | |
did.notes | string | null | no | |
did.created_at | string (date-time) | no | |
did.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 (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"
}
}Salud del DID calculada a partir del CDR
http
GET /v1/dids/{id}/healthLa salud se CALCULA a partir del CDR de solo anexar en el momento de la lectura: cada número es un recuento de filas, nunca una puntuación en caché. short_call_rate (llamadas contestadas que terminan en menos de 15 s / contestadas) es la señal más fuerte del lado del CDR de «posible spam». Las tasas son null cuando el denominador es cero. reputation.hiya/reputation.tns son nulos explícitos hasta que se contrate una fuente externa. Un DID retirado sigue sirviendo su salud (la procedencia sobrevive a la rotación).
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. |
from | query | string (date-time) | no | Límite inferior RFC 3339 (campo específico del endpoint; por defecto los últimos 30 días UTC donde se indica). |
to | query | string (date-time) | no | Límite superior RFC 3339. |
Respuestas
200
Salud calculada para el periodo (por defecto, los últimos 30 días UTC).
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did_id | string (uuid) | no | |
e164 | string | no | |
status | active · quarantine · retired | no | |
period | object | no | |
period.from | string (date-time) | no | |
period.to | string (date-time) | no | |
dials | integer | no | |
answered | integer | no | |
answer_rate | number | null | no | |
short_calls | integer | no | |
short_call_rate | number | null | no | |
short_call_seconds | integer | no | |
daily | arreglo de object | no | |
daily[].date | string (date) | no | |
daily[].dials | integer | no | |
daily[].answered | integer | no | |
daily[].short_calls | integer | no | |
reputation | object | no | Nulos explícitos hasta que se contrate una fuente externa: muéstralo como pendiente, no como cero. |
reputation.hiya | number | null | no | |
reputation.tns | number | null | no | |
reputation.note | string | no |
json
{
"did_id": "4e3d2c1b-0a9f-4e8d-7c6b-5a4f3e2d1c0b",
"e164": "+13125550184",
"status": "active",
"period": {
"from": "2026-06-05T00:00:00Z",
"to": "2026-07-05T00:00:00Z"
},
"dials": 412,
"answered": 67,
"answer_rate": 0.1626,
"short_calls": 24,
"short_call_rate": 0.3582,
"short_call_seconds": 15,
"daily": [
{
"date": "2026-06-01",
"dials": 80,
"answered": 14,
"short_calls": 5
}
],
"reputation": {
"hiya": null,
"tns": null,
"note": "external reputation feeds not integrated yet"
}
}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"
}
}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 (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"
}
}Lista de verificación de lanzamiento de un número
http
GET /v1/dids/{id}/launch-checklistCuatro pasos, cada uno con su source. attestation es derived del registro (A/B/C = hecho; el valor es lo que declaró el tenant, no un veredicto del carrier). warmup es derived del propio CDR del número: hecho cuando ha marcado en warmup_min_active_days días UTC distintos de los últimos 30. registration y cnam son manual: la plataforma no tiene datos sobre ellos, así que son lo que confirmó el operador. No se consulta ninguna fuente externa de reputación.
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
La lista de verificación.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did_id | string (uuid) | sí | |
e164 | string | sí | |
complete | boolean | sí | Los cuatro pasos están done. |
warmup_min_active_days | integer | sí | |
steps | arreglo de object | sí | |
steps[].step | registration · cnam · attestation · warmup | sí | |
steps[].source | derived · manual | sí | De dónde sale el estado; manual es la palabra del operador. |
steps[].state | done · pending | sí | |
steps[].evidence | object | sí | derived: {origin, ...} con los valores detrás del estado (dids.attestation + value; cdr + active_days, required_days, dials). manual: el último {confirmed_at, note}, vacío si nunca se confirmó. |
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 (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"
}
}Confirmar (o desconfirmar) un paso manual del lanzamiento
http
POST /v1/dids/{id}/launch-checklist/{step}/confirmationsAñade una confirmación para un paso manual (registration o cnam); la última es el estado del paso y ninguna se edita ni se borra nunca. Un paso derived (attestation, warmup) da 422: lo calcula la plataforma. Un paso desconocido da 404. Devuelve la lista de verificación actualizada.
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. |
step | path | registration · cnam · attestation · warmup | sí |
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
confirmed | boolean | sí | |
note | string | no |
Respuestas
201
La lista de verificación tras la confirmación.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
did_id | string (uuid) | sí | |
e164 | string | sí | |
complete | boolean | sí | Los cuatro pasos están done. |
warmup_min_active_days | integer | sí | |
steps | arreglo de object | sí | |
steps[].step | registration · cnam · attestation · warmup | sí | |
steps[].source | derived · manual | sí | De dónde sale el estado; manual es la palabra del operador. |
steps[].state | done · pending | sí | |
steps[].evidence | object | sí | derived: {origin, ...} con los valores detrás del estado (dids.attestation + value; cdr + active_days, required_days, dials). manual: el último {confirmed_at, note}, vacío si nunca se confirmó. |
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"
}
}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 — Unprocessable
La forma es correcta, la semántica no (regla de dominio incumplida).
json
{
"error": {
"code": "unprocessable",
"message": "scheduled_at is closer than the minimum notice for a callback (10 minutes unless the tenant's callback_min_notice_seconds says otherwise)"
}
}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 (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"
}
}Tickets del carrier de un número
http
GET /v1/dids/{id}/carrier-ticketsLos tickets que el tenant mantiene sobre este número con su carrier, el de actividad más reciente primero, cada uno con su hilo completo de solo anexar. Un número retirado sigue sirviendo sus tickets.
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
Los tickets.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
tickets | arreglo de DidCarrierTicket | sí | |
tickets[].id | string (uuid) | sí | |
tickets[].did_id | string (uuid) | sí | |
tickets[].carrier | string | sí | |
tickets[].subject | string | sí | |
tickets[].reference | string | sí | |
tickets[].status | open · in_progress · resolved · closed | sí | |
tickets[].opened_at | string (date-time) | sí | |
tickets[].updated_at | string (date-time) | sí | |
tickets[].events | arreglo de object | sí | El hilo de solo anexar, del más antiguo al más reciente; el primero tiene kind opened. |
tickets[].events[].id | string (uuid) | sí | |
tickets[].events[].kind | opened · update | sí | |
tickets[].events[].status | open · in_progress · resolved · closed | sí | |
tickets[].events[].note | string | sí | |
tickets[].events[].created_at | string (date-time) | sí |
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 (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"
}
}Abrir un ticket del carrier para un número
http
POST /v1/dids/{id}/carrier-ticketsPará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 |
|---|---|---|---|
carrier | string | sí | |
subject | string | sí | |
reference | string | no | La referencia propia del carrier para el ticket, si dio una. |
note | string | no |
Respuestas
201
El ticket abierto (estado open).
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
ticket | object (DidCarrierTicket) | sí | |
ticket.id | string (uuid) | sí | |
ticket.did_id | string (uuid) | sí | |
ticket.carrier | string | sí | |
ticket.subject | string | sí | |
ticket.reference | string | sí | |
ticket.status | open · in_progress · resolved · closed | sí | |
ticket.opened_at | string (date-time) | sí | |
ticket.updated_at | string (date-time) | sí | |
ticket.events | arreglo de object | sí | El hilo de solo anexar, del más antiguo al más reciente; el primero tiene kind opened. |
ticket.events[].id | string (uuid) | sí | |
ticket.events[].kind | opened · update | sí | |
ticket.events[].status | open · in_progress · resolved · closed | sí | |
ticket.events[].note | string | sí | |
ticket.events[].created_at | string (date-time) | sí |
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"
}
}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 (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"
}
}Añadir una nota y/o cambiar el estado de un ticket del carrier
http
POST /v1/dids/{id}/carrier-tickets/{ticket_id}/eventsAñade al hilo del ticket; nada se edita ni se borra. status toma por defecto el vigente. Un evento sin nota ni cambio de estado da 400.
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. |
ticket_id | path | string (uuid) | sí | UUID del ticket. Debe pertenecer al número de la ruta; si no, 404. |
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
status | open · in_progress · resolved · closed | no | |
note | string | no |
Respuestas
201
El ticket con el nuevo evento añadido.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
ticket | object (DidCarrierTicket) | sí | |
ticket.id | string (uuid) | sí | |
ticket.did_id | string (uuid) | sí | |
ticket.carrier | string | sí | |
ticket.subject | string | sí | |
ticket.reference | string | sí | |
ticket.status | open · in_progress · resolved · closed | sí | |
ticket.opened_at | string (date-time) | sí | |
ticket.updated_at | string (date-time) | sí | |
ticket.events | arreglo de object | sí | El hilo de solo anexar, del más antiguo al más reciente; el primero tiene kind opened. |
ticket.events[].id | string (uuid) | sí | |
ticket.events[].kind | opened · update | sí | |
ticket.events[].status | open · in_progress · resolved · closed | sí | |
ticket.events[].note | string | sí | |
ticket.events[].created_at | string (date-time) | sí |
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"
}
}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 (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"
}
}