Conecta tu tienda online, tu ERP o herramientas como Zapier, Make y n8n con tus líneas de WhatsApp: crea contactos, envía mensajes y campañas, maneja pedidos, arranca flujos del bot y recibe un aviso firmado cada vez que pasa algo.
La API está en los planes que incluyen API Keys; las campañas y los webhooks también necesitan que el plan los incluya. Todo está en español: los errores traen un message que puedes mostrar tal cual.
Permisos de las claves
Cada endpoint pide un permiso. Si la clave no lo tiene, responde 403.
Permiso
Qué permite
contacts:read
Leer contactos
contacts:write
Crear, editar y borrar contactos
messages:send
Enviar mensajes y plantillas
messages:read
Ver mensajes y su estado
conversations:write
Pasar chats a una persona (bot)
catalog:read
Leer productos, precios y sucursales
orders:read
Ver pedidos
orders:write
Crear pedidos y cambiar su estado
flows:start
Arrancar flujos (bots) para un contacto
campaigns:read
Ver campañas y su avance
campaigns:write
Crear, enviar y cancelar campañas (envío masivo)
webhooks:manage
Suscribir y quitar webhooks (Zapier, Make, n8n)
Paginación, límites y errores
Paginación: las listas devuelven { data, has_more, next_cursor }. Para la página siguiente manda ?cursor= con el next_cursor.
Límite: 120 peticiones por minuto por clave. Cada respuesta trae X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset.
Reintentos seguros: en los envíos manda Idempotency-Key con un valor único. Si tu sistema repite la petición en las 24 h siguientes, recibe la misma respuesta (con Idempotent-Replayed: true) y nada se envía dos veces.
Fechas en ISO 8601 (UTC) y teléfonos con código de país.
{ "error": "insufficient_scope", "message": "Esta clave no tiene el permiso «Ver pedidos» (orders:read)." }
Status
error
Qué significa
400
invalid_json, invalid_…
Falta un dato o tiene un formato inválido. message dice cuál.
401
unauthorized, key_expired
Falta la clave, no existe, fue revocada o venció.
403
insufficient_scope
La clave no tiene el permiso que pide ese endpoint.
403
plan_feature_missing
El plan de la empresa no incluye esa función.
404
…_not_found
No existe o es de otra empresa.
409
chat_assigned, channel_unavailable, …
El estado actual no lo permite (por ejemplo una persona ya atiende el chat).
422
empty_audience
La audiencia de la campaña no tiene a nadie a quien enviar.
429
rate_limited
Más de 120 peticiones por minuto con la misma clave. Espera Retry-After segundos.
502
delivery_failed
WhatsApp rechazó el mensaje (queda guardado como fallido).
Cuenta
Para comprobar que una clave funciona (Zapier, Make y n8n lo usan al conectar).
GET/me
Ver la empresa y los permisos de la clave
Permiso: cualquier clave
curl -X GET "https://ankatickets.com/api/public/v1/me" \
-H "Authorization: Bearer cmnk_TU_CLAVE"
Envíos masivos. Salen por lotes con pausas (como desde la pantalla) para cuidar tu número. Los contactos que respondieron BAJA nunca la reciben. El plan de la empresa tiene que incluir Campañas.
GET/campaigns
Listar campañas
Permiso: campaigns:read
Parámetro
Descripción
limit
1 a 100 (25 por defecto).
cursor
El next_cursor de la página anterior.
status
draft, scheduled, sending o completed.
curl -X GET "https://ankatickets.com/api/public/v1/campaigns" \
-H "Authorization: Bearer cmnk_TU_CLAVE"
Queda en borrador, programada (scheduled_at) o saliendo ya (send_now: true, responde 202). Por QR se manda message, que acepta {{nombre}}, {{telefono}}, {{empresa}} y tus campos personalizados. Por la API oficial se manda template_id y variables.
Permiso: campaigns:write · acepta Idempotency-Key
nameobligatorio — Nombre interno.
channel_id — Línea. Con plantilla puede faltar (se usa la de la plantilla).
message — Texto (líneas por QR).
template_id + variables — Plantilla aprobada (líneas de la API oficial).
audienceobligatorio — { type: "all" }, { type: "tag" | "department" | "segment", id } o { type: "contacts", contact_ids, phones } (hasta 1000; los teléfonos nuevos se crean como contacto).
scheduled_at — Fecha ISO 8601 futura.
send_now — true para enviarla ya.
batch_size / batch_delay_seconds — Tamaño del lote (1 a 500, 20) y espera entre lotes (0 a 3600 s, 60).
Para que otro sistema se suscriba solo a los avisos (REST hooks). Es lo que usan Zapier, Make y n8n en sus disparadores instantáneos. Los webhooks también se crean a mano en Integraciones → Webhooks.
POST/webhooks
Suscribir una URL
Responde 201 con el secret para verificar la firma (solo se muestra esta vez). Máximo 50 webhooks por empresa.
Permiso: webhooks:manage
url (o target_url)obligatorio — Dirección pública https que recibirá los avisos.
events (o event)obligatorio — Lista de eventos; ["*"] = todos.
Cuando pasa algo, Anka hace un POST con JSON a tu URL. Los creas en Integraciones → Webhooks o por la API (POST /webhooks). Responde con un 2xx en menos de 10 segundos; si no, se reintenta a los 1 min, 5 min, 30 min, 2 h, 6 h, 12 h y después queda como fallido (lo puedes reenviar a mano desde el panel). El id se repite en los reintentos: úsalo para no procesar dos veces el mismo aviso.
Cambió el estado de un mensaje (entregado, leído, fallido)
conversation.created
Conversación nueva
conversation.assigned
Conversación asignada
conversation.transferred
Conversación transferida de departamento
conversation.resolved
Conversación terminada
conversation.reopened
Conversación reabierta
contact.created
Contacto nuevo
contact.updated
Contacto actualizado
contact.deleted
Contacto eliminado
contact.tag_added
Etiqueta agregada
contact.tag_removed
Etiqueta quitada
contact.stage_changed
Contacto cambió de etapa
order.created
Pedido nuevo
order.status_changed
Cambió el estado de un pedido
payment.paid
Se pagó un link de pago (Cobros)
csat.responded
Respuesta de la encuesta de satisfacción
Encabezados
X-Anka-Event, X-Anka-Event-Id y X-Anka-Delivery-Id.
X-Anka-Signature: t=1761663845,v1=5f8a…: v1 es el HMAC-SHA256, con el secreto del webhook, de <t>.<cuerpo>. Rechaza los avisos con más de 5 minutos para que nadie pueda repetir uno viejo.
Node.js
import crypto from "crypto";
// rawBody: el cuerpo tal cual llegó (string), sin volver a convertirlo a JSON.
export function avisoValido(rawBody, header, secret) {
const partes = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(partes.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // más de 5 min: se descarta
const esperado = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(partes.v1 ?? ""));
}
import hashlib, hmac, time
def aviso_valido(raw_body: bytes, header: str, secret: str) -> bool:
p = dict(x.split("=", 1) for x in header.split(","))
t = int(p.get("t", 0))
if not t or abs(time.time() - t) > 300:
return False
esperado = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperado, p.get("v1", ""))
URL de un flujo (sin clave)
En Automatizaciones → Flujos, un flujo con inicio «Desde otro sistema (URL o API)» tiene su propia URL secreta (botón «Copiar URL para tu otro sistema»). Llamarla arranca el flujo para ese teléfono; la URL es la credencial, así que no lleva clave de API. Admite 60 llamadas por minuto.
Con los webhooks y la API puedes conectar Anka con más de 6.000 aplicaciones sin programar. Los tres funcionan igual: un disparador que recibe los avisos de Anka y acciones que llaman a la API.
Zapier
Disparador: elige Webhooks by Zapier → Catch Hook y copia la URL que te da.
En Anka, Integraciones → Webhooks → Nuevo: pega la URL y marca los eventos (por ejemplo «Pedido nuevo»). Toca «Probar» para que Zapier vea un ejemplo.
Acción hacia Anka:Webhooks by Zapier → Custom Request, con la URL del endpoint (por ejemplo https://ankatickets.com/api/public/v1/messages), el encabezado Authorization: Bearer cmnk_… y el cuerpo JSON.
Make
Disparador: módulo Webhooks → Custom webhook; copia la dirección y regístrala en Anka como arriba. Con «Probar» Make aprende la estructura.
Acción: módulo HTTP → Make a request, método y URL del endpoint, el encabezado Authorization y el cuerpo en JSON.
n8n
Disparador: nodo Webhook (método POST). Registra en Anka la «Production URL». Si quieres verificar la firma, agrega un nodo Code con el ejemplo de Node.js de arriba.
Acción: nodo HTTP Request con una credencial Header Auth (Authorization = Bearer cmnk_…). También puedes pegar cualquier ejemplo curl de esta página con «Import cURL».