Saltar al contenido

API ​

La API REST da a tus propios sistemas acceso a las conversaciones, los leads, los contactos y las citas de tu empresa. Úsala para pasar conversaciones a un CRM, iniciar llamadas salientes desde tu programa de planificación o sincronizar contactos.

Autenticación ​

Crear una clave de API ​

  1. Ve a Ajustes → Conexiones (necesitas el rol Administrador).
  2. En Claves de API, escribe un nombre (por ejemplo Make) y haz clic en Crear.
  3. Copia la clave de inmediato. Empieza por pk_ y solo se muestra una vez; después el panel solo enseña los primeros 10 caracteres, para que puedas reconocerla más adelante.

Elimina una clave en la misma página cuando ya no la necesites. Puedes tener hasta 200 claves. No hay permisos por clave: cada clave puede hacer todo lo que esta API permite para tu empresa, así que guárdala como una contraseña. Crear o eliminar una clave solo funciona durante las 2 horas posteriores a iniciar sesión, y solo con tu propio acceso, consulta Cambios que piden volver a iniciar sesión. Las claves dejan de funcionar si tu suscripción está impagada, suspendida o cancelada.

Con una suscripción Enterprise puedes limitar las claves a determinadas direcciones IP: en Ajustes → Gestión de acceso, dentro de Reglas de seguridad, indica los rangos de IP permitidos y activa Limitar también las claves de API a estos rangos. Una petición desde otra dirección recibe entonces un 403.

Hacer peticiones ​

Envía la clave como token bearer. La URL base es tu dominio de API (la ves en Ajustes → Conexiones, dentro de Claves de API).

bash
curl https://<dominio-api>/v1/me \
  -H "Authorization: Bearer pk_..."

Las peticiones y las respuestas son JSON. Una petición correcta siempre devuelve el estado 200, también con POST. Los números de teléfono van en formato E.164 (+31612345678). Las fechas y horas son ISO 8601 en UTC.

Límite de peticiones ​

Cada clave de API puede hacer 600 peticiones por minuto; por encima recibes 429 con el código ERR-50022. Además, todos los clientes de la API comparten un límite de la plataforma de 50 peticiones por segundo, con picos de hasta 100. No consultes datos más de una vez por minuto; para datos en tiempo real usa webhooks.

Errores ​

Los errores devuelven un estado HTTP y un cuerpo JSON:

json
{ "error": "lead not found", "code": "ERR-56004", "errorId": "…" }

error es una descripción en inglés y code es el código de error. errorId identifica este error concreto; indícalo cuando vayas a informar de un problema. Algunos errores también incluyen un campo details.

EstadocodeSignificado
400ERR-50020, ERR-50023–ERR-50028, ERR-50010Datos no válidos. El código indica el primer problema: ERR-50023 texto demasiado largo y ERR-50028 demasiado corto (details.max / details.min), ERR-50024 demasiados elementos en una lista, ERR-50025 un campo obligatorio vacío o ausente, ERR-50026 un correo electrónico no válido, ERR-50027 una dirección web no válida, y ERR-50020 todo lo demás. details.field y error indican el campo. ERR-50010 es JSON no válido. Algunos endpoints tienen su propio código, que aparece más abajo junto al endpoint.
401ERR-51004, ERR-51005Falta la clave de API o no es válida.
402ERR-52250, ERR-56007La suscripción está impagada, suspendida o cancelada (ERR-52250, en cada petición). Las llamadas salientes no están en el plan (ERR-56007, solo POST /v1/calls).
403ERR-52056, ERR-56008No permitido: la dirección IP no está en la lista de tu empresa (ERR-52056) o las llamadas salientes están bloqueadas (ERR-56008).
404ERR-56000, ERR-56002, ERR-56004, ERR-56006, ERR-51044Objeto no encontrado. Una ruta que no existe devuelve 404 sin code.
413ERR-50021El cuerpo pesa más de 8 MB.
429ERR-50022Demasiadas peticiones con esta clave. Un 429 sin code significa que se ha alcanzado el límite compartido de la plataforma. Vuelve a intentarlo pasado un momento.
500ERR-50000Error inesperado; vuelve a intentarlo más tarde.

Endpoints ​

GET /v1/me ​

Devuelve la empresa a la que pertenece la clave.

json
{
  "business": { "id": "…", "name": "Pipes & Co", "slug": "pipes-co-1a2b", "timezone": "Europe/Amsterdam" },
  "apiKey": { "id": "…", "name": "Make" }
}

GET /v1/assistants ​

Lista de asistentes: id, name, language.

json
[{ "id": "01J…", "name": "Sam", "language": "nl-NL" }]

POST /v1/calls ​

Inicia una llamada saliente con un asistente. Necesitas un número que pueda hacer llamadas salientes (consulta Llamadas salientes).

json
{
  "to": "+31612345678",
  "assistantId": "01J…",
  "from": "+31201234567",
  "variables": { "name": "Jan", "order": "BP20260016" }
}

from es opcional (se usa el primer número que pueda hacer llamadas salientes). variables también es opcional: hasta 200 variables, nombres de hasta 64 caracteres y valores de texto de hasta 2000 caracteres, un número o true/false. Rellenan {{name}} y {{order}} en el Saludo de salida, el asistente recibe los valores como datos durante la llamada y puedes usarlos después en tus acciones. En el texto del propio prompt no se rellenan: {{name}} queda vacío. Por eso, en el prompt escribe "el nombre del cliente" en lugar de {{name}}.

Respuesta:

json
{ "conversationId": "v3:…", "status": "dialing" }

Este endpoint también puede devolver estos errores:

EstadocodeSignificado
400ERR-56001No hay ningún número disponible: ninguno puede hacer llamadas salientes, o el from no es tuyo o no puede hacerlas.
402ERR-56007Las llamadas salientes no están incluidas en la suscripción de esta empresa.
403ERR-56008Las llamadas salientes están bloqueadas para esta empresa. Ponte en contacto con soporte.
404ERR-56000No se ha encontrado el asistente.

GET /v1/conversations ​

Parámetros de consulta: from, to (fechas ISO en UTC sobre startedAt), channel (voice, sms, whatsapp, webchat), outcome, assistantId, sentiment (positive, neutral, negative), flag (una de las marcas de abajo, o any para todas las conversaciones marcadas), limit (100 por defecto, máximo 500). Un sentiment o flag desconocido devuelve 400 con el código ERR-52121. Devuelve una lista de objetos de conversación, de la más reciente a la más antigua. Las conversaciones archivadas no se devuelven.

GET /v1/conversations/ ​

Un objeto de conversación y además:

CampoSignificado
transcriptLista de { "role": "user" | "assistant" | "system", "text": "…", "createdAt": "…" }. user es el cliente, assistant es el asistente o un compañero que se hizo cargo de la conversación, y system son líneas de la plataforma, como el saludo. text puede incluir marcas, como [image] para una imagen o el nombre de una herramienta usada, entre corchetes.
recordingUrlEnlace temporal para descargar la grabación (válido una hora), o null. Las grabaciones se eliminan a los 30 días; después el enlace deja de funcionar.

Leads ​

Los leads son las solicitudes que ves en el panel en Bandeja → Solicitudes, consulta Solicitudes. new y qualified aparecen allí como Abierta, contacted como Contactada, booked como Cita concertada y lost como Cerrada.

  • GET /v1/leads?status=&limit= — lista de leads, del más reciente al más antiguo (limit 200 por defecto, máximo 500). status se puede escribir en mayúsculas o minúsculas: new, qualified, contacted, booked, lost. Otro valor devuelve 400 con el código ERR-56003.
  • GET /v1/leads/{id}
  • PATCH /v1/leads/{id} con { "status": "contacted", "notes": "Llamada devuelta, presupuesto enviado" } (ambos opcionales; notes tiene un máximo de 4000 caracteres y puede ser null).

Objeto lead:

json
{
  "id": "01J…",
  "businessId": "01J…",
  "conversationId": "v3:…",
  "channel": "voice",
  "status": "QUALIFIED",
  "customerName": "Jan de Vries",
  "customerPhone": "+31612345678",
  "address": "Damrak 1, Amsterdam",
  "problem": "Grifo de la cocina que gotea",
  "urgency": "urgent",
  "preferredTime": "mañana por la mañana",
  "summary": "Grifo que gotea, quiere una visita mañana por la mañana",
  "notes": null,
  "phoneProof": null,
  "customerPhoneVerified": false,
  "customerPhoneVerifiedBy": null,
  "createdAt": "2026-09-11T10:00:00.000Z",
  "updatedAt": "2026-09-11T10:00:00.000Z"
}

urgency es emergency, urgent, routine o unknown. status se devuelve en mayúsculas. Un lead de Probar con Ejecutar las acciones de verdad también aparece aquí; su conversationId empieza por test:. customerPhoneVerified es true si el cliente demostró el número en la conversación, false si no, y null en un lead anterior a este campo. customerPhoneVerifiedBy (y phoneProof.by) dice cómo: caller_id (el cliente llamó desde ese número), sms_code, email_code, call_code, whatsapp o phone_change.

Contactos ​

  • GET /v1/contacts?phone=&limit= — contactos, del más reciente al más antiguo (limit 500 por defecto, máximo 2000). Con phone recibes una lista con el contacto que tiene exactamente ese número E.164, o una lista vacía; escribe el + de la URL como %2B.
  • POST /v1/contacts — cuerpo con phone o email, o ambos (uno es obligatorio), y de forma opcional name (máximo 160 caracteres, se separa en nombre y apellidos) o firstName/lastName, company, notes, tags, blocked, fields. Sin phone ni email recibes 400 con el código ERR-56005. Al llegar al máximo de 1.000.000 de contactos por empresa recibes 400 con el código ERR-52058; details.count indica el máximo. No se comprueban los duplicados: busca primero con ?phone= si el número puede existir ya.
  • GET /v1/contacts/{id}
  • PATCH /v1/contacts/{id} — los mismos campos que al crear, salvo name; blocked: true rechaza las futuras llamadas y los mensajes de SMS y WhatsApp de ese número.

Un contacto también incluye id, businessId, lastSeenAt, conversationCount, createdAt y updatedAt.

GET /v1/appointments ​

Parámetros de consulta from y to (fechas ISO en UTC sobre startAt; por defecto, de ahora a 90 días vista). Devuelve un máximo de 500 citas reservadas en un servicio de Yarla, de la más temprana a la más tardía e incluidas las canceladas. Las reservas hechas con Cal.com o eTermin no aparecen.

json
[{
  "id": "01J…",
  "businessId": "01J…",
  "eventTypeId": "01J…",
  "startAt": "2026-09-15T07:00:00.000Z",
  "endAt": "2026-09-15T08:00:00.000Z",
  "timezone": "Europe/Amsterdam",
  "status": "confirmed",
  "guestName": "Jan de Vries",
  "guestEmail": "jan@example.com",
  "guestPhone": "+31612345678",
  "fields": { "address": "Damrak 1" },
  "source": "voice",
  "conversationId": "v3:…",
  "contactId": null,
  "externalEventId": null,
  "meetingUrl": "",
  "remindersSent": [],
  "phoneProof": { "phone": "+31612345678", "by": "caller_id", "at": "2026-09-11T09:58:00.000Z" },
  "guestPhoneVerified": true,
  "guestPhoneVerifiedBy": "caller_id",
  "createdAt": "2026-09-11T10:00:00.000Z",
  "updatedAt": "2026-09-11T10:00:00.000Z"
}]

status es confirmed, rescheduled, cancelled, completed o no_show. source es voice, sms, whatsapp, webchat, web, dashboard o api. El enlace privado con el que el cliente gestiona la cita nunca se incluye. Una cita de Probar con Ejecutar las acciones de verdad también aparece aquí; su conversationId empieza por test:. guestPhoneVerified es true o false si la cita se reservó o se cambió en una conversación, y null si no. guestPhoneVerifiedBy dice cómo, como en un lead.

El objeto conversation ​

CampoSignificado
idId de la conversación; también se usa en las variables conversationLink.
assistantIdAsistente que atendió la conversación.
channelvoice, sms, whatsapp o webchat.
directioninbound u outbound.
customerPhoneNúmero E.164. En el chat web suele ser null: el widget y la página de chat no envían ningún número.
customerPhoneVerifiedtrue si el cliente demostró el número en esta conversación (llamó desde él, un código, o WhatsApp), false si no, null sin número.
customerPhoneVerifiedByCómo: caller_id, sms_code, email_code, call_code, whatsapp o phone_change, o null.
agentNumberTu número en el que se desarrolló la conversación, o null en el chat web.
contactIdContacto reconocido, o null.
statusactive, handed_over (responde un compañero) o ended.
outcomeresolved, transferred, appointment_booked, callback_requested, voicemail, abandoned, no_interaction, spam. A menudo sigue siendo null mientras la conversación está activa, pero appointment_booked, callback_requested, transferred y voicemail ya pueden quedar establecidos durante la conversación. El valor definitivo llega al terminar.
summaryResumen con IA, disponible al terminar la conversación.
leadId, appointmentIdLead y cita vinculados, o null.
durationSecondsDuración de la llamada; null en los canales de texto.
variablesLas variables que se pasaron al inicio (POST /v1/calls, una campaña, o el nombre del contacto como name cuando llamas a un contacto desde el panel), más las Variables personalizadas que extraer que el asistente sacó de la conversación al terminar. El widget y la página de chat no pasan variables al inicio.
inboundContextCampos que devolvió tu webhook antes de la conversación.
analysisLa valoración del asistente después de la conversación, o null mientras no exista: sentiment (positive, neutral, negative), score (de 0 a 100), flags (ninguna o varias de off_topic, not_grounded, failed_task, frustrated, wants_human, manipulation_attempt) y checks (comprobaciones propias de Enterprise: { "id", "question", "passed" }, donde passed es null si la pregunta no aplicaba).
campaignIdSe rellena en las llamadas de una campaña saliente.
startedAt, endedAtFechas ISO; endedAt es null mientras la conversación sigue activa.

La API usa sus propios nombres de campo (customerPhone, startedAt, recordingUrl). El cuerpo de los webhooks usa los nombres de las variables de plantilla (personNumber para el número del cliente, startTimestamp, audioLink). El id del objeto de conversación es el conversationId del webhook; relaciona ambos con ese valor. Consulta Webhooks.

Artículos relacionados ​

Yarla Ayuda — la guía de tu asistente telefónico.