Appearance
Rutas entrantes
Generado desde
DialerDigital/corecommit0fc18008b3c8— especificaciónopenapi/dialer-v1.yamlv0.134.0. No se edita a mano; consulta Cómo se construye esta referencia. Descargar la especificación OpenAPI.
Traducción en curso
Esta referencia se genera desde la especificación OpenAPI. Las cadenas que todavía no tienen traducción aparecen en inglés.
Enrutamiento de DID entrantes + aprovisionamiento del SBC.
Endpoints
| Método | Ruta | Resumen |
|---|---|---|
GET | /v1/inbound-routes | Listar las rutas entrantes |
POST | /v1/inbound-routes | Crear una ruta entrante |
GET | /v1/inbound-routes/{id} | Obtener una ruta entrante |
PATCH | /v1/inbound-routes/{id} | Actualizar una ruta entrante (e164 inmutable) |
POST | /v1/inbound-routes/{id}/provision | Empujar la ruta al borde SIP |
POST | /v1/inbound-routes/{id}/disable | Deshabilitar una ruta entrante |
Listar las rutas entrantes
http
GET /v1/inbound-routesRespuestas
200
Las rutas entrantes del tenant.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
inbound_routes | arreglo de InboundRoute | sí | |
inbound_routes[].id | string (uuid) | no | |
inbound_routes[].tenant_id | string (uuid) | no | |
inbound_routes[].e164 | string | no | Inmutable tras la creación. |
inbound_routes[].dest_type | agent · queue · ivr · optout · ai_agent | no | ivr ejecuta el menú IVR entrante que nombra dest_ref (core#1319). Una ruta guardada antes de core#1311 sin menú se sigue rechazando al conectar con CALL_REJECTED. optout es el número de baja (core#1316): el número que llama se añade a la lista de no llamar propia del tenant al conectar y FreeSWITCH confirma y cuelga; una ruta así siempre lee dest_ref: null, recording: false, ai_enabled: false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
inbound_routes[].dest_ref | string | null | no | |
inbound_routes[].queue_id | string,null (uuid) | no | La cola de una ruta queue (core#1347); null en cualquier otro tipo, y en una ruta queue guardada sin ella. |
inbound_routes[].ai_agent_id | string,null (uuid) | no | El agente de IA de una ruta ai_agent (core#1547); null en cualquier otro tipo. |
inbound_routes[].hours | InboundRouteHours | null | no | El horario de la ruta (core#2530), o null cuando contesta a todas horas. Un mensaje closed se lee de vuelta como el texto que se envió. |
inbound_routes[].recording | boolean | no | |
inbound_routes[].ai_enabled | boolean | no | true si y solo si dest_type es ai_agent (derivado, ADR #200); false en cualquier otro tipo. Una escritura que nombre lo contrario da 400 (ADR #148). Las rutas que tenían true antes de que se rechazara el indicador se apagaron con una migración de datos. |
inbound_routes[].status | active · disabled | no | |
inbound_routes[].notes | string | null | no | |
inbound_routes[].created_at | string (date-time) | no | |
inbound_routes[].updated_at | string (date-time) | no |
401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}Crear una ruta entrante
http
POST /v1/inbound-routese164 es inmutable tras la creación; el router inyecta tenant_id.
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
e164 | string | sí | E.164 (inmutable tras la creación). Debe ser un número de ESTA cuenta (uno registrado con /v1/dids, o un número house asignado a ella, core#2414): un número que es de otra cuenta o que nadie registró da 422 unprocessable (e164 not a number of this account). Un PATCH que devuelve una ruta a active se juzga igual; una ruta que ya existe nunca se vuelve a juzgar. |
dest_type | agent · queue · ivr · optout · ai_agent | sí | ivr ejecuta uno de los menús IVR entrantes del tenant (core#1319): dest_ref es OBLIGATORIO y debe ser el id de un menú publicado con /v1/inbound-ivr-menus en esta cuenta y no retirado, o la escritura da 400 invalid. Cada llamada oye la versión del menú vigente cuando se conecta; FreeSWITCH la contesta tras el veredicto del plan, core reproduce los avisos de voz, y la tecla (o, tras dos ventanas de silencio, el default del menú) la envía a una cola, un agente, la baja o un colgado. optout es el número de baja (core#1316, 47 CFR 64.1200(b)(3)): el número que llama se añade a la lista de no llamar propia del tenant cuando la llamada se conecta, antes de que conteste nada y sea cual sea el plan del tenant; con un plan activo, FreeSWITCH reproduce entonces una confirmación compuesta por la plataforma que nombra al vendedor del tenant (o un tono) y cuelga, con un plan apagado la llamada se rechaza sin contestar. Un llamante sin número utilizable (oculto o no válido) se rechaza y no se registra nada. Una ruta optout es desnuda: un dest_ref no nulo, recording: true o ai_enabled: true en la misma escritura se rechazan con 400 invalid; si se omiten, se fijan en ninguno/false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
dest_ref | string (uuid) | no | Obligatorio para agent (el id del agente) y para ivr (el id de un menú IVR entrante publicado y no retirado de esta cuenta, si no 400 invalid); un valor no nulo se rechaza en una ruta optout. Un valor que no es un UUID canónico se rechaza con 400 invalid (dest_ref must be a UUID, core#1338). |
queue_id | string (uuid) | no | La cola de una ruta queue (core#1347) o la cola de respaldo de una ruta ai_agent (core#1547): una cola ACTIVA de esta cuenta creada con /v1/inbound-queues; una retirada, de otra cuenta, inexistente o un id mal formado da 400 invalid. OBLIGATORIA en una ruta ai_agent (core#1547): la cola a la que recurre la llamada, sujeta a la misma regla. Se rechaza en cualquier otro dest_type. Opcional en una ruta queue: sin ella una ruta queue se acepta, como antes, y rechaza sus llamadas al conectar. Un PATCH que mueve la ruta a otro tipo sin nombrarla la elimina. |
ai_agent_id | string (uuid) | no | OBLIGATORIO en una ruta ai_agent (core#1547, ADR #200): el id de un agente de IA live de esta cuenta, creado con /v1/ai/agents; uno en borrador, en pausa o retirado, de otra cuenta, inexistente o un id mal formado da 400 invalid. Se rechaza en cualquier otro dest_type; un PATCH que mueve la ruta a otro tipo sin nombrarlo lo elimina. El agente se juzga EN LA ESCRITURA (un PATCH que apunta la ruta a un agente o la devuelve a active): ponerlo en pausa después no toca la ruta, y retirarlo mientras una ruta activa lo nombra da 409 en PATCH /v1/ai/agents/{id} y DELETE /v1/ai/agents/{id}. |
hours | InboundRouteHours | null | no | El horario de la ruta (core#2530, ADR #304). Ausente o null = el número contesta a todas horas, exactamente como antes; en un PATCH, null ELIMINA el horario y omitir la clave lo conserva. Fuera del horario, o en un festivo, una llamada NUEVA se trata como indica la ruta closed (un mensaje u otro destino); una llamada ya admitida nunca se corta cuando pasa la hora de cierre. Una ruta optout no tiene horario: enviarlo con dest_type: optout, o mover una ruta que lo tiene a optout sin hours: null en la misma escritura, da 422. Una zona que no se resuelve, un festivo mal formado o repetido, más de 366 festivos, un closed que no es exactamente una de sus dos formas, o uno que nombra una cola, menú, agente o agente de IA que no está vivo en esta cuenta da 422 unprocessable. El mensaje closed se convierte en audio cuando se guarda el horario; si no se puede, la escritura da 503 prompt_render_failed y no se guarda nada. Una ruta con horario se aprovisiona anclada en FreeSWITCH (de otro modo, una ruta agent sin recording se entrega directamente al agente y core nunca ve la llamada): tras escribir el horario, haz POST /v1/inbound-routes/{id}/provision para que el borde SIP lo conozca. |
recording | boolean | no | true se rechaza en una ruta optout y en una ruta ai_agent (el tramo de IA no se graba, ADR #200); si se omite ahí, es false. Por defecto true en cualquier otra ruta. |
ai_enabled | boolean | no | Derivado del destino, no elegido (ADR #148, ADR #200): true si y solo si dest_type es ai_agent. Nombrar true en cualquier otro destino, o false en una ruta ai_agent, da 400 invalid (ai_enabled is derived from the destination ...); omítelo, o envía el valor que implica el destino (por defecto false). |
notes | string | no |
json
{
"e164": "+13125550171",
"dest_type": "queue"
}Respuestas
201
Ruta creada.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
inbound_route | object (InboundRoute) | sí | |
inbound_route.id | string (uuid) | no | |
inbound_route.tenant_id | string (uuid) | no | |
inbound_route.e164 | string | no | Inmutable tras la creación. |
inbound_route.dest_type | agent · queue · ivr · optout · ai_agent | no | ivr ejecuta el menú IVR entrante que nombra dest_ref (core#1319). Una ruta guardada antes de core#1311 sin menú se sigue rechazando al conectar con CALL_REJECTED. optout es el número de baja (core#1316): el número que llama se añade a la lista de no llamar propia del tenant al conectar y FreeSWITCH confirma y cuelga; una ruta así siempre lee dest_ref: null, recording: false, ai_enabled: false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
inbound_route.dest_ref | string | null | no | |
inbound_route.queue_id | string,null (uuid) | no | La cola de una ruta queue (core#1347); null en cualquier otro tipo, y en una ruta queue guardada sin ella. |
inbound_route.ai_agent_id | string,null (uuid) | no | El agente de IA de una ruta ai_agent (core#1547); null en cualquier otro tipo. |
inbound_route.hours | InboundRouteHours | null | no | El horario de la ruta (core#2530), o null cuando contesta a todas horas. Un mensaje closed se lee de vuelta como el texto que se envió. |
inbound_route.recording | boolean | no | |
inbound_route.ai_enabled | boolean | no | true si y solo si dest_type es ai_agent (derivado, ADR #200); false en cualquier otro tipo. Una escritura que nombre lo contrario da 400 (ADR #148). Las rutas que tenían true antes de que se rechazara el indicador se apagaron con una migración de datos. |
inbound_route.status | active · disabled | no | |
inbound_route.notes | string | null | no | |
inbound_route.created_at | string (date-time) | no | |
inbound_route.updated_at | string (date-time) | no |
400 — BadRequest
Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).
json
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}409 — Conflict
Transición de estado no válida, conflicto de unicidad, o un asiento que está ocupado/reservado.
json
{
"error": {
"code": "conflict",
"message": "invalid state transition"
}
}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"
}
}503
El mensaje closed del horario no se pudo convertir en audio (prompt_render_failed); la ruta no se guardó. La petición es correcta y puede funcionar cuando responda el texto a voz.
Obtener una ruta entrante
http
GET /v1/inbound-routes/{id}Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | UUID del recurso. Los ids mal formados o de otro tenant se leen como 404. |
Respuestas
200
La ruta.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
inbound_route | object (InboundRoute) | sí | |
inbound_route.id | string (uuid) | no | |
inbound_route.tenant_id | string (uuid) | no | |
inbound_route.e164 | string | no | Inmutable tras la creación. |
inbound_route.dest_type | agent · queue · ivr · optout · ai_agent | no | ivr ejecuta el menú IVR entrante que nombra dest_ref (core#1319). Una ruta guardada antes de core#1311 sin menú se sigue rechazando al conectar con CALL_REJECTED. optout es el número de baja (core#1316): el número que llama se añade a la lista de no llamar propia del tenant al conectar y FreeSWITCH confirma y cuelga; una ruta así siempre lee dest_ref: null, recording: false, ai_enabled: false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
inbound_route.dest_ref | string | null | no | |
inbound_route.queue_id | string,null (uuid) | no | La cola de una ruta queue (core#1347); null en cualquier otro tipo, y en una ruta queue guardada sin ella. |
inbound_route.ai_agent_id | string,null (uuid) | no | El agente de IA de una ruta ai_agent (core#1547); null en cualquier otro tipo. |
inbound_route.hours | InboundRouteHours | null | no | El horario de la ruta (core#2530), o null cuando contesta a todas horas. Un mensaje closed se lee de vuelta como el texto que se envió. |
inbound_route.recording | boolean | no | |
inbound_route.ai_enabled | boolean | no | true si y solo si dest_type es ai_agent (derivado, ADR #200); false en cualquier otro tipo. Una escritura que nombre lo contrario da 400 (ADR #148). Las rutas que tenían true antes de que se rechazara el indicador se apagaron con una migración de datos. |
inbound_route.status | active · disabled | no | |
inbound_route.notes | string | null | no | |
inbound_route.created_at | string (date-time) | no | |
inbound_route.updated_at | string (date-time) | no |
401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (core#2503) (code rate_limited). La petición no se procesó. Espera Retry-After segundos y reintenta; un rechazo no cuenta contra el presupuesto, así que esa espera siempre basta. Acotado por clave de API y, por encima de las claves, por tenant (api_tenant_requests_per_minute): una clave hermana no se ve afectada hasta que las claves del tenant en conjunto alcanzan ese techo. La cuota se aplica a toda operación alcanzable con una clave dd_, así que las operaciones que nombran un 429 más específico (control de llamadas, disposiciones, SMS, …) PUEDEN responder TAMBIÉN este, con sus cabeceras X-RateLimit-*.
json
{
"error": {
"code": "rate_limited",
"message": "API key request quota exceeded; retry after the interval in Retry-After"
}
}Actualizar una ruta entrante (e164 inmutable)
http
PATCH /v1/inbound-routes/{id}Parámetros
| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id | path | string (uuid) | sí | UUID del recurso. Los ids mal formados o de otro tenant se leen como 404. |
Cuerpo de la petición (JSON, obligatorio)
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
dest_type | agent · queue · ivr · optout · ai_agent | no | ivr ejecuta uno de los menús IVR entrantes del tenant (core#1319): dest_ref es OBLIGATORIO y debe ser el id de un menú publicado con /v1/inbound-ivr-menus en esta cuenta y no retirado, o la escritura da 400 invalid. Cada llamada oye la versión del menú vigente cuando se conecta; FreeSWITCH la contesta tras el veredicto del plan, core reproduce los avisos de voz, y la tecla (o, tras dos ventanas de silencio, el default del menú) la envía a una cola, un agente, la baja o un colgado. optout es el número de baja (core#1316, 47 CFR 64.1200(b)(3)): el número que llama se añade a la lista de no llamar propia del tenant cuando la llamada se conecta, antes de que conteste nada y sea cual sea el plan del tenant; con un plan activo, FreeSWITCH reproduce entonces una confirmación compuesta por la plataforma que nombra al vendedor del tenant (o un tono) y cuelga, con un plan apagado la llamada se rechaza sin contestar. Un llamante sin número utilizable (oculto o no válido) se rechaza y no se registra nada. Una ruta optout es desnuda: un dest_ref no nulo, recording: true o ai_enabled: true en la misma escritura se rechazan con 400 invalid; si se omiten, se fijan en ninguno/false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
dest_ref | string (uuid) | no | Obligatorio para agent (el id del agente) y para ivr (el id de un menú IVR entrante publicado y no retirado de esta cuenta, si no 400 invalid); un valor no nulo se rechaza en una ruta optout. Un valor que no es un UUID canónico se rechaza con 400 invalid (dest_ref must be a UUID, core#1338). |
queue_id | string (uuid) | no | La cola de una ruta queue (core#1347) o la cola de respaldo de una ruta ai_agent (core#1547): una cola ACTIVA de esta cuenta creada con /v1/inbound-queues; una retirada, de otra cuenta, inexistente o un id mal formado da 400 invalid. OBLIGATORIA en una ruta ai_agent (core#1547): la cola a la que recurre la llamada, sujeta a la misma regla. Se rechaza en cualquier otro dest_type. Opcional en una ruta queue: sin ella una ruta queue se acepta, como antes, y rechaza sus llamadas al conectar. Un PATCH que mueve la ruta a otro tipo sin nombrarla la elimina. |
ai_agent_id | string (uuid) | no | OBLIGATORIO en una ruta ai_agent (core#1547, ADR #200): el id de un agente de IA live de esta cuenta, creado con /v1/ai/agents; uno en borrador, en pausa o retirado, de otra cuenta, inexistente o un id mal formado da 400 invalid. Se rechaza en cualquier otro dest_type; un PATCH que mueve la ruta a otro tipo sin nombrarlo lo elimina. El agente se juzga EN LA ESCRITURA (un PATCH que apunta la ruta a un agente o la devuelve a active): ponerlo en pausa después no toca la ruta, y retirarlo mientras una ruta activa lo nombra da 409 en PATCH /v1/ai/agents/{id} y DELETE /v1/ai/agents/{id}. |
hours | InboundRouteHours | null | no | El horario de la ruta (core#2530, ADR #304). Ausente o null = el número contesta a todas horas, exactamente como antes; en un PATCH, null ELIMINA el horario y omitir la clave lo conserva. Fuera del horario, o en un festivo, una llamada NUEVA se trata como indica la ruta closed (un mensaje u otro destino); una llamada ya admitida nunca se corta cuando pasa la hora de cierre. Una ruta optout no tiene horario: enviarlo con dest_type: optout, o mover una ruta que lo tiene a optout sin hours: null en la misma escritura, da 422. Una zona que no se resuelve, un festivo mal formado o repetido, más de 366 festivos, un closed que no es exactamente una de sus dos formas, o uno que nombra una cola, menú, agente o agente de IA que no está vivo en esta cuenta da 422 unprocessable. El mensaje closed se convierte en audio cuando se guarda el horario; si no se puede, la escritura da 503 prompt_render_failed y no se guarda nada. Una ruta con horario se aprovisiona anclada en FreeSWITCH (de otro modo, una ruta agent sin recording se entrega directamente al agente y core nunca ve la llamada): tras escribir el horario, haz POST /v1/inbound-routes/{id}/provision para que el borde SIP lo conozca. |
recording | boolean | no | true se rechaza en una ruta optout y en una ruta ai_agent (el tramo de IA no se graba, ADR #200); si se omite ahí, es false. Por defecto true en cualquier otra ruta. |
ai_enabled | boolean | no | Derivado del destino, no elegido (ADR #148, ADR #200): true si y solo si dest_type es ai_agent. Nombrar true en cualquier otro destino, o false en una ruta ai_agent, da 400 invalid (ai_enabled is derived from the destination ...); omítelo, o envía el valor que implica el destino (por defecto false). |
status | active · disabled | no | |
notes | string | no |
json
{
"recording": false
}Respuestas
200
Ruta actualizada.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
inbound_route | object (InboundRoute) | sí | |
inbound_route.id | string (uuid) | no | |
inbound_route.tenant_id | string (uuid) | no | |
inbound_route.e164 | string | no | Inmutable tras la creación. |
inbound_route.dest_type | agent · queue · ivr · optout · ai_agent | no | ivr ejecuta el menú IVR entrante que nombra dest_ref (core#1319). Una ruta guardada antes de core#1311 sin menú se sigue rechazando al conectar con CALL_REJECTED. optout es el número de baja (core#1316): el número que llama se añade a la lista de no llamar propia del tenant al conectar y FreeSWITCH confirma y cuelga; una ruta así siempre lee dest_ref: null, recording: false, ai_enabled: false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
inbound_route.dest_ref | string | null | no | |
inbound_route.queue_id | string,null (uuid) | no | La cola de una ruta queue (core#1347); null en cualquier otro tipo, y en una ruta queue guardada sin ella. |
inbound_route.ai_agent_id | string,null (uuid) | no | El agente de IA de una ruta ai_agent (core#1547); null en cualquier otro tipo. |
inbound_route.hours | InboundRouteHours | null | no | El horario de la ruta (core#2530), o null cuando contesta a todas horas. Un mensaje closed se lee de vuelta como el texto que se envió. |
inbound_route.recording | boolean | no | |
inbound_route.ai_enabled | boolean | no | true si y solo si dest_type es ai_agent (derivado, ADR #200); false en cualquier otro tipo. Una escritura que nombre lo contrario da 400 (ADR #148). Las rutas que tenían true antes de que se rechazara el indicador se apagaron con una migración de datos. |
inbound_route.status | active · disabled | no | |
inbound_route.notes | string | null | no | |
inbound_route.created_at | string (date-time) | no | |
inbound_route.updated_at | string (date-time) | no |
400 — BadRequest
Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).
json
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}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"
}
}503
El mensaje closed del horario no se pudo convertir en audio (prompt_render_failed); la ruta no se guardó. La petición es correcta y puede funcionar cuando responda el texto a voz.
Empujar la ruta al borde SIP
http
POST /v1/inbound-routes/{id}/provision409 cuando la ruta está deshabilitada; 422 cuando el agente de destino no se puede resolver para esta sede o no tiene extensión SIP (puesto) a la que entregar; 200 {"status": "sbc_disabled"} cuando no hay KAMAILIO_RPC_URL configurada.
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
Aprovisionada (o SBC deshabilitado en este entorno).
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
status | provisioned · sbc_disabled | sí | sbc_disabled = no hay KAMAILIO_RPC_URL en este entorno; la intención de la fila queda registrada, no empujada. |
401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}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"
}
}502 — SbcError
El borde SIP rechazó la petición de aprovisionamiento.
json
{
"error": {
"code": "sbc_error",
"message": "the SIP edge rejected the provisioning request"
}
}Deshabilitar una ruta entrante
http
POST /v1/inbound-routes/{id}/disablePará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 ruta deshabilitada.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
inbound_route | object (InboundRoute) | sí | |
inbound_route.id | string (uuid) | no | |
inbound_route.tenant_id | string (uuid) | no | |
inbound_route.e164 | string | no | Inmutable tras la creación. |
inbound_route.dest_type | agent · queue · ivr · optout · ai_agent | no | ivr ejecuta el menú IVR entrante que nombra dest_ref (core#1319). Una ruta guardada antes de core#1311 sin menú se sigue rechazando al conectar con CALL_REJECTED. optout es el número de baja (core#1316): el número que llama se añade a la lista de no llamar propia del tenant al conectar y FreeSWITCH confirma y cuelga; una ruta así siempre lee dest_ref: null, recording: false, ai_enabled: false. agent puentea directamente al agente registrado; queue ancla el tramo en FreeSWITCH. Hoy la imagen de FreeSWITCH de producción no incluye extensiones de cola (ADR #104 D13: el corral de aparcamiento y dd_queue_hold son una dependencia pendiente de freeswitch, aún no entregada), así que FreeSWITCH cuelga un tramo de cola como UNALLOCATED_NUMBER sea cual sea el indicador. Cuando se entreguen: con el indicador inbound_queue_stream_enabled del tenant ACTIVADO y su agent_session_journal_enabled también ACTIVADO (core#1354: con el diario de puestos APAGADO la llamada se rechaza sin contestar, ya que no habría agente al que ofrecérsela), core admite la llamada en la cola de la ruta (enqueued), la extensión contesta con un tono generado, el propietario la ofrece al agente Ready más antiguo y la puentea (MT-CTI-17 FASE 3); con el indicador APAGADO (por defecto): el tramo termina sin contestar en el corral. ai_agent nombra un agente de IA de voz de la cuenta (core#1547, ADR #200): ai_agent_id (un agente live de esta cuenta) y queue_id (la cola activa a la que recurre la llamada) son OBLIGATORIOS, o la escritura da 400 invalid; ai_enabled lee true y recording false, ambos derivados del tipo, no elegidos. La admisión se decide antes de contestar la llamada (core#1548, ADR #200 decisión 3): con el indicador inbound_ai_enabled del tenant apagado (por defecto) o si falla cualquiera de sus comprobaciones, la llamada se trata como una llamada a la cola queue_id y no la contesta la IA; el motivo queda registrado en la evidencia del CDR de la llamada (compliance_snapshot.inbound_ai). Todavía nada entrega una llamada al agente (la bifurcación es una entrega posterior del ADR #200), así que una llamada a este número no la contesta la IA. |
inbound_route.dest_ref | string | null | no | |
inbound_route.queue_id | string,null (uuid) | no | La cola de una ruta queue (core#1347); null en cualquier otro tipo, y en una ruta queue guardada sin ella. |
inbound_route.ai_agent_id | string,null (uuid) | no | El agente de IA de una ruta ai_agent (core#1547); null en cualquier otro tipo. |
inbound_route.hours | InboundRouteHours | null | no | El horario de la ruta (core#2530), o null cuando contesta a todas horas. Un mensaje closed se lee de vuelta como el texto que se envió. |
inbound_route.recording | boolean | no | |
inbound_route.ai_enabled | boolean | no | true si y solo si dest_type es ai_agent (derivado, ADR #200); false en cualquier otro tipo. Una escritura que nombre lo contrario da 400 (ADR #148). Las rutas que tenían true antes de que se rechazara el indicador se apagaron con una migración de datos. |
inbound_route.status | active · disabled | no | |
inbound_route.notes | string | null | no | |
inbound_route.created_at | string (date-time) | no | |
inbound_route.updated_at | string (date-time) | no |
400 — BadRequest
Petición mal formada (errores de forma/tipo, filtros no válidos, marcas de tiempo erróneas).
json
{
"error": {
"code": "bad_request",
"message": "from must be RFC-3339"
}
}401 — Unauthorized
Clave de API ausente, desconocida o revocada (o, en /v1/admin/*, un token de administración incorrecto o sin definir; en webhooks, una firma incorrecta o ausente). Una sesión del dashboard (ddu_) que un inicio de sesión más reciente de la misma persona haya cerrado responde en cambio con el código session_superseded (indicador de tenant single_session_enforced), para que la pantalla pueda explicar por qué se cerró la sesión; un cierre de sesión, un token vencido o uno desconocido siguen siendo unauthorized.
json
{
"error": {
"code": "unauthorized",
"message": "invalid or revoked API key"
}
}404 — NotFound
Id desconocido, mal formado (no UUID) O id de otro tenant: RLS devuelve cero filas, así que los tres son indistinguibles por diseño (sin fuga de existencia, nunca un 403 para ids ajenos).
json
{
"error": {
"code": "not_found",
"message": "resource not found for this tenant"
}
}429 — ApiKeyRateLimited
Esta clave de API ha superado su cuota de peticiones, o las claves del tenant en conjunto han superado el techo del tenant (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"
}
}