Apariencia
Claves de API
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.
Claves de API por tenant (sha256 en reposo; texto plano mostrado una vez).
Endpoints
| Método | Ruta | Resumen |
|---|---|---|
GET | /v1/api_keys | Listar las claves de API |
POST | /v1/api_keys | Emitir una clave de API |
PATCH | /v1/api_keys/{id} | Establecer la lista de permitidos de red de una clave de API |
DELETE | /v1/api_keys/{id} | Revocar una clave de API |
POST | /v1/api_keys/{id}/rotate | Rotar una clave de API en un paso, con solape |
GET | /v1/api_keys/{id}/requests | Peticiones hechas con una clave de API |
GET | /v1/api_keys/{id}/requests/summary | Peticiones por minuto de una clave de API, con sus 429 |
Listar las claves de API
http
GET /v1/api_keysSolo ids, etiquetas y marcas de tiempo de revocación — los hashes nunca se exponen.
Respuestas
200
Las claves del tenant.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
api_keys | arreglo de ApiKey | sí | |
api_keys[].id | string (uuid) | no | |
api_keys[].label | string | no | |
api_keys[].environment | live · test | no | live (toda clave anterior al campo) o test: una clave de prueba no alcanza ninguna ruta de salida. Fijo en la creación. |
api_keys[].revoked_at | string (date-time) | null | no | |
api_keys[].last_used_at | string (date-time) | null | no | Reloj de higiene de rotación: la última vez que esta clave se autenticó CON ÉXITO. Se escribe como mucho una vez por minuto por clave, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha autenticado con éxito desde que la columna adquirió un escritor — no que la clave nunca se haya presentado. |
api_keys[].allowed_cidrs | arreglo de string | no | Lista de permitidos de red. [] = sin restricción. Fuera de ella, una petición se sirve y se cuenta, o se rechaza con 401, según el interruptor de tenant api_key_network_enforced (desactivado por defecto). |
api_keys[].stale | boolean | no | true para una clave live sin uso durante 90 días (una clave que nunca se autenticó cuenta desde su creación). Es un consejo para que la consola la rote o la revoque; una clave solo caduca por sí sola cuando tiene expires_at. |
api_keys[].permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. null = todos (toda clave anterior al campo). |
api_keys[].expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse; null = nunca. Una rotación lo fija en la clave antigua al final del solape. |
api_keys[].created_by_user_id | string (uuid) | null | no | El usuario del dashboard cuya sesión emitió la clave. null cuando la emitió otra clave dd_, el operador o las semillas, y en toda clave anterior al campo. |
api_keys[].created_at | string (date-time) | no |
json
{
"api_keys": [
{
"id": "7a3f0f7e-52a1-4f3d-9f9d-27e5a1b9c001",
"label": "onboarding",
"revoked_at": null,
"created_at": "2026-06-01T12:00:00Z"
}
]
}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"
}
}Emitir una clave de API
http
POST /v1/api_keysEl token en claro (dd_...) se devuelve UNA SOLA VEZ y solo se almacena su sha256. Rota en un paso con POST /v1/api_keys/{id}/rotate.
environment es live (por defecto; el prefijo histórico dd_) o test (prefijo de token dd_test_). Una clave de prueba se autentica y lee por los mismos carriles y RLS que una live, pero no alcanza ninguna ruta de salida: las rutas que marcan, envían SMS, compran números o aprovisionan operadores responden 403 test_environment, y no se mide ni se cobra nada. La misma respuesta cubre las rutas que emiten, fijan o restablecen una credencial o identidad live: POST|DELETE /agents/{id}/credential, POST /api_keys/{id}/rotate, POST /users y su enable, mfa/reset-failures y mfa/remove, POST|PATCH /click-to-call/sites, POST /widget_tokens (y /sip_credential) y PUT|PATCH /sso/idp-config. El entorno queda fijado en la creación.
Reglas de rol: emitir exige un login account_admin (403 role_forbidden para un member Y, una vez que el tenant tiene un account_admin activo, para una clave dd_; ajuste por tenant api_key_admin_only, activado por defecto; ajuste del fundador api_key_manages_people, desactivado por defecto). Un tenant sin account_admin activo mantiene la emisión con la clave dd_. Una clave emitida desde un login del dashboard registra a esa persona en created_by_user_id; toda emisión se escribe en el rastro de auditoría de claves.
allowed_cidrs es la lista de redes permitidas de la clave; omitido o [] significa sin restricción. Lo que ocurre con una petición desde fuera de la lista lo decide el ajuste del tenant api_key_network_enforced: desactivado (por defecto) la sirve y la cuenta, activado responde 401.
permissions restringe la clave a GRUPOS de rutas; ausente o null es la clave de siempre (todas las rutas). Una clave con lista recibe 403 permission_denied en las rutas de cualquier otro grupo (p. ej. /v1/billing/* sin billing); el grupo de una ruta es su primer segmento de path, y un segmento que ningún grupo reclama pertenece a general. Una clave que a su vez tiene una lista no puede emitir una con más permisos (403 permission_escalation). expires_at (ISO 8601, en el futuro; ausente = nunca) es el instante a partir del cual la clave deja de autenticarse (401, como una revocada); las demás claves no se ven afectadas.
Límites: un tenant tiene como máximo api_keys_max_live claves LIVE (50 por defecto; 409 api_key_limit por encima, revocar una clave libera un hueco), y la emisión tiene límite de tasa por tenant (429 rate_limited con Retry-After). La cuota de peticiones es por clave, así que las claves de un tenant juntas también están acotadas por api_tenant_requests_per_minute (por defecto 5 veces la de una clave).
Cuerpo de la petición (JSON)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
label | string | no | Etiqueta de formato libre (por defecto ""). |
environment | live · test | no | test emite una clave que nunca alcanza llamadas, SMS ni correo (prefijo dd_test_). Inmutable. Cualquier otro valor es 422. |
allowed_cidrs | arreglo de string | no | CIDR (o direcciones simples) desde los que se puede usar la clave. Una lista con una entrada que no se puede interpretar se rechaza entera (400); un valor que no es una lista de cadenas da 422. |
permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. Ausente o null = todos. [] = ninguno. Un grupo desconocido es 422. |
expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse. Debe estar en el futuro (si no, 422). |
json
{
"label": "postman-smoke-1751600000"
}Respuestas
201
Clave emitida; token es la única vez que el texto plano es visible.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
api_key | object (ApiKey) | sí | Metadatos de la clave — el hash del token nunca se expone. |
api_key.id | string (uuid) | no | |
api_key.label | string | no | |
api_key.environment | live · test | no | live (toda clave anterior al campo) o test: una clave de prueba no alcanza ninguna ruta de salida. Fijo en la creación. |
api_key.revoked_at | string (date-time) | null | no | |
api_key.last_used_at | string (date-time) | null | no | Reloj de higiene de rotación: la última vez que esta clave se autenticó CON ÉXITO. Se escribe como mucho una vez por minuto por clave, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha autenticado con éxito desde que la columna adquirió un escritor — no que la clave nunca se haya presentado. |
api_key.allowed_cidrs | arreglo de string | no | Lista de permitidos de red. [] = sin restricción. Fuera de ella, una petición se sirve y se cuenta, o se rechaza con 401, según el interruptor de tenant api_key_network_enforced (desactivado por defecto). |
api_key.stale | boolean | no | true para una clave live sin uso durante 90 días (una clave que nunca se autenticó cuenta desde su creación). Es un consejo para que la consola la rote o la revoque; una clave solo caduca por sí sola cuando tiene expires_at. |
api_key.permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. null = todos (toda clave anterior al campo). |
api_key.expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse; null = nunca. Una rotación lo fija en la clave antigua al final del solape. |
api_key.created_by_user_id | string (uuid) | null | no | El usuario del dashboard cuya sesión emitió la clave. null cuando la emitió otra clave dd_, el operador o las semillas, y en toda clave anterior al campo. |
api_key.created_at | string (date-time) | no | |
token | string | sí | Token bearer en texto plano, mostrado exactamente una vez. |
json
{
"api_key": {
"id": "9a1c2b3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
"label": "postman-smoke-1751600000",
"revoked_at": null,
"created_at": "2026-07-05T10:00:00Z"
},
"token": "dd_example_plaintext_shown_once"
}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 — ApiKeyAdminForbidden
Se rechazó emitir o revocar una clave de API. code role_forbidden: quien llama es un inicio de sesión de dashboard sin el rol account_admin, o una clave dd_ en un tenant que ya tiene un account_admin activo (interruptor del founder api_key_manages_people, desactivado por defecto); el interruptor por tenant api_key_admin_only (activado por defecto) desactiva esto.
json
{
"error": {
"code": "role_forbidden",
"message": "minting or revoking an API key takes a dashboard login with the account_admin role; a dd_ key may do it only while the tenant has no account_admin"
}
}409 — ApiKeyLimit
El tenant ya tiene el número máximo de claves de API VIVAS (interruptor por tenant api_keys_max_live, 50 por defecto). code api_key_limit. No se emitió nada; revoca una clave (DELETE /v1/api_keys/{id}) y reintenta.
json
{
"error": {
"code": "api_key_limit",
"message": "this tenant already holds the maximum number of live API keys; revoke one first"
}
}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"
}
}Establecer la lista de permitidos de red de una clave de API
http
PATCH /v1/api_keys/{id}Sustituye allowed_cidrs de una clave LIVE; [] levanta la restricción. Admite los mismos roles que la emisión (403 role_forbidden para un member mientras el knob api_key_admin_only esté activado). El cambio se escribe en la pista de auditoría de la clave como network_changed y rige desde la siguiente petición: la clave se olvida de la caché de autenticación. Una clave revocada o desconocida es 404. Una clave que tiene una lista de permisos solo puede modificarse a sí misma y a las claves cuyos permisos cubre: en otro caso 403 permission_escalation.
Una clave de API test solo puede actuar sobre claves test: contra una clave live se rechaza con 403 test_environment y la clave queda intacta.
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 |
|---|---|---|---|
allowed_cidrs | arreglo de string | sí |
json
{
"allowed_cidrs": [
"203.0.113.0/24",
"2001:db8::/32"
]
}Respuestas
200
La clave con su nueva lista.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
api_key | object (ApiKey) | sí | Metadatos de la clave — el hash del token nunca se expone. |
api_key.id | string (uuid) | no | |
api_key.label | string | no | |
api_key.environment | live · test | no | live (toda clave anterior al campo) o test: una clave de prueba no alcanza ninguna ruta de salida. Fijo en la creación. |
api_key.revoked_at | string (date-time) | null | no | |
api_key.last_used_at | string (date-time) | null | no | Reloj de higiene de rotación: la última vez que esta clave se autenticó CON ÉXITO. Se escribe como mucho una vez por minuto por clave, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha autenticado con éxito desde que la columna adquirió un escritor — no que la clave nunca se haya presentado. |
api_key.allowed_cidrs | arreglo de string | no | Lista de permitidos de red. [] = sin restricción. Fuera de ella, una petición se sirve y se cuenta, o se rechaza con 401, según el interruptor de tenant api_key_network_enforced (desactivado por defecto). |
api_key.stale | boolean | no | true para una clave live sin uso durante 90 días (una clave que nunca se autenticó cuenta desde su creación). Es un consejo para que la consola la rote o la revoque; una clave solo caduca por sí sola cuando tiene expires_at. |
api_key.permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. null = todos (toda clave anterior al campo). |
api_key.expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse; null = nunca. Una rotación lo fija en la clave antigua al final del solape. |
api_key.created_by_user_id | string (uuid) | null | no | El usuario del dashboard cuya sesión emitió la clave. null cuando la emitió otra clave dd_, el operador o las semillas, y en toda clave anterior al campo. |
api_key.created_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 — ApiKeyAdminForbidden
Se rechazó emitir o revocar una clave de API. code role_forbidden: quien llama es un inicio de sesión de dashboard sin el rol account_admin, o una clave dd_ en un tenant que ya tiene un account_admin activo (interruptor del founder api_key_manages_people, desactivado por defecto); el interruptor por tenant api_key_admin_only (activado por defecto) desactiva esto.
json
{
"error": {
"code": "role_forbidden",
"message": "minting or revoking an API key takes a dashboard login with the account_admin role; a dd_ key may do it only while the tenant has no account_admin"
}
}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"
}
}Revocar una clave de API
http
DELETE /v1/api_keys/{id}Fija revoked_at; las claves nunca se borran. Semántica de revocación idempotente.
Reglas de rol: revocar requiere un login account_admin (403 role_forbidden para un member Y, una vez que el tenant tiene un account_admin activo, para una clave dd_; knob por tenant api_key_admin_only, activado por defecto; knob del founder api_key_manages_people, desactivado por defecto). Un tenant sin ningún account_admin activo mantiene la revocación con la clave dd_. Toda revocación se escribe en la pista de auditoría de la clave. Una clave que tiene una lista de permisos solo puede revocarse a sí misma y a las claves cuyos permisos cubre: en otro caso 403 permission_escalation.
Una clave de API test solo puede actuar sobre claves test: contra una clave live se rechaza con 403 test_environment y la clave queda intacta.
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 clave revocada.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
api_key | object (ApiKey) | sí | Metadatos de la clave — el hash del token nunca se expone. |
api_key.id | string (uuid) | no | |
api_key.label | string | no | |
api_key.environment | live · test | no | live (toda clave anterior al campo) o test: una clave de prueba no alcanza ninguna ruta de salida. Fijo en la creación. |
api_key.revoked_at | string (date-time) | null | no | |
api_key.last_used_at | string (date-time) | null | no | Reloj de higiene de rotación: la última vez que esta clave se autenticó CON ÉXITO. Se escribe como mucho una vez por minuto por clave, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha autenticado con éxito desde que la columna adquirió un escritor — no que la clave nunca se haya presentado. |
api_key.allowed_cidrs | arreglo de string | no | Lista de permitidos de red. [] = sin restricción. Fuera de ella, una petición se sirve y se cuenta, o se rechaza con 401, según el interruptor de tenant api_key_network_enforced (desactivado por defecto). |
api_key.stale | boolean | no | true para una clave live sin uso durante 90 días (una clave que nunca se autenticó cuenta desde su creación). Es un consejo para que la consola la rote o la revoque; una clave solo caduca por sí sola cuando tiene expires_at. |
api_key.permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. null = todos (toda clave anterior al campo). |
api_key.expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse; null = nunca. Una rotación lo fija en la clave antigua al final del solape. |
api_key.created_by_user_id | string (uuid) | null | no | El usuario del dashboard cuya sesión emitió la clave. null cuando la emitió otra clave dd_, el operador o las semillas, y en toda clave anterior al campo. |
api_key.created_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"
}
}403 — ApiKeyAdminForbidden
Se rechazó emitir o revocar una clave de API. code role_forbidden: quien llama es un inicio de sesión de dashboard sin el rol account_admin, o una clave dd_ en un tenant que ya tiene un account_admin activo (interruptor del founder api_key_manages_people, desactivado por defecto); el interruptor por tenant api_key_admin_only (activado por defecto) desactiva esto.
json
{
"error": {
"code": "role_forbidden",
"message": "minting or revoking an API key takes a dashboard login with the account_admin role; a dd_ key may do it only while the tenant has no account_admin"
}
}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"
}
}Rotar una clave de API en un paso, con solape
http
POST /v1/api_keys/{id}/rotateEmite una clave nueva con la misma etiqueta, entorno, lista de redes y permisos y deja que la antigua siga autenticándose durante overlap_seconds (3600 por defecto, máximo 86400; 0 la corta de inmediato); pasado ese tiempo solo lo hace la nueva. El expires_at de la clave antigua pasa a ser el final del solape (nunca posterior al que ya tuviera) y se devuelve como rotated. El token nuevo se muestra UNA SOLA VEZ. El rastro de auditoría de claves recibe issued (nueva) y rotated (antigua). Mismos roles, límite de tasa de emisión y límite de claves live que la emisión; durante el solape ambas claves cuentan para el límite. Una clave que tiene una lista de permisos solo rota claves cuyos permisos cubre (403 permission_escalation). Una clave revocada, caducada o desconocida es 404.
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)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
overlap_seconds | integer | no | |
expires_at | string (date-time) | null | no | Caducidad opcional de la clave NUEVA (la caducidad de la antigua no se hereda). |
json
{
"overlap_seconds": 1800
}Respuestas
201
La clave nueva (con su token, una sola vez) y la antigua con el final de su solape.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
api_key | object (ApiKey) | sí | Metadatos de la clave — el hash del token nunca se expone. |
api_key.id | string (uuid) | no | |
api_key.label | string | no | |
api_key.environment | live · test | no | live (toda clave anterior al campo) o test: una clave de prueba no alcanza ninguna ruta de salida. Fijo en la creación. |
api_key.revoked_at | string (date-time) | null | no | |
api_key.last_used_at | string (date-time) | null | no | Reloj de higiene de rotación: la última vez que esta clave se autenticó CON ÉXITO. Se escribe como mucho una vez por minuto por clave, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha autenticado con éxito desde que la columna adquirió un escritor — no que la clave nunca se haya presentado. |
api_key.allowed_cidrs | arreglo de string | no | Lista de permitidos de red. [] = sin restricción. Fuera de ella, una petición se sirve y se cuenta, o se rechaza con 401, según el interruptor de tenant api_key_network_enforced (desactivado por defecto). |
api_key.stale | boolean | no | true para una clave live sin uso durante 90 días (una clave que nunca se autenticó cuenta desde su creación). Es un consejo para que la consola la rote o la revoque; una clave solo caduca por sí sola cuando tiene expires_at. |
api_key.permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. null = todos (toda clave anterior al campo). |
api_key.expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse; null = nunca. Una rotación lo fija en la clave antigua al final del solape. |
api_key.created_by_user_id | string (uuid) | null | no | El usuario del dashboard cuya sesión emitió la clave. null cuando la emitió otra clave dd_, el operador o las semillas, y en toda clave anterior al campo. |
api_key.created_at | string (date-time) | no | |
token | string | sí | Token bearer en texto plano, mostrado exactamente una vez. |
rotated | object (ApiKey) | sí | Metadatos de la clave — el hash del token nunca se expone. |
rotated.id | string (uuid) | no | |
rotated.label | string | no | |
rotated.environment | live · test | no | live (toda clave anterior al campo) o test: una clave de prueba no alcanza ninguna ruta de salida. Fijo en la creación. |
rotated.revoked_at | string (date-time) | null | no | |
rotated.last_used_at | string (date-time) | null | no | Reloj de higiene de rotación: la última vez que esta clave se autenticó CON ÉXITO. Se escribe como mucho una vez por minuto por clave, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha autenticado con éxito desde que la columna adquirió un escritor — no que la clave nunca se haya presentado. |
rotated.allowed_cidrs | arreglo de string | no | Lista de permitidos de red. [] = sin restricción. Fuera de ella, una petición se sirve y se cuenta, o se rechaza con 401, según el interruptor de tenant api_key_network_enforced (desactivado por defecto). |
rotated.stale | boolean | no | true para una clave live sin uso durante 90 días (una clave que nunca se autenticó cuenta desde su creación). Es un consejo para que la consola la rote o la revoque; una clave solo caduca por sí sola cuando tiene expires_at. |
rotated.permissions | arreglo de ApiKeyPermission | null | no | Grupos de rutas a los que puede entrar la clave. null = todos (toda clave anterior al campo). |
rotated.expires_at | string (date-time) | null | no | Instante a partir del cual la clave deja de autenticarse; null = nunca. Una rotación lo fija en la clave antigua al final del solape. |
rotated.created_by_user_id | string (uuid) | null | no | El usuario del dashboard cuya sesión emitió la clave. null cuando la emitió otra clave dd_, el operador o las semillas, y en toda clave anterior al campo. |
rotated.created_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 — ApiKeyAdminForbidden
Se rechazó emitir o revocar una clave de API. code role_forbidden: quien llama es un inicio de sesión de dashboard sin el rol account_admin, o una clave dd_ en un tenant que ya tiene un account_admin activo (interruptor del founder api_key_manages_people, desactivado por defecto); el interruptor por tenant api_key_admin_only (activado por defecto) desactiva esto.
json
{
"error": {
"code": "role_forbidden",
"message": "minting or revoking an API key takes a dashboard login with the account_admin role; a dd_ key may do it only while the tenant has no account_admin"
}
}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"
}
}409 — ApiKeyLimit
El tenant ya tiene el número máximo de claves de API VIVAS (interruptor por tenant api_keys_max_live, 50 por defecto). code api_key_limit. No se emitió nada; revoca una clave (DELETE /v1/api_keys/{id}) y reintenta.
json
{
"error": {
"code": "api_key_limit",
"message": "this tenant already holds the maximum number of live API keys; revoke one first"
}
}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"
}
}Peticiones hechas con una clave de API
http
GET /v1/api_keys/{id}/requestsEl rastro de peticiones de UNA clave dd_, la más reciente primero, paginado por keyset: método, PLANTILLA de ruta (/v1/calls/:call_id, nunca la URL con ids), estado HTTP, duración y el request_id que quien llama también vio en x-request-id. Una petición aparece en cuestión de segundos (el escritor es asíncrono, fuera de la ruta de la petición).
Nunca se almacena: cuerpos de petición o respuesta, cabeceras (incluida Authorization), la query string, la IP ni el hash de la clave. Las filas se conservan API_REQUEST_LOG_RETENTION_DAYS días (30 por defecto, mínimo 1). Un 429 de la cuota de la clave es una fila como cualquier otra; lleva la plantilla de ruta que el router había casado (/v1 cuando aún ninguna).
Filtros: since (inclusivo) y until (exclusivo), RFC-3339; status, un estado HTTP exacto. Un filtro mal formado es 400, nunca una página vacía en silencio. Ámbito de tenant (clave dd_ o login del dashboard); una clave de otro tenant es 404.
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. |
since | query | string (date-time) | no | |
until | query | string (date-time) | no | |
status | query | integer | no | |
limit | query | integer | no | |
cursor | query | string | no | Cursor keyset opaco: el next_cursor de la página anterior. |
Respuestas
200
Una página de peticiones, la más reciente primero.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
requests | arreglo de ApiRequest | sí | |
requests[].id | string (uuid) | sí | |
requests[].request_id | string | sí | El x-request-id de la petición. |
requests[].method | string | sí | |
requests[].route | string | sí | Plantilla de ruta, nunca la URL con ids. |
requests[].status | integer | sí | |
requests[].duration_us | integer | sí | Microsegundos desde que se aceptó la clave hasta que salió la respuesta. |
requests[].requested_at | string (date-time) | sí | |
next_cursor | string | null | sí | Cursor de la página siguiente; null en la última. |
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 (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"
}
}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"
}
}Peticiones por minuto de una clave de API, con sus 429
http
GET /v1/api_keys/{id}/requests/summaryRecuentos por minuto de las peticiones de UNA clave: requests, rate_limited (estado 429, la cuota de la clave o del tenant) y server_errors (estado >= 500). Solo aparecen los minutos con tráfico, el más reciente primero. Ventana [since, until): por defecto la última hora, como máximo 1440 minutos (400 por encima). Mismo ámbito, retención y regla 404 que el listado.
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. |
since | query | string (date-time) | no | |
until | query | string (date-time) | no |
Respuestas
200
Los recuentos por minuto.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
minutes | arreglo de ApiRequestMinute | sí | |
minutes[].minute | string (date-time) | sí | |
minutes[].requests | integer | sí | |
minutes[].rate_limited | integer | sí | Respuestas con estado 429. |
minutes[].server_errors | integer | sí | Respuestas con estado >= 500. |
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 (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"
}
}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"
}
}