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 → Integraciones y automatización → API, 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…

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 and the transcript too.
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.

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.

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 (2026-08-08T09:30:00Z). A la entrada se acepta cualquier desplazamiento explícito (…+02:00). 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.

{
  "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.
413payload_too_largeEl cuerpo pasa del límite.
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.
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. 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.

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.

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.bookedappointment.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.