Skip to content

Widgets ​

Generado desde DialerDigital/core commit 0fc18008b3c8 — especificación openapi/dialer-v1.yaml v0.134.0. No se edita a mano; consulta Cómo se construye esta referencia. Descargar la especificación OpenAPI.

English version

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.

Ciclo de vida del widget de agente incrustable: tokens de navegador ddw_ y lista de orígenes permitidos.

Endpoints ​

MétodoRutaResumen
GET/v1/widget_tokensListar los tokens de widget
POST/v1/widget_tokensEmitir un token de widget
DELETE/v1/widget_tokens/{id}Revocar un token de widget
POST/v1/widget_tokens/renewRenovar la sesión de widget de quien llama
POST/v1/widget_tokens/introspectEl contexto de la sesión de widget de quien llama
POST/v1/widget_tokens/sip_credentialEmitir la credencial SIP efímera de quien llama
DELETE/v1/widget_tokens/sip_credentialDevolver la credencial SIP efímera de quien llama
GET/v1/widget_originsListar los orígenes permitidos
POST/v1/widget_originsAñadir un origen permitido
DELETE/v1/widget_origins/{id}Deshabilitar un origen permitido
POST/v1/widget_origins/{id}/enableVolver a habilitar un origen permitido

Listar los tokens de widget ​

http
GET /v1/widget_tokens

Solo ids, agente, etiquetas, caducidad y revocación; el hash del token nunca se expone.

Respuestas

200 ​

Los tokens de widget del tenant.

CampoTipoObligatorioDescripción
widget_tokensarreglo de WidgetTokensí
widget_tokens[].idstring (uuid)no
widget_tokens[].agent_idstring (uuid)no
widget_tokens[].labelstringno
widget_tokens[].allowed_origin_idstring (uuid) | nullnoFijación opcional a una fila de widget_origins — reduce los orígenes de EMBED expuestos al frame (CSP/postMessage) a solo ese; null = todos los orígenes de embed habilitados del tenant. NO es el límite de autenticación (ese es el Origin widget-host). El inicio de sesión del agente emite SIN FIJAR.
widget_tokens[].expires_atstring (date-time)no
widget_tokens[].session_expires_atstring (date-time)no
widget_tokens[].revoked_atstring (date-time) | nullno
widget_tokens[].last_used_atstring (date-time) | nullnoReloj de higiene de rotación, con el mismo significado que ApiKey.last_used_at: la última vez que este token se resolvió CON ÉXITO (superadas todas las compuertas), escrito como mucho una vez por minuto por token, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha resuelto con éxito desde que la columna adquirió un escritor en la ruta caliente — no que el token nunca se haya presentado. La renovación también lo marca.
widget_tokens[].created_atstring (date-time)no
widget_tokens[].updated_atstring (date-time)noFecha la FILA, no la emisión: el reloj de uso anterior y las escrituras del ciclo de vida (renovación, baja) lo mueven todos.

401 — Unauthorized ​

Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.

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

403 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

429 — ApiKeyRateLimited ​

Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

Emitir un token de widget ​

http
POST /v1/widget_tokens

Emite un token de navegador ddw_ ligado a un agente. El texto plano se devuelve UNA sola vez; solo se almacena su sha256. Los TTL los fija el servidor (nunca vienen de la entrada del cliente). Tiene límite de uso por tenant.

PARA QUIÉN se emite el token depende del principal (ADR #133, ADR #134). Una clave de máquina dd_ nombra a cualquier agente de su tenant y para ella agent_id es obligatorio (400 si falta). Una sesión de login ddu_ cuya persona está vinculada a un puesto de agente emite para ESE puesto: agent_id puede omitirse (se rellena con el puesto) o repetirlo; nombrar a otro agente da 403 forbidden y no se emite ningún token: una persona no puede acuñar la credencial de otro agente. Una ddu_ sin puesto vinculado puede emitir para otro agente solo con users.role = account_admin (un member recibe 403 role_forbidden), una vez que la llave de catálogo del tenant ddu_author_role_enforced está activada (nace apagada: hasta entonces la sesión sin puesto conserva el contrato de dd_, con agent_id obligatorio).

Cuerpo de la petición (JSON, obligatorio)

CampoTipoObligatorioDescripción
agent_idstring (uuid)noEl agente en cuyo nombre actúa este token. OBLIGATORIO para una clave dd_; opcional (y, si se indica, debe ser el puesto propio de quien llama) para una sesión ddu_ vinculada a un puesto.
labelstringnoEtiqueta de formato libre (por defecto "").
allowed_origin_idstring (uuid)noOpcional: lo fija a una sola fila de widget_origins (acota los orígenes de INCRUSTACIÓN que se muestran al marco; NO es el límite de autenticación, que es el Origin del anfitrión del widget). El inicio de sesión del agente emite SIN fijar.
json
{
  "agent_id": "7a3f0f7e-52a1-4f3d-9f9d-27e5a1b9c001",
  "label": "crm-embed"
}

Respuestas

201 ​

Token emitido; token es la única vez que se ve el texto plano.

CampoTipoObligatorioDescripción
widget_tokenobject (WidgetToken)síUn token de widget de navegador ddw_ — el texto plano y el hash nunca se exponen aquí.
widget_token.idstring (uuid)no
widget_token.agent_idstring (uuid)no
widget_token.labelstringno
widget_token.allowed_origin_idstring (uuid) | nullnoFijación opcional a una fila de widget_origins — reduce los orígenes de EMBED expuestos al frame (CSP/postMessage) a solo ese; null = todos los orígenes de embed habilitados del tenant. NO es el límite de autenticación (ese es el Origin widget-host). El inicio de sesión del agente emite SIN FIJAR.
widget_token.expires_atstring (date-time)no
widget_token.session_expires_atstring (date-time)no
widget_token.revoked_atstring (date-time) | nullno
widget_token.last_used_atstring (date-time) | nullnoReloj de higiene de rotación, con el mismo significado que ApiKey.last_used_at: la última vez que este token se resolvió CON ÉXITO (superadas todas las compuertas), escrito como mucho una vez por minuto por token, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha resuelto con éxito desde que la columna adquirió un escritor en la ruta caliente — no que el token nunca se haya presentado. La renovación también lo marca.
widget_token.created_atstring (date-time)no
widget_token.updated_atstring (date-time)noFecha la FILA, no la emisión: el reloj de uso anterior y las escrituras del ciclo de vida (renovación, baja) lo mueven todos.
tokenstringsíToken ddw_ en texto plano, mostrado exactamente una vez.

400 — BadRequest ​

Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).

json
{
  "error": {
    "code": "bad_request",
    "message": "from must be RFC-3339"
  }
}

401 — Unauthorized ​

Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.

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

403 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

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 — WidgetRateLimited ​

El freno de escritura de tokens de widget rechazó esta petición (reintentable más tarde). code rate_limited. La emisión tiene límite por tenant; la renovación, por token. Retry-After es el tiempo que queda en la ventana fija.

json
{
  "error": {
    "code": "rate_limited",
    "message": "widget token mint rate limit exceeded; retry later"
  }
}

Revocar un token de widget ​

http
DELETE /v1/widget_tokens/{id}

Fija revoked_at; los tokens nunca se borran. Idempotente.

TAMBIÉN desmonta el endpoint SIP del agente (NR-02): borra la credencial efímera agentcred y el registro usrloc vivo. Sin esto, un token revocado dejaba al softphone en condiciones de hacer REGISTER y cursar llamadas hasta la caducidad automática de la credencial a las 24 h. La revocación en la base de datos es duradera y ocurre en cualquier caso; sip_teardown informa de si la parte SIP tuvo éxito, de modo que un 200 nunca implica una expulsión que no ocurrió.

Parámetros

NombreEnTipoObligatorioDescripción
idpathstring (uuid)síUUID del recurso. Los ids mal formados o de otro tenant se leen como 404.

Respuestas

200 ​

El token revocado, más el resultado del desmontaje SIP.

CampoTipoObligatorioDescripción
widget_tokenobject (WidgetToken)síUn token de widget de navegador ddw_ — el texto plano y el hash nunca se exponen aquí.
widget_token.idstring (uuid)no
widget_token.agent_idstring (uuid)no
widget_token.labelstringno
widget_token.allowed_origin_idstring (uuid) | nullnoFijación opcional a una fila de widget_origins — reduce los orígenes de EMBED expuestos al frame (CSP/postMessage) a solo ese; null = todos los orígenes de embed habilitados del tenant. NO es el límite de autenticación (ese es el Origin widget-host). El inicio de sesión del agente emite SIN FIJAR.
widget_token.expires_atstring (date-time)no
widget_token.session_expires_atstring (date-time)no
widget_token.revoked_atstring (date-time) | nullno
widget_token.last_used_atstring (date-time) | nullnoReloj de higiene de rotación, con el mismo significado que ApiKey.last_used_at: la última vez que este token se resolvió CON ÉXITO (superadas todas las compuertas), escrito como mucho una vez por minuto por token, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha resuelto con éxito desde que la columna adquirió un escritor en la ruta caliente — no que el token nunca se haya presentado. La renovación también lo marca.
widget_token.created_atstring (date-time)no
widget_token.updated_atstring (date-time)noFecha la FILA, no la emisión: el reloj de uso anterior y las escrituras del ciclo de vida (renovación, baja) lo mueven todos.
sip_teardownok · skipped · failedsíResultado del desmontaje SIP que acompaña a una revocación (NR-02): el borrado de la credencial efímera agentcred del agente y de su registro usrloc vivo en Kamailio. * ok: credencial y registro eliminados; el softphone ya no puede registrarse. * skipped: no había nada que eliminar: el agente no tiene extensión SIP, el aprovisionamiento del SBC no está configurado en este entorno, o el agente aún conserva una sesión VIGENTE (véase abajo), por lo que esta revocación no dejó ningún acceso abierto. * failed: la revocación en la base de datos se mantiene, pero la credencial SIP SIGUE ACTIVA y lo seguirá hasta su caducidad automática a las 24 h. Trátalo como una vía de acceso abierta: reintenta o expulsa al agente por otros medios. Es un campo y no un código de estado a propósito: la revocación en sí es duradera y sí ocurrió, así que un 5xx mentiría en el otro sentido. Lo que nunca debe pasar es un 200 silencioso que implique una expulsión que no ocurrió. El desmontaje sigue a la TRANSICIÓN, no al agente. Revocar un id de token que ya estaba revocado (un id que un cliente puede conservar legítimamente, ya que GET /v1/widget_tokens lista las filas revocadas, y ya que emitir un token sustituye al anterior) NO debe expulsar, porque se cortaría la sesión SUCESORA del agente. Por tanto, el desmontaje solo se ejecuta cuando el agente se queda sin ningún token vigente; en caso contrario informa skipped. Esto es lo que mantiene útil el consejo de reintento de failed: un token ya revocado y sin sucesor vivo sí expulsa en un DELETE reintentado, de modo que reintentar es un remedio real y no una operación vacía.

401 — Unauthorized ​

Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.

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

403 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

404 — NotFound ​

Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).

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

429 — ApiKeyRateLimited ​

Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

Renovar la sesión de widget de quien llama ​

http
POST /v1/widget_tokens/renew

Adelanta la caducidad del token ddw_ AUTENTICADO (nunca más allá del tope de la sesión). Se autentica con el propio ddw_; opera SOLO sobre el token de quien llama (no hay id en la ruta ni en el cuerpo). Tiene límite de uso por token.

Respuestas

200 ​

El token renovado.

CampoTipoObligatorioDescripción
widget_tokenobject (WidgetToken)síUn token de widget de navegador ddw_ — el texto plano y el hash nunca se exponen aquí.
widget_token.idstring (uuid)no
widget_token.agent_idstring (uuid)no
widget_token.labelstringno
widget_token.allowed_origin_idstring (uuid) | nullnoFijación opcional a una fila de widget_origins — reduce los orígenes de EMBED expuestos al frame (CSP/postMessage) a solo ese; null = todos los orígenes de embed habilitados del tenant. NO es el límite de autenticación (ese es el Origin widget-host). El inicio de sesión del agente emite SIN FIJAR.
widget_token.expires_atstring (date-time)no
widget_token.session_expires_atstring (date-time)no
widget_token.revoked_atstring (date-time) | nullno
widget_token.last_used_atstring (date-time) | nullnoReloj de higiene de rotación, con el mismo significado que ApiKey.last_used_at: la última vez que este token se resolvió CON ÉXITO (superadas todas las compuertas), escrito como mucho una vez por minuto por token, de modo que una lectura reciente puede ir retrasada hasta ese tiempo. null significa que no se ha resuelto con éxito desde que la columna adquirió un escritor en la ruta caliente — no que el token nunca se haya presentado. La renovación también lo marca.
widget_token.created_atstring (date-time)no
widget_token.updated_atstring (date-time)noFecha la FILA, no la emisión: el reloj de uso anterior y las escrituras del ciclo de vida (renovación, baja) lo mueven todos.

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 — WidgetRateLimited ​

El freno de escritura de tokens de widget rechazó esta petición (reintentable más tarde). code rate_limited. La emisión tiene límite por tenant; la renovación, por token. Retry-After es el tiempo que queda en la ventana fija.

json
{
  "error": {
    "code": "rate_limited",
    "message": "widget token mint rate limit exceeded; retry later"
  }
}

El contexto de la sesión de widget de quien llama ​

http
POST /v1/widget_tokens/introspect

Devuelve el tenant y el agente de la sesión ddw_ autenticada, sus orígenes permitidos (para la CSP del marco) y sus relojes de sesión. Se autentica con el propio ddw_; acotado al tenant, sin enumeración.

Respuestas

200 ​

El contexto vivo de la sesión de quien llama.

CampoTipoObligatorioDescripción
widget_sessionobject (WidgetSession)síLa vista de introspección con la que arranca un marco (su propia sesión viva).
widget_session.tenant_idstring (uuid)sí
widget_session.agent_idstring (uuid)sí
widget_session.originsarreglo de stringsíLos orígenes de INCRUSTACIÓN habilitados de la sesión (widget_origins) para la CSP / postMessage del marco; NO es el límite de autenticación (el Origin del anfitrión del widget).
widget_session.expires_atstring (date-time)sí
widget_session.session_expires_atstring (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"
  }
}

Emitir la credencial SIP efímera de quien llama ​

http
POST /v1/widget_tokens/sip_credential

Aprovisiona la credencial SIP EFÍMERA (agentcred_w) de la sesión ddw_ AUTENTICADA y la devuelve una sola vez, en memoria: el arranque del marco para registrarse por WSS (MT-CTI-07 fase 2).

Se autentica con el propio ddw_ y opera SOLO sobre la sesión de quien llama: el id del token sale del bearer, nunca de un valor de la ruta o del cuerpo, de modo que una sesión no puede emitir ni leer la de otra. La credencial es por TOKEN (w-<token_id>@t-<tenant>.<base>), nunca por extensión del agente, y vive en su propia htable y en su propio AOR de usrloc, por lo que revocarla no puede alcanzar la credencial del softphone del agente, ni al revés.

FAIL-CLOSED: si no se puede emitir la credencial, NO se devuelve NADA. No hay respaldo a agentcred, la credencial de 24 h del softphone del agente; un marco sin audio es el resultado previsto.

Idempotente por sesión: una nueva emisión SOBRESCRIBE la clave, así que la contraseña ANTERIOR de esa misma sesión deja de funcionar. Tiene límite de uso por token.

La password se devuelve EXACTAMENTE UNA VEZ y no se almacena en ningún lugar del lado del servidor: ni en Postgres, ni en una línea de log, ni en una fila de auditoría. El rastro de auditoría registra QUE se emitió una credencial, nunca CUÁL.

Respuestas

200 ​

El arranque, o sip: null cuando el carril SIP del widget no está armado en este entorno (WIDGET_SIP_ENABLED=false, o sin SBC configurado). null es un estado de DESPLIEGUE, no un fallo de quien llama: no se inventa ninguna credencial y el marco simplemente no tiene audio. Ramifica sobre ello en lugar de reintentar.

CampoTipoObligatorioDescripción
sipWidgetSipCredential | nullsí

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 — WidgetRateLimited ​

El freno de escritura de tokens de widget rechazó esta petición (reintentable más tarde). code rate_limited. La emisión tiene límite por tenant; la renovación, por token. Retry-After es el tiempo que queda en la ventana fija.

json
{
  "error": {
    "code": "rate_limited",
    "message": "widget token mint rate limit exceeded; retry later"
  }
}

503 — WidgetSipUnavailable ​

No se pudo aprovisionar la credencial SIP (code sbc_unavailable), así que no se devolvió NADA. FAIL-CLOSED y reintentable: no hay respaldo a la agentcred de larga duración del agente, porque entregar al marco una credencial que el servidor no pretendía conceder es peor que un marco sin audio.

json
{
  "error": {
    "code": "sbc_unavailable",
    "message": "widget sip provisioning unavailable, retry"
  }
}

Devolver la credencial SIP efímera de quien llama ​

http
DELETE /v1/widget_tokens/sip_credential

Borra la credencial agentcred_w de la sesión ddw_ AUTENTICADA y su registro usrloc, SIN terminar la sesión: el token sigue vivo y puede volver a emitir. Es lo que el marco llama al descargarse, al cerrar sesión o cuando el agente pasa a un teléfono de escritorio.

Su razón de ser es el residuo: sin él, el único desmontaje para una sesión que deja de usar audio es la caducidad automática de la htable o revocar el token entero, hasta 12 h de una credencial viva que nadie va a usar.

Idempotente, y llamarlo nunca es un error para una sesión que jamás encendió SIP. Acotado a la sesión de quien llama (el id del token sale del bearer), así que nunca puede alcanzar la credencial de una sesión hermana ni la agentcred del agente.

Respuestas

200 ​

El resultado del desmontaje. failed se informa en un 200 A PROPÓSITO (ADR #56 D3: un fallo del SBC se dice, no se traga): la sesión del marco no depende de que el desmontaje haya tenido éxito, y lo que quede se resuelve de todos modos con la caducidad automática de la htable o el barrido del tope de sesión. No reintentes en bucle ante él.

CampoTipoObligatorioDescripción
sip_teardownok · skipped · failedsíResultado de desmontar la credencial efímera de una sesión de WIDGET: el carril agentcred_w. Distinto de SipTeardown, que informa sobre la agentcred del agente: los dos carriles tienen htables y AOR separados precisamente para que uno nunca pueda alcanzar al otro, y informarlos con un solo esquema es como empiezan a leerse como uno. * ok: credencial y registro usrloc eliminados; este marco ya no puede registrarse. * skipped: no había nada que eliminar: el carril SIP del widget no está armado en este entorno, así que nunca se emitió ninguna credencial. * failed: falló el RPC al SBC y la credencial sigue viva hasta la caducidad automática de agentcred_w. Se registra y se emite como telemetría en lugar de tragarse. Se informa dentro de un 200 a propósito; no reintentes en bucle.

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"
  }
}

Listar los orígenes permitidos ​

http
GET /v1/widget_origins

Respuestas

200 ​

Los orígenes permitidos del tenant (habilitados y deshabilitados).

CampoTipoObligatorioDescripción
widget_originsarreglo de WidgetOriginsí
widget_origins[].idstring (uuid)no
widget_origins[].originstringnoOrigen https canónico (host en minúsculas, sin el :443 por defecto).
widget_origins[].labelstringno
widget_origins[].disabled_atstring (date-time) | nullnoNo nulo = deshabilitado (fuera de la lista de incrustación permitida: sin frame-ancestors/postMessage, nunca se muestra a un marco).
widget_origins[].created_atstring (date-time)no
widget_origins[].updated_atstring (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 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

429 — ApiKeyRateLimited ​

Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

Añadir un origen permitido ​

http
POST /v1/widget_origins

El origen en bruto se normaliza a la forma https canónica; un valor mal formado da 400.

Cuerpo de la petición (JSON, obligatorio)

CampoTipoObligatorioDescripción
originstringsíUn origen web, p. ej. https://crm.example.com.
labelstringno
json
{
  "origin": "https://crm.example.com"
}

Respuestas

201 ​

El origen añadido (forma canónica).

CampoTipoObligatorioDescripción
widget_originobject (WidgetOrigin)síUn origen web de la lista de INCRUSTACIÓN permitida por tenant (forma https canónica): gobierna quién puede enmarcar el widget (CSP frame-ancestors / postMessage); NO es el límite de autenticación (el Origin del anfitrión del widget).
widget_origin.idstring (uuid)no
widget_origin.originstringnoOrigen https canónico (host en minúsculas, sin el :443 por defecto).
widget_origin.labelstringno
widget_origin.disabled_atstring (date-time) | nullnoNo nulo = deshabilitado (fuera de la lista de incrustación permitida: sin frame-ancestors/postMessage, nunca se muestra a un marco).
widget_origin.created_atstring (date-time)no
widget_origin.updated_atstring (date-time)no

400 — BadRequest ​

Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).

json
{
  "error": {
    "code": "bad_request",
    "message": "from must be RFC-3339"
  }
}

401 — Unauthorized ​

Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.

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

403 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

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"
  }
}

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 (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

Deshabilitar un origen permitido ​

http
DELETE /v1/widget_origins/{id}

Deshabilitación suave (fuera de la lista de incrustación permitida: deja de enmarcar este CRM mediante frame-ancestors/postMessage; NO bloquea el inicio de sesión del agente, que se controla con el Origin del anfitrión del widget). Los orígenes nunca se borran.

Parámetros

NombreEnTipoObligatorioDescripción
idpathstring (uuid)síUUID del recurso. Los ids mal formados o de otro tenant se leen como 404.

Respuestas

200 ​

El origen deshabilitado.

CampoTipoObligatorioDescripción
widget_originobject (WidgetOrigin)síUn origen web de la lista de INCRUSTACIÓN permitida por tenant (forma https canónica): gobierna quién puede enmarcar el widget (CSP frame-ancestors / postMessage); NO es el límite de autenticación (el Origin del anfitrión del widget).
widget_origin.idstring (uuid)no
widget_origin.originstringnoOrigen https canónico (host en minúsculas, sin el :443 por defecto).
widget_origin.labelstringno
widget_origin.disabled_atstring (date-time) | nullnoNo nulo = deshabilitado (fuera de la lista de incrustación permitida: sin frame-ancestors/postMessage, nunca se muestra a un marco).
widget_origin.created_atstring (date-time)no
widget_origin.updated_atstring (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 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

404 — NotFound ​

Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).

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

429 — ApiKeyRateLimited ​

Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

Volver a habilitar un origen permitido ​

http
POST /v1/widget_origins/{id}/enable

Parámetros

NombreEnTipoObligatorioDescripción
idpathstring (uuid)síUUID del recurso. Los ids mal formados o de otro tenant se leen como 404.

Respuestas

200 ​

El origen vuelto a habilitar.

CampoTipoObligatorioDescripción
widget_originobject (WidgetOrigin)síUn origen web de la lista de INCRUSTACIÓN permitida por tenant (forma https canónica): gobierna quién puede enmarcar el widget (CSP frame-ancestors / postMessage); NO es el límite de autenticación (el Origin del anfitrión del widget).
widget_origin.idstring (uuid)no
widget_origin.originstringnoOrigen https canónico (host en minúsculas, sin el :443 por defecto).
widget_origin.labelstringno
widget_origin.disabled_atstring (date-time) | nullnoNo nulo = deshabilitado (fuera de la lista de incrustación permitida: sin frame-ancestors/postMessage, nunca se muestra a un marco).
widget_origin.created_atstring (date-time)no
widget_origin.updated_atstring (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 — Forbidden ​

El tenant está suspendido. Una sesión del dashboard (ddu_) de un tenant cuya política de inicio de sesión (ADR 227) está en modo enforce responde 403 con el código login_policy_denied ante una solicitud desde una dirección o en una hora que la política no permite — el mismo cuerpo en ambos casos; la sesión no se revoca y una solicitud posterior dentro de la política se procesa. Un token de widget (ddw_) de un puesto queda sujeto a la misma política en cada solicitud (core#2406, indicador widget_login_honors_policy). Un tenant sintético (demo) responde 403 con el código synthetic_tenant en toda ruta que llegaría a un tercero — marcación manual, pierna de transferencia externa o de conferencia, envío de SMS (core#2251, adenda del ADR #280). Ningún pago lo cambia.

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

404 — NotFound ​

Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).

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

429 — ApiKeyRateLimited ​

Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.

json
{
  "error": {
    "code": "rate_limited",
    "message": "API key request quota exceeded; retry after the interval in Retry-After"
  }
}

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