AtendyDocumentación Ir al panel

Llamadas salientes (API)

Referencia del endpoint POST /api/v1/calls para lanzar llamadas salientes desde tu código, n8n u otra herramienta.

Llamadas salientes (API)

Esta es la API pública de Atendy para desarrolladores. Con una sola petición HTTP puedes pedirle a la plataforma que llame por teléfono a un número usando uno de tus agentes. Es ideal para conectar Atendy con tus propias aplicaciones o con herramientas de automatización como n8n: cuando ocurre algo en tu sistema (una nueva reserva, un pedido, un aviso), disparas una llamada automática.

El uso de la API requiere el plan Escala. Con planes inferiores la petición se rechazará con un error 403.

Autenticación

Todas las peticiones se autentican con una clave de API que empieza por sk_live_. La creas en la sección Llamadas salientes del panel, en el apartado de claves de API. La clave se muestra completa una sola vez al crearla, así que guárdala en un lugar seguro. Se envía en cada petición mediante la cabecera x-api-key. Cada llamada lanzada con tu clave se factura a la cuenta dueña de esa clave, así que trátala como una contraseña y no la publiques en código del lado del cliente.

Método y URL

POST https://atendy.es/api/v1/calls

Cabeceras

CabeceraValor
Content-Typeapplication/json
x-api-keysk_live_... (tu clave de API). Como alternativa puedes enviarla en Authorization: Bearer sk_live_...
Idempotency-KeyOpcional. Identificador único que tú eliges para esta llamada. Si repites la petición con la misma clave, se te devuelve la respuesta de la primera en lugar de llamar otra vez. Ver el apartado Evitar llamadas duplicadas.

Cuerpo de la petición

El cuerpo es un objeto JSON con los siguientes campos:

CampoTipoObligatorioDescripción
agent_idtexto (UUID)Identificador del agente que hará la llamada. Lo encuentras en la ficha del agente, dentro de la sección Agentes.
totextoNúmero de destino, la persona a la que llamará el agente. Usa siempre formato internacional (+34600000000). Se admiten espacios, guiones, puntos y paréntesis, que se eliminan antes de marcar. El + es técnicamente opcional, pero sin prefijo de país tu operadora puede no saber enrutar la llamada, así que no lo omitas.
fromtextoNoSirve para elegir CON QUÉ NÚMERO TUYO se marca, cuando tienes varios asignados al mismo agente: se usa la línea que coincida exactamente con este valor. Si lo omites, se usa la primera línea de salida disponible de ese agente. Importante: este campo NO cambia el número que ve el destinatario en su pantalla; ese identificador lo impone la línea SIP de tu operadora.
varsobjeto JSONNoPares clave-valor que se inyectan en el prompt y el saludo del agente como {{variables}}. Útil para personalizar cada llamada (nombre del cliente, número de pedido, importe, etc.).

Ejemplo de petición (cURL)

curl -X POST https://atendy.es/api/v1/calls \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk_live_tu_clave_aqui" \
  -d '{
    "agent_id": "1a2b3c4d-0000-0000-0000-000000000000",
    "to": "+34600000000",
    "from": "+34910000000",
    "vars": {
      "nombre": "Ana",
      "pedido": "12345"
    }
  }'

Respuesta correcta (200)

Si la llamada se acepta y empieza a marcarse, recibes un código 200 con un cuerpo JSON como este:

{
  "call_id": "call-out-4f3a9c2b1d7e",
  "room": "call-out-4f3a9c2b1d7e",
  "status": "dialing"
}
CampoDescripción
call_idIdentificador único de la llamada, con el formato call-out- seguido de 12 caracteres. Guárdalo: es el mismo valor que usarás para consultar el estado y el que llegará en el webhook de fin de llamada, así que es la forma de relacionar tu petición con su resultado.
roomIdentificador interno de la sesión. Hoy su valor es idéntico al de call_id; se mantiene por compatibilidad. Usa call_id.
statusEstado inicial. dialing significa que la llamada se está marcando.
El estado dialing indica que la llamada se ha lanzado, no que la persona haya contestado. Para saber cómo acabó tienes tres vías: consultar el estado con GET /api/v1/calls/{call_id}, recibir el webhook de fin de llamada, o mirarlo en la analítica del panel.

Evitar llamadas duplicadas (Idempotency-Key)

Cada petición aceptada llama por teléfono a una persona real y consume minutos de tu plan. Si tu sistema reintenta automáticamente cuando una petición tarda o da timeout, sin más precauciones esa persona recibiría dos llamadas. Para evitarlo, envía la cabecera Idempotency-Key con un identificador único de esa llamada: si repites la petición con la misma clave y los mismos datos, Atendy te devuelve la respuesta de la primera sin volver a marcar.

Usa un valor que identifique el hecho de negocio, no el intento: por ejemplo el identificador del pedido, del aviso o de la fila de tu base de datos. Debe tener entre 8 y 255 caracteres y admite letras, números, punto, guion, guion bajo y dos puntos. La clave se recuerda durante 24 horas.

curl -X POST https://atendy.es/api/v1/calls \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk_live_tu_clave_aqui" \
  -H "Idempotency-Key: aviso-2026-08-06-12345" \
  -d '{
    "agent_id": "1a2b3c4d-0000-0000-0000-000000000000",
    "to": "+34600000000"
  }'
SituaciónQué recibes
Misma clave, mismos datos, la primera llamada ya se lanzó200 con la respuesta original y la cabecera Idempotent-Replay: true. No se marca de nuevo.
Misma clave, mientras la primera petición sigue en curso409. Espera unos segundos y vuelve a consultar; la llamada original sigue su curso.
Misma clave, pero con datos distintos409. Es señal de que tu sistema está reutilizando la clave para otra llamada: usa una clave nueva.
El primer intento falló (por ejemplo, comunicando)La clave queda libre: puedes reintentar esa misma llamada con la misma clave.
Si Atendy no puede garantizar en ese momento que la llamada no se duplicará, responde 503 en lugar de marcar. Es intencionado: preferimos que reintentes a arriesgarnos a llamar dos veces a la misma persona. Trata el 503 como reintentable.

Cómo se usan las vars como {{variables}}

Cada clave que envíes dentro de vars queda disponible en el prompt y en el saludo del agente escribiéndola entre dobles llaves. Por ejemplo, si envías vars con nombre igual a Ana y pedido igual a 12345, en el prompt o el saludo puedes escribir {{nombre}} y {{pedido}} y el agente dirá los valores reales durante la llamada.

Saludo del agente:
Hola {{nombre}}, le llamo de la tienda por su pedido {{pedido}}.

Con vars = { "nombre": "Ana", "pedido": "12345" } el agente dice:
Hola Ana, le llamo de la tienda por su pedido 12345.
Además de tus propias variables, el agente dispone de {{numero_origen}}. Ojo con el nombre: en una llamada saliente contiene el número al que estás llamando, es decir el mismo valor que enviaste en to, no un número tuyo. Asegúrate de que cada variable que uses en el prompt o el saludo la envías en vars: si falta, Atendy elimina el hueco para que el agente no lea el texto {{variable}} en voz alta.

Errores

Cuando algo falla, la API devuelve un código de estado distinto de 200:

CódigoSignificadoQué hacer
400Petición mal formada.Falta agent_id, no tiene forma de identificador válido, o el número de to no es un número de teléfono reconocible. También si la Idempotency-Key no cumple el formato. Revisa el cuerpo antes de reintentar: reintentar sin cambios volverá a fallar.
401Clave de API no válida o ausente.Revisa que envías la cabecera x-api-key y que la clave existe y no ha sido revocada. Genera una nueva en Llamadas salientes si hace falta.
403Plan insuficiente.La API requiere el plan Escala. Sube de plan para poder lanzar llamadas por API.
404Agente no encontrado.El agent_id no existe o no pertenece a la cuenta dueña de la clave. Comprueba que copiaste el identificador del agente correcto.
409Conflicto de Idempotency-Key.Esa clave ya está en uso para una llamada en curso, o se usó antes con datos distintos. Ver el apartado Evitar llamadas duplicadas.
422El agente no tiene línea de salida.Ese agente no tiene ningún número con llamadas salientes configuradas. Asígnaselo en la sección Números del panel. Es el error más habitual en la primera integración.
429Límite de ritmo superado.El límite es de 30 peticiones por minuto y cuenta. La respuesta incluye la cabecera Retry-After con los segundos que debes esperar. Reparte las llamadas en el tiempo.
502Tu operadora rechazó la llamada.El mensaje concreta la causa: credenciales SIP rechazadas, destino ocupado o número no enrutable. Si son las credenciales, corrígelas en Números; si es el destino, se puede reintentar más tarde.
503No se puede garantizar la idempotencia.Solo ocurre si enviaste Idempotency-Key. La llamada NO se ha lanzado. Reintenta la misma petición al cabo de unos segundos.
500Error inesperado.Reintenta pasado un momento. Si se repite, escríbenos con el momento exacto y el agent_id.

Límite de peticiones

Puedes lanzar hasta 30 peticiones por minuto con la misma cuenta. Al superarlo recibes un 429 con la cabecera Retry-After. Ten en cuenta que ese límite es de peticiones, no de conversaciones simultáneas: cada llamada ocupa recursos durante varios minutos, así que si vas a lanzar decenas de llamadas seguidas, repártelas en el tiempo o usa las campañas del panel, que tienen ritmo configurable. Si necesitas volumen alto y sostenido, háblalo con nosotros antes para dimensionar la capacidad.

Recuerda que cada llamada lanzada con tu clave se factura a la cuenta dueña de la clave. Antes de automatizar en producción, prueba el agente con Probar agente y lanza alguna llamada de prueba a un número tuyo.
La lista de exclusión NO se aplica a esta API. Cuando alguien pide durante una llamada que no se le vuelva a llamar, su número queda registrado y las campañas del panel lo respetan automáticamente, pero una petición a este endpoint se ejecuta siempre, porque se entiende como una acción explícita de tu flujo (por ejemplo, devolver una llamada). Si haces llamadas comerciales, comprueba tú las bajas antes de llamar.
Si prefieres no programar, en la sección Llamadas salientes puedes lanzar llamadas puntuales o campañas por lista (CSV) con ritmo configurable, sin escribir nada de código.