Skip to content
Technical reference

API reference

Documentation for integrators. If you are looking for how to configure Alpire, the admin guide is in Documentation.

This technical reference is written in Spanish only. The product Documentation is available in your language.

← Documentación del producto · Referencia de webhooks · Crear una clave

La clave se queda en este navegador (solo se usa para escribir los ejemplos) y no se envía a ninguna parte.

Empezar

Tres cosas y ya estás dentro: una clave, la URL de tu región y el permiso adecuado en esa clave.

  1. Crea una clave en Ajustes → API y webhooks, marcando solo los permisos que vayas a usar. Se enseña una vez: guárdala donde guardes el resto de secretos.
  2. Elige tu región arriba. Tu organización vive en una sola y sus datos no salen de ella.
  3. Comprueba que funciona con GET /v1/me, que te dice qué organización eres y qué permisos tiene la clave.
Los webhooks y la API son las dos mitades. La API sirve para preguntar y para hacer. Para enterarte de que algo ha pasado están los webhooks: sondear /v1/calls cada pocos segundos llega tarde y gasta de más.

Autenticación

Cada petición lleva la clave en una cabecera:

Authorization: Bearer ak_9f3c1d2b…

Escribe Bearer así, con mayúscula: bearer ak_… se rechaza como si faltara la cabecera.

Una clave pertenece a la organización, no a una persona: tu automatización no se cae el día que se va de la empresa quien la configuró. En el registro de auditoría las acciones salen como api-key:ak_9f3c1d2b, junto a la persona que responde de esa clave.

Cuando quien creó una clave sale del equipo —expulsión, suspensión o baja—, la clave sigue funcionando y pasa a responder de ella quien lo expulsa o suspende (en una baja voluntaria, el propietario más antiguo). Los administradores reciben un correo con la lista: si esa persona pudo copiar alguna, rótala (crea otra con los mismos permisos, cámbiala en tu integración y revoca la vieja).

Permisos

Sin el permiso, la respuesta es 403 y dice cuál falta. Da a cada integración lo justo: es lo que hace que revocar una clave sea una molestia y no una urgencia.

PermisoDa acceso a
calendar:readCalendars, availability and appointments.
calendar:writeCreate and cancel appointments.
calls:readCall list and detail. Metadata only, never the content.
recordings:readThe recording audio, the transcript and the data the flow saved in the call.
callbacks:readThe callback queue.
campaigns:readCampaigns and their counters.
reports:readAggregated reports.
extensions:readThe list of extensions.
extensions:writeAdd and remove extensions.
groups:readHunt groups and queues, with their members.
groups:writeChange who belongs to a group or a queue.
dnc:writeAdd numbers to the Do-Not-Call list. Cannot read it or remove anyone.
assist:readThe operator assistants' profile: name and configuration.
assist:writeEach query spends your organization's AI credits.
chatbots:readThe chatbots and ALL their conversations, including what visitors wrote.
chatbots:writeOpen, write to and close conversations, request a person, rate and confirm bot actions. Each message spends AI credits.
team:readWho is on the team (name, email and role), pending invitations and the plan seats.
team:writeInvite a person by email (uses a plan seat). Never grants the owner role.
hours:readThe organization opening hours with their holidays and special days.
hours:writeChange the weekly hours and add or remove holidays and special days.
numbers:readWhich numbers the phone system answers and which flow each one goes to. Read only.
flows:readSee what each of the organization's call flows does and which templates exist to create a new one.
flows:writeCreate flows from templates, change the greeting, agent instructions, hours and forwarding, publish them and assign a number. It changes what callers hear.
audios:readThe organization's audio prompts (queues, voicemail, menus), where each one is used, the available voices and a temporary link to listen to them.
audios:writeCreate an audio from a text with an AI voice (spends AI credits), rename it or delete it. An audio used by a flow, queue or voicemail cannot be deleted.
agents:readThe AI agents in the library: prompt, rules, model, voice, language and which flows use them.
agents:writeCreate agents and change their prompt, model, voice or language. An agent in use answers real calls: changing it requires explicit confirmation. Requires an administrator with Routing access.
knowledge:readThe knowledge bases of assistants and chatbots, their documents and their text.
knowledge:writeAdd texts (FAQs, prices, policies) to an assistant or chatbot knowledge base and remove them. It changes what the bot answers. Requires an administrator with Routing access.
contacts:readThe contact book: name, phone, email, company, tags and notes. This is personal data of your customers.
contacts:writeCreate contacts, change their data and add notes. Contacts cannot be deleted through the API.
credits:readThe AI credit balance (plan pool and loaded credits) and what was used this month by model. Credits only: no prices or billing.
live:readCalls in progress, who is on each one, calls waiting in queue and extension status. Read only: it does not listen in or intervene.

recordings:read cubre el audio y la transcripción: con calls:read a secas se leen los metadatos de la llamada, nunca su contenido.

Región

Si llamas a la región equivocada no recibes una lista vacía —que parecería un dato y no lo es— sino un 421 con la URL buena:

{
  "error": {
    "type": "wrong_region",
    "message": "esta organización se sirve desde otra región; repite la petición contra base_url",
    "base_url": "https://eu.alpire.ai"
  }
}

La misma clave vale en las dos: lo que cambia es dónde están los datos.

Formato común

Listados y paginación

{ "data": [ … ], "next_cursor": "01JZK8…" }

Paginación por cursor, no por número de página. Pasa el next_cursor que te llega y para cuando venga null. limit por defecto 50, máximo 200. Los catálogos cortos (/v1/extensions, /v1/groups, /v1/queues, /v1/calendars, /v1/availability) no paginan: llegan enteros en data, sin next_cursor.

No hay offset a propósito: la tabla de llamadas crece sin tope y un OFFSET 50000 lo acabarían pagando también las llamadas en curso, que comparten esa base de datos. Los ids son ULID, así que ordenar por id es ordenar por fecha.

Fechas

RFC 3339 y en UTC a la salida, con el desplazamiento escrito (2026-08-08T09:30:00+00:00; trátalo igual que una Z). A la entrada se acepta cualquier desplazamiento explícito (…+02:00). En una query string el + hay que codificarlo (%2B): sin codificar llega como un espacio y la petición da 400. Lo mismo con los cursores que llevan fecha. Lo que no se acepta es una fecha sin zona: en un producto que corre en dos continentes, eso es una cita a la hora equivocada esperando a ocurrir.

Errores

Mira siempre type, nunca message: el texto puede cambiar, el tipo no. Todo error de /v1 sale con este formato, también una ruta mal escrita, un verbo equivocado, un JSON mal cerrado o un timeout. request_id es el mismo valor que la cabecera X-Request-Id: guárdalo con el error. Cuando un mismo type tiene varios motivos que tu código tiene que distinguir, llega además error.code (p. ej. chat_closed o chat_full en los 409 del chat), y el 409 de una reserva trae error.alternatives ([{start, end}], huecos cercanos) y error.hard.

{
  "error": {
    "type": "bad_request",
    "message": "'status' no admite «canceled»; valores válidos: booked, cancelled",
    "request_id": "01K5…"
  }
}
HTTPtypeQué hacer
400bad_requestArreglar la petición (cuerpo, Content-Type, parámetros, un filtro con un valor que no existe). No reintentar igual.
401unauthorizedClave ausente, inválida, caducada o revocada.
403forbiddenFalta un permiso (el mensaje dice cuál), organización suspendida, plan sin API, plan no operativo (solo escrituras) o, en asistencia, sin créditos de IA.
404not_foundNo existe — o no es tuyo: misma respuesta a propósito —, o la ruta no es de la API.
405method_not_allowedLa ruta existe con otro método.
409conflictPetición válida, pero el mundo dice que no.
409idempotency_in_progressOtra petición con la misma Idempotency-Key sigue en curso: esperar Retry-After. Si llega sin Retry-After, la primera murió hace más de 15 minutos: usa una clave nueva.
413payload_too_largeEl cuerpo pasa de 1 MiB.
416bad_requestDescarga de grabación con un Range que no cabe en el fichero.
421wrong_regionRepetir contra el base_url del error.
422idempotency_mismatchEsa Idempotency-Key ya se usó con otra petición. Una clave por operación.
429rate_limitedEsperar lo que diga Retry-After. En /v1/assist/ask hay tres motivos distintos (ver su nota).
500internalFallo nuestro. Reintentar con espera creciente.
502provider_errorFalló un tercero: el calendario (Cal.com, Google) o el proveedor del modelo de IA. Reintentar con espera creciente.
503unavailableEl servicio de chat de la organización no respondió. Reintentar en unos segundos (con el mismo client_id no se duplica).
504timeoutPasó el tiempo máximo. Una escritura puede haberse completado: repítela con la misma Idempotency-Key.

Límites

  • 600 lecturas (GET) por minuto y clave.
  • 60 escrituras (POST, PUT, DELETE) por minuto y clave.
  • 60 descargas de grabación cada 5 minutos y clave.
  • 1200 peticiones por minuto y dirección IP.
  • 10 claves activas por organización. Revocar una libera hueco; las revocadas y las caducadas no cuentan.

Los tres primeros son por clave, no por cuenta: dos integraciones tuyas no se quitan cupo entre ellas. Hoy se cuentan en cada nodo de la región, así que con varios nodos detrás del balanceador X-RateLimit-Remaining puede saltar entre una petición y otra; no calcules tu ritmo contando peticiones, respeta el 429. Cada petición paga un solo cubo, y GET /v1/me no gasta ninguno.

No hace falta que lo lleves a ciegas: toda respuesta que paga cupo trae X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset (epoch en segundos) del cubo que gobierna esa petición concreta — el de lectura, el de escritura o el de grabación, que tienen ventanas distintas. Si te acercas a cero, frena antes de chocar.

Al pasarte recibes 429 con error.type: "rate_limited" y la cabecera Retry-After con los segundos que faltan de verdad para que se reponga ese cubo (también en error.retry_after). Respétala y reintenta: no hace falta backoff propio. El techo por IP es la excepción: su 429 llega antes de mirar ningún cubo, con Retry-After: 60 fijo, sin error.retry_after ni cabeceras X-RateLimit-*.

Idempotencia y tiempos

Toda escritura acepta la cabecera Idempotency-Key: un valor único por operación (una UUID vale). La primera petición con esa clave se ejecuta y su respuesta se guarda 24 horas; repetirla con la misma clave y la misma petición devuelve la misma respuesta, con Idempotent-Replayed: true, sin volver a ejecutar nada. La misma clave con otra petición es un 422. Un 400, 401, 403, 429 o 5xx no la consume: corrige o reintenta con la misma. Un 404 o un 409 sí son el resultado de esa clave durante las 24 horas: si reintentas cuando cambie la situación (la llamada ya colgó, eliges otro hueco), usa una clave nueva. Las claves son por clave de API, no por organización. Genera la clave una vez por operación, fuera del bucle de reintentos: los ejemplos de abajo la generan en la propia petición para que se vean completos.

Idempotency-Key: 5f0c2a8e-4b7d-4c1e-9f3a-2d6b8e1c7a90

Una petición tiene 30 s, salvo POST /v1/appointments y POST /v1/assist/ask, que tienen 90 s. Pasado el tiempo recibes un 504, pero la escritura no se cancela: termina igual. Ante un 504 o un corte de red, repite con la misma Idempotency-Key y recibirás el resultado real; sin ella, repetir puede duplicar.

Llama desde tu servidor, no desde el navegador. La API no manda cabeceras CORS, así que un fetch() desde el JavaScript de tu web no va a funcionar — y es a propósito: una clave en el frontend es una clave pública, y la tuya puede leer llamadas y crear citas. El patrón correcto es tu backend hablando con nosotros y tu frontend hablando con tu backend.

Endpoints

Cada uno con sus parámetros, la petición ya montada en el lenguaje que elijas arriba y un ejemplo de respuesta real.

Qué deja rastro

Una acción hecha por la API produce lo mismo que si la hubiera hecho una persona en el panel: mismo webhook, mismo registro de auditoría.

AcciónWebhookAuditoría
POST /v1/appointmentsappointment.booked (solo agenda nativa)appointment.create
POST /v1/appointments/{id}/cancelappointment.cancelledappointment.cancel
POST /v1/extensions—extension.create
DELETE /v1/extensions/{id}—extension.delete
PUT /v1/groups/{id}/members—dial_group.update
PUT /v1/queues/{id}/members—queue.update
POST /v1/dnc—dnc.add
POST /v1/assist/ask—assist.ask

Las citas creadas por API emiten el mismo evento que las del mostrador o las que reserva el agente por teléfono, pero el data no es idéntico según el origen (la API y el panel mandan source, end y resource_id; la voz, call_id): la tabla campo a campo está en la referencia de webhooks. Extensiones, grupos y colas no tienen webhook: tampoco lo emite el panel.