Skip to content

Email ​

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.

Direcciones de email de los deudores con su procedencia, el libro de supresiones (lectura) y el libro de emails (lectura).

Endpoints ​

MétodoRutaResumen
GET/v1/email/addressesLas direcciones de email de un contacto
POST/v1/email/addressesRegistrar la dirección de email de un deudor CON su procedencia
GET/v1/email/addresses/{id}Una dirección de email con su elegibilidad en el momento de la lectura
GET/v1/email/suppressionsEl historial de supresión de una dirección (solo lectura)
GET/v1/email/messagesConsulta del libro de emails (solo lectura)
GET/v1/email/messages/{id}Vista colapsada de un solo email

Las direcciones de email de un contacto ​

http
GET /v1/email/addresses

Parámetros

NombreEnTipoObligatorioDescripción
contact_idquerystring (uuid)sí

Respuestas

200 ​

Las direcciones del contacto, de la más antigua a la más reciente, cada una con su elegibilidad en el momento de la lectura.

CampoTipoObligatorioDescripción
email_addressesarreglo de EmailAddresssí
email_addresses[].idstring (uuid)sí
email_addresses[].contact_idstring (uuid)sí
email_addresses[].addressstringsí
email_addresses[].provenanceconsumer_replied · consumer_consent · creditor_notice · prior_collector · imported_unverifiedsí
email_addresses[].provenance_evidencestringno
email_addresses[].notice_sent_atstring (date-time) | nullno
email_addresses[].obtained_atstring (date-time)no
email_addresses[].domain_publicboolean | nullnoDerivado del dominio de la dirección; nunca viene de la entrada del cliente.
email_addresses[].sendablebooleansí
email_addresses[].ineligible_reasonprovenance_not_sendable · evidence_missing · notice_date_missing · notice_period_open · domain_not_public · suppressed · suppression_unreadable | nullsí
email_addresses[].created_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"
  }
}

429 — ApiKeyRateLimited ​

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

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

Registrar la dirección de email de un deudor CON su procedencia ​

http
POST /v1/email/addresses

Almacena una dirección de un contacto (contact_id) con la procedencia que la hace utilizable o no (12 CFR 1006.6(d)(4)): consumer_replied, consumer_consent, creditor_notice (necesita notice_sent_at; se puede enviar solo 35 días después y para un dominio de correo público) o prior_collector necesitan una provenance_evidence no vacía; imported_unverified se almacena pero NUNCA se puede enviar. sendable / ineligible_reason en la respuesta se calculan en la lectura (procedencia, plazo de aviso, libro de supresiones): ningún campo de la petición puede declarar enviable una dirección. La dirección se normaliza (recortada, en minúsculas); registrar la misma dirección dos veces para un contacto da 409, y un contacto desconocido 400. Requiere el alcance de tenant (una clave dd_ o un login de dashboard).

Cuerpo de la petición (JSON, obligatorio)

CampoTipoObligatorioDescripción
contact_idstring (uuid)sí
addressstring (email)sí
provenanceconsumer_replied · consumer_consent · creditor_notice · prior_collector · imported_unverifiedsí
provenance_evidencestringnoObligatorio (no vacío) para toda procedencia excepto imported_unverified.
notice_sent_atstring (date-time)noObligatorio para creditor_notice.
obtained_atstring (date-time)sí
json
{
  "contact_id": "00000000-0000-4000-8000-000000000001",
  "address": "[email protected]",
  "provenance": "consumer_consent",
  "provenance_evidence": "Written consent recorded in the account file",
  "obtained_at": "2026-10-01T12:00:00Z"
}

Respuestas

201 ​

La dirección registrada.

CampoTipoObligatorioDescripción
email_addressobject (EmailAddress)síLa dirección de email de un deudor con su procedencia. sendable se calcula al leer, nunca se almacena.
email_address.idstring (uuid)sí
email_address.contact_idstring (uuid)sí
email_address.addressstringsí
email_address.provenanceconsumer_replied · consumer_consent · creditor_notice · prior_collector · imported_unverifiedsí
email_address.provenance_evidencestringno
email_address.notice_sent_atstring (date-time) | nullno
email_address.obtained_atstring (date-time)no
email_address.domain_publicboolean | nullnoDerivado del dominio de la dirección; nunca viene de la entrada del cliente.
email_address.sendablebooleansí
email_address.ineligible_reasonprovenance_not_sendable · evidence_missing · notice_date_missing · notice_period_open · domain_not_public · suppressed · suppression_unreadable | nullsí
email_address.created_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"
  }
}

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

Una dirección de email con su elegibilidad en el momento de la lectura ​

http
GET /v1/email/addresses/{id}

Parámetros

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

Respuestas

200 ​

La dirección.

CampoTipoObligatorioDescripción
email_addressobject (EmailAddress)síLa dirección de email de un deudor con su procedencia. sendable se calcula al leer, nunca se almacena.
email_address.idstring (uuid)sí
email_address.contact_idstring (uuid)sí
email_address.addressstringsí
email_address.provenanceconsumer_replied · consumer_consent · creditor_notice · prior_collector · imported_unverifiedsí
email_address.provenance_evidencestringno
email_address.notice_sent_atstring (date-time) | nullno
email_address.obtained_atstring (date-time)no
email_address.domain_publicboolean | nullnoDerivado del dominio de la dirección; nunca viene de la entrada del cliente.
email_address.sendablebooleansí
email_address.ineligible_reasonprovenance_not_sendable · evidence_missing · notice_date_missing · notice_period_open · domain_not_public · suppressed · suppression_unreadable | nullsí
email_address.created_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"
  }
}

El historial de supresión de una dirección (solo lectura) ​

http
GET /v1/email/suppressions

El libro de supresiones de solo anexar de UNA dirección, las más recientes primero, más el status resultante («gana la última fila»: suppressed cuando la fila más reciente es un suppress, si no clear). No hay ruta de escritura: las supresiones las escriben las vías de baja / rebote / queja, y un lift necesita la procedencia propia del consumidor. El resumen de la dirección nunca se devuelve. Una address mal formada da 400.

Parámetros

NombreEnTipoObligatorioDescripción
addressquerystring (email)sí

Respuestas

200 ​

Las filas del libro de la dirección (100 como máximo) y su estado actual.

CampoTipoObligatorioDescripción
statussuppressed · clearsí
email_suppressionsarreglo de EmailSuppressionsí
email_suppressions[].idstring (uuid)no
email_suppressions[].seqintegernoPosición en el libro de la dirección; gana la más alta.
email_suppressions[].actionsuppress · liftno
email_suppressions[].reasonunsubscribe · hard_bounce · complaint · third_party · cease_communication | nullnoSe fija en las filas suppress.
email_suppressions[].provenanceconsumer_consent · consumer_replied | nullnoSe fija en las filas lift.
email_suppressions[].evidencestringno
email_suppressions[].occurred_atstring (date-time)no
email_suppressions[].recorded_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"
  }
}

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

Consulta del libro de emails (solo lectura) ​

http
GET /v1/email/messages

FILAS del libro (originales Y transiciones de estado; corrects_id las distingue), las más recientes primero, paginadas por keyset como /v1/sms/messages. En las listas, los cuerpos son vistas previas de 40 caracteres. El envío no forma parte de esta superficie: pasa por el Sender con compuertas (campaña send_email), nunca por una ruta.

Parámetros

NombreEnTipoObligatorioDescripción
directionqueryoutbound · inboundno
statusqueryqueued · sent · delivered · deferred · bounced · complained · failed · receivedno
campaign_idquerystring (uuid)no
debt_idquerystring (uuid)no
limitqueryintegernoTamaño de página (por defecto 100, máximo 1000).
cursorquerystringnoCursor keyset opaco del next_cursor de la página anterior.

Respuestas

200 ​

Una página de filas del libro mayor.

CampoTipoObligatorioDescripción
email_messagesarreglo de EmailMessagesí
email_messages[].idstring (uuid)no
email_messages[].directionoutbound · inboundno
email_messages[].statusqueued · sent · delivered · deferred · bounced · complained · failed · receivedno
email_messages[].from_addressstring | nullno
email_messages[].to_addressstringno
email_messages[].subjectstring | nullno
email_messages[].body_previewstring | nullno
email_messages[].template_version_idstring (uuid) | nullno
email_messages[].regionstringno
email_messages[].client_refstringno
email_messages[].provider_idstring (uuid) | nullno
email_messages[].provider_message_idstringno
email_messages[].campaign_idstring (uuid) | nullno
email_messages[].debt_idstring (uuid) | nullno
email_messages[].contact_idstring (uuid) | nullno
email_messages[].occurred_atstring (date-time)no
email_messages[].corrects_idstring (uuid) | nullno
email_messages[].recorded_atstring (date-time)no
next_cursorstring | nullsí

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

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

Vista colapsada de un solo email ​

http
GET /v1/email/messages/{id}

La identidad del original + el estado VIGENTE, los timestamps por estado, el compliance_snapshot congelado, el subject/body completos y las filas de transitions en orden.

Parámetros

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

Respuestas

200 ​

La vista colapsada.

CampoTipoObligatorioDescripción
email_messageobject (EmailMessageView)síLa vista COLAPSADA de un solo email: estado vigente, marcas de tiempo por estado, instantánea de cumplimiento congelada, asunto/cuerpo COMPLETOS, transiciones en orden.
email_message.idstring (uuid)no
email_message.directionoutbound · inboundno
email_message.statusqueued · sent · delivered · deferred · bounced · complained · failed · receivedno
email_message.from_addressstring | nullno
email_message.to_addressstringno
email_message.subjectstring | nullno
email_message.bodystring | nullno
email_message.template_version_idstring (uuid) | nullno
email_message.regionstringno
email_message.client_refstringno
email_message.provider_idstring (uuid) | nullno
email_message.provider_message_idstringno
email_message.campaign_idstring (uuid) | nullno
email_message.debt_idstring (uuid) | nullno
email_message.contact_idstring (uuid) | nullno
email_message.compliance_snapshotobject | nullno
email_message.occurred_atstring (date-time)no
email_message.timestampsobjectnoMarcas de tiempo por estado (p. ej. queued, sent, delivered).
email_message.transitionsarreglo de EmailMessageno
email_message.transitions[].idstring (uuid)no
email_message.transitions[].directionoutbound · inboundno
email_message.transitions[].statusqueued · sent · delivered · deferred · bounced · complained · failed · receivedno
email_message.transitions[].from_addressstring | nullno
email_message.transitions[].to_addressstringno
email_message.transitions[].subjectstring | nullno
email_message.transitions[].body_previewstring | nullno
email_message.transitions[].template_version_idstring (uuid) | nullno
email_message.transitions[].regionstringno
email_message.transitions[].client_refstringno
email_message.transitions[].provider_idstring (uuid) | nullno
email_message.transitions[].provider_message_idstringno
email_message.transitions[].campaign_idstring (uuid) | nullno
email_message.transitions[].debt_idstring (uuid) | nullno
email_message.transitions[].contact_idstring (uuid) | nullno
email_message.transitions[].occurred_atstring (date-time)no
email_message.transitions[].corrects_idstring (uuid) | nullno
email_message.transitions[].recorded_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.