Documentación de la API
Guía completa para integración con la API de Zapini
URL Base
https://instance-{id}.zapini.app
Autenticación
Bearer Token (Sanctum)
Rate Limit
100 requests / 15 min
Primeros Pasos
La API REST de Zapini le permite integrar capacidades de mensajería de WhatsApp en sus aplicaciones. Todas las solicitudes deben usar HTTPS e incluir autenticación Bearer token.
Tipos de API
Zapini ofrece dos tipos de API para diferentes necesidades. Elige la que mejor se adapte a tu caso de uso.
API Universal
https://zapini.app/api/v1
API REST completa para gestionar todas tus instancias, conversaciones, contactos y configuraciones. Usa esta API para aplicaciones web/móviles que necesitan acceso completo al sistema.
API de Instancia
https://instance-{id}.zapini.app/
API directa para enviar mensajes con baja latencia. Cada instancia de WhatsApp tiene su propia URL dedicada. Ideal para bots y automatizaciones de alto volumen.
¿Qué API debo usar?
| Caso de Uso | API Recomendada |
|---|---|
| Aplicación web/móvil | Universal (Token Sanctum) |
| Bot de mensajes | Instancia (Token sk_) |
| CRM / Sistema de soporte | Universal (Token Sanctum) |
| Envío masivo / campañas | Instancia (Token sk_) |
| Integración externa simple | Instancia (Token sk_) |
ID de Instancia
La API acepta tanto ID numérico como UUID en todos los endpoints.
| ID Numérico | UUID | |
|---|---|---|
| Ejemplo | 777 |
550e8400-e29b-... |
| Dónde encontrar | Se muestra en la tarjeta de la instancia. Ejemplo: 777 | Se muestra en la página de detalles de la instancia. Ejemplo: 550e8400-e29b-41d4-a716-446655440000 |
Con un token sk_, el parámetro instance_id es opcional — se detecta automáticamente desde el token.
Headers Requeridos
Authorization: Bearer {token}
Accept: application/json
Content-Type: application/json
Formato de Respuesta
Respuesta Exitosa
{
"success": true,
"message": "Operation completed",
"data": { ... }
}
Respuesta de Error
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Error description",
"details": {}
}
}
Códigos HTTP
| Código | Descripción |
|---|---|
| 200 | OK - Solicitud exitosa |
| 201 | Created - Recurso creado exitosamente |
| 400 | Bad Request - Parámetros inválidos |
| 401 | Unauthorized - Token inválido o ausente |
| 403 | Forbidden - Sin permiso para este recurso |
| 404 | Not Found - Recurso no encontrado |
| 422 | Unprocessable Entity - Error de validación |
| 429 | Too Many Requests - Límite de solicitudes excedido |
| 500 | Internal Server Error - Error interno del servidor |
Autenticación
Tipos de Token
Hay dos tipos de tokens de autenticación, cada uno adecuado para diferentes escenarios.
Token Sanctum
Token de usuario obtenido via login. Da acceso a todas las instancias y recursos de tu tenant. Ideal para aplicaciones web/móviles donde el usuario inicia sesión.
- • Cómo obtener: POST /auth/login con email y contraseña
- • Formato: 1|abc123xyz...
- • Acceso: Todas las instancias del tenant
Token de Instancia (sk_)
Token específico de una instancia de WhatsApp. Generado en el panel administrativo. Ideal para integraciones externas y bots.
- • Cómo obtener: Generar en panel en Instancias > Tokens API
- • Formato: sk_xxxxxxxxxxxxxxxx
- • Acceso: Solo la instancia específica
Ambos tokens funcionan de la misma manera en el header Authorization:
Authorization: Bearer {token}
/auth/login
Autentica un usuario y devuelve un token de acceso.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
email |
string | Sí | Email del usuario |
password |
string | Sí | Contraseña del usuario |
device_name |
string | No | Nombre del dispositivo para identificación del token |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/auth/login \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"email": "user@example.com",
"password": "your_password",
"device_name": "My App"
}'
Respuesta
{
"success": true,
"message": "Login successful",
"data": {
"user": {
"id": 1,
"name": "User Name",
"email": "user@example.com",
"role": "admin"
},
"token": "1|abc123xyz...",
"token_type": "Bearer"
}
}
/auth/me
Devuelve información del usuario autenticado.
Ejemplo
curl -X GET https://instance-{id}.zapini.app/auth/me \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
/auth/logout
Revoca el token de acceso actual.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/auth/logout \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
/auth/refresh
Actualiza el token de acceso.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/auth/refresh \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Instancias
/instances
Lista todas las instancias de WhatsApp en su cuenta.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
status |
string | connected, disconnected, qr_ready, pending |
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/instances?status=connected" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"data": {
"instances": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"phone_number": "5511999999999",
"status": "connected",
"connected": true,
"messages_sent_today": 50,
"remaining_quota": 450,
"can_send_messages": true,
"last_activity_at": "2025-01-15T10:30:00Z"
}
]
}
}
/instances/{id}
Devuelve detalles de una instancia específica.
La API acepta tanto ID numérico como UUID en todos los endpoints.
Ejemplo
# ID Numéricocurl -X GET https://instance-{id}.zapini.app/instances/777 \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
# UUID
curl -X GET https://instance-{id}.zapini.app/instances/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
/instances/{id}/qr
Devuelve el código QR para conectar la instancia.
Ejemplo
curl -X GET https://instance-{id}.zapini.app/instances/777/qr \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"data": {
"status": "qr_ready",
"qr_code": "data:image/png;base64,...",
"qr_code_text": "2@...",
"qr_generated_at": "2025-01-15T10:30:00Z",
"qr_expired": false,
"message": "QR code ready to scan"
}
}
/instances/{id}/status
Devuelve el estado actual de la instancia.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
realtime |
boolean | Si es true, verifica el estado en tiempo real en el servidor |
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/instances/777/status?realtime=true" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
/instances/{id}/stats
Devuelve estadísticas de uso de la instancia.
Respuesta
{
"success": true,
"data": {
"messages_sent_today": 50,
"remaining_quota": 450,
"daily_limit": 500,
"messages_this_week": 200,
"messages_this_month": 800,
"messages_received_today": 30,
"conversations_count": 150,
"contacts_count": 500
}
}
/instances/{id}/disconnect
Desconecta la instancia de WhatsApp.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/instances/777/disconnect \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
/instances/{id}/reconnect
Inicia el proceso de reconexión de la instancia.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/instances/777/reconnect \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Mensajes
API de Instancia
API directa para enviar mensajes con baja latencia. Cada instancia de WhatsApp tiene su propia URL dedicada. Ideal para bots y automatizaciones de alto volumen.
Base URL:
https://instance-{id}.zapini.app
API Universal - /chat/send
Para enviar mensagens via API Universal, use o endpoint /chat/send (consulte a aba Chat API).
/send-message
Envía un mensaje de texto a un número de WhatsApp.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
recipient
(ou number, to)
|
string | Sí | Número de WhatsApp del destinatario (con código de país) (5511999999999) |
message |
string | Sí | Contenido del mensaje de texto |
reply_to
(ou quoted_message_id)
|
string | No | ID del mensaje para responder |
recipient, number e to são equivalentes.
Assim como reply_to e quoted_message_id.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/send-message \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"recipient": "5511999999999",
"message": "Olá! Esta é uma mensagem de teste."
}'
Respuesta
{
"success": true,
"message": "Message sent successfully",
"message_id": "3EB0B430A8B7F23C1D12",
"timestamp": "2025-12-30T17:30:00.000Z"
}
/send-media
Envía un mensaje con medios (imagen, video, audio, documento).
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
recipient
(ou number, to)
|
string | Sí | Número de WhatsApp del destinatario (con código de país) (5511999999999) |
media_url
(ou url)
|
string | Sí | URL pública del archivo de medios |
media_type
(ou type)
|
string | Sí | image, video, audio, document |
caption |
string | No | Leyenda para imágenes y videos |
filename |
string | No | Nombre del archivo para documentos |
recipient/number/to,
media_url/url e
media_type/type são equivalentes.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/send-media \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"recipient": "5511999999999",
"media_url": "https://example.com/image.jpg",
"media_type": "image",
"caption": "Confira esta imagem!"
}'
Respuesta
{
"success": true,
"message": "Media sent successfully",
"message_id": "3EB0B430A8B7F23C1D13",
"timestamp": "2025-12-30T17:30:00.000Z"
}
/send-reaction
Envía un emoji de reacción a un mensaje específico.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
to |
string | Sí | JID do chat |
messageId |
string | Sí | ID da mensagem para reagir |
emoji |
string | Sí | Emoji da reação (ex: 👍, ❤️, 😂) |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/send-reaction \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"to": "5511999999999@s.whatsapp.net",
"messageId": "3EB0B430A8B7F23C1D12",
"emoji": "👍"
}'
/status
Devuelve el estado actual de conexión de la instancia de WhatsApp.
Ejemplo
curl -X GET https://instance-{id}.zapini.app/status \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"status": "connected",
"phone": "5511999999999",
"name": "Meu WhatsApp",
"platform": "android"
}
/qr
Devuelve el código QR para conectar la instancia de WhatsApp. Solo disponible cuando el estado es qr_ready.
Ejemplo
curl -X GET https://instance-{id}.zapini.app/qr \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"qr": "data:image/png;base64,iVBORw0KGgoAAAA...",
"status": "qr_ready"
}
/health
Devuelve el estado de salud del servidor de la API. No requiere autenticación.
Ejemplo
curl -X GET https://instance-{id}.zapini.app/health
Respuesta
{
"status": "ok",
"uptime": 123456,
"timestamp": "2025-12-15T14:30:00.000Z"
}
Conversaciones
/conversations
Lista todas las conversaciones activas.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
instance_id |
string | Filtrar por instancia (UUID) |
unread |
boolean | Mostrar solo conversaciones no leídas |
search |
string | Buscar por nombre o número |
is_group |
boolean | Filtrar por grupos (true/false) |
per_page |
integer | Items por página (máx 100) |
include_tags |
boolean | Incluir tags de la conversación en la respuesta |
tag_id |
uuid | Filtrar por ID de etiqueta |
tag_ids |
uuid[] | Filtrar por múltiples UUIDs de etiquetas (separados por coma o array) |
untagged |
boolean | Mostrar solo conversaciones sin etiquetas |
format |
string | Usar formato de respuesta optimizado para chat (chat) |
?format=chat: La Chat API devuelve los mismos datos que los endpoints estándar, pero con campos adicionales optimizados para renderizado de UI. También puede usar ?format=chat en los endpoints estándar.
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/conversations?unread=true&per_page=20" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440045",
"contact_number": "5511999999999",
"contact_name": "John Doe",
"display_name": "John Doe",
"is_group": false,
"profile_picture_url": "https://...",
"last_message": "Ok, deal!",
"last_message_at": "2025-01-15T10:30:00Z",
"unread_count": 2,
"is_archived": false
}
],
"meta": {
"pagination": {
"total": 100,
"per_page": 20,
"current_page": 1,
"last_page": 5
}
}
}
/conversations/{uuid}
Devuelve detalles de una conversación específica.
/conversations/{uuid}/messages
Devuelve el historial de mensajes de una conversación.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
from |
datetime | Fecha inicial (ISO 8601) |
to |
datetime | Fecha final (ISO 8601) |
before_id |
integer | Mensajes antes de este ID |
after_id |
integer | Mensajes después de este ID |
limit |
integer | Límite de mensajes (máx 100) |
format |
string | Usar formato de respuesta optimizado para chat (chat) |
?format=chat: Devuelve mensajes con formatted_body (@menciones resueltas) y reacciones agrupadas.
/conversations/{uuid}/mark-read
Marca una conversación como leída.
/conversations/{uuid}/archive
Archiva una conversación.
Respuesta
{
"success": true,
"message": "Conversation archived.",
"data": {
"archived_id": "550e8400-e29b-41d4-a716-446655440045",
"archived_at": "2025-12-29T12:00:00.000000Z"
}
}
/conversations/{uuid}/archive
Restaura una conversación archivada a estado activo.
El UUID debe ser de una conversación archivada. Use GET /conversations/archived para listar conversaciones archivadas.
Respuesta
{
"success": true,
"message": "Conversation restored.",
"data": {
"conversation_id": "550e8400-e29b-41d4-a716-446655440045",
"restored": true
}
}
/conversations/{uuid}
Elimina una conversación y sus mensajes.
Control de Automatización
Gestione la automatización de IA para conversaciones. Cuando la automatización está activa, los mensajes manuales están bloqueados hasta que asuma el chat.
Importante: Comportamiento de la Automatización
- Cuando la automatización está activa, los mensajes manuales están bloqueados para evitar conflictos con las respuestas de IA.
- Use "pause" para asumir el chat y enviar mensajes manualmente.
- Use "resume" para dejar que la IA maneje la conversación nuevamente.
- IMPORTANTE: Para reanudar la automatización, primero debe archivar la conversación.
Seguridad: Archivo Requerido para Reanudar
La automatización solo puede reanudarse después de archivar la conversación. Esto asegura que la sesión de servicio manual se cierre correctamente antes de devolver el control a la IA. Al reanudar, la conversación se desarchivará automáticamente.
/conversations/{uuid}/automation
Devuelve el estado actual de la automatización para una conversación.
Respuesta
{
"success": true,
"data": {
"conversation_id": "550e8400-e29b-41d4-a716-446655440045",
"automation_status": "active",
"is_automation_active": true,
"can_send_manual_message": false,
"paused_at": null,
"paused_by": null,
"pause_reason": null
}
}
/conversations/{uuid}/automation/pause
Pausa la automatización para una conversación, permitiendo mensajes manuales.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
reason |
string | No | Razón opcional para pausar la automatización |
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/conversations/550e8400-e29b-41d4-a716-446655440045/automation/pause" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"reason": "Manual takeover for VIP client"}'
Respuesta
{
"success": true,
"message": "Automation paused. You can now send messages manually.",
"data": {
"automation_status": "paused",
"paused_at": "2025-12-20T14:30:00Z",
"paused_by": "John Doe"
}
}
/conversations/{uuid}/automation/resume
Reanuda la automatización para una conversación, dejando que la IA maneje las respuestas.
Respuesta
{
"success": true,
"message": "Automation resumed. AI will handle this conversation.",
"data": {
"automation_status": "active"
}
}
/conversations/automation/bulk-pause
Pausa la automatización para múltiples conversaciones a la vez.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
conversation_ids |
array | Sí | Array de IDs de conversaciones a procesar |
reason |
string | No | Razón opcional para pausar la automatización |
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/conversations/automation/bulk-pause" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"conversation_ids": ["550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002", "550e8400-e29b-41d4-a716-446655440003"]}'
Respuesta
{
"success": true,
"message": "3 conversations paused successfully."
}
/conversations/automation/bulk-resume
Reanuda la automatización para múltiples conversaciones a la vez.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
conversation_ids |
array | Sí | Array de IDs de conversaciones a procesar |
Respuesta
{
"success": true,
"message": "3 conversations resumed successfully."
}
Contactos
/contacts
Lista todos los contactos guardados.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
instance_id |
string | Filtrar por instancia (UUID) |
search |
string | Buscar por nombre o número |
per_page |
integer | Items por página (máx 100) |
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/contacts?search=john&per_page=50" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"data": [
{
"id": 1,
"phone_number": "5511999999999",
"name": "John Doe",
"display_name": "John",
"email": "john@example.com",
"company": "Acme Inc",
"notes": "VIP customer",
"profile_picture_url": "https://...",
"is_business": false,
"created_at": "2025-01-15T10:30:00Z"
}
],
"meta": {
"pagination": {
"total": 500,
"per_page": 50,
"current_page": 1,
"last_page": 10
}
}
}
/contacts
Crea un nuevo contacto.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
instance_id |
string | Sí | ID da instância |
phone_number |
string | Sí | Número de teléfono del contacto |
name |
string | No | Nombre del contacto |
email |
string | No | Email del contacto |
company |
string | No | Empresa del contacto |
notes |
string | No | Notas sobre el contacto |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/contacts \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"phone_number": "+5511999999999",
"name": "John Doe",
"email": "john@example.com",
"company": "Acme Inc",
"notes": "Met at conference"
}'
/contacts/{id}
Devuelve detalles de un contacto específico.
/contacts/{id}
Actualiza un contacto existente.
Parámetros
| Campo | Tipo | Descripción |
|---|---|---|
name |
string | Nombre del contacto |
email |
string | Email del contacto |
company |
string | Empresa del contacto |
notes |
string | Notas sobre el contacto |
/contacts/{id}
Elimina un contacto.
/contacts/import
Importa múltiples contactos a la vez.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
instance_id |
string | Sí | ID da instância |
contacts |
array | Sí | Array de objetos de contacto |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/contacts/import \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"contacts": [
{"phone_number": "+5511999999999", "name": "John Doe"},
{"phone_number": "+5511888888888", "name": "Jane Smith"}
]
}'
Respuesta
{
"success": true,
"message": "Contacts imported successfully",
"data": {
"imported": 2,
"skipped": 0,
"errors": []
}
}
/contacts/export
Exporta contactos en formato JSON o CSV.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
instance_id |
string | Filtrar por instancia (UUID) |
format |
string | json, csv (default: json) |
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/contacts/export?format=csv" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Webhooks
Sistema de Webhooks
Los webhooks le permiten recibir notificaciones en tiempo real sobre eventos en sus instancias de WhatsApp.
Webhooks de Entrada
URLs que Zapini usa para recibir datos de sus instancias WhatsApp.
Webhooks de Salida
URLs que usted configura para recibir notificaciones de Zapini.
Webhooks de Salida
Recibe notificaciones en tiempo real en tu servidor
Configura webhooks para recibir notificaciones en tiempo real cuando ocurran eventos en tu instancia de WhatsApp. Zapini enviará solicitudes HTTP POST a tu URL configurada con los datos del evento.
Cómo Configurar
- Ve a la configuración de tu Token de API y haz clic en "Configurar Webhook"
- Ingresa tu URL de webhook (debe ser HTTPS en producción)
- Genera o ingresa una clave secreta para verificación de firma
- Selecciona qué eventos deseas recibir y guarda
Eventos Disponibles
| Evento | Descripción |
|---|---|
message.received |
Nuevo mensaje recibido |
message.sent |
Mensaje enviado |
message.status |
Estado del mensaje cambiado (enviado, entregado, leído) |
instance.connected |
Instancia conectó a WhatsApp |
instance.disconnected |
Instancia desconectó |
instance.qr |
Nuevo código QR generado |
Entendiendo los IDs de Mensaje
Cada mensaje tiene dos identificadores. Usa el correcto según tu caso de uso:
| Campo | Formato | Uso |
|---|---|---|
message_id |
UUID (e.g., 055f01b2-da7b-476b-...) |
Clave primaria para deduplicación y seguimiento en tu sistema |
whatsapp_message_id |
WhatsApp ID (e.g., 3EB0ABC123456789) |
Requerido para reacciones, respuestas y operaciones de WhatsApp |
Tip: Cómo evitar duplicados
Almacena el message_id cuando recibas un webhook. Antes de procesar nuevos webhooks, verifica si el message_id ya existe en tu base de datos. Si existe, actualiza el registro existente en lugar de crear uno nuevo.
Formato de Solicitud
Cada solicitud de webhook se envía como HTTP POST con los siguientes headers:
POST https://your-server.com/webhook
Content-Type: application/json
X-Webhook-Signature: a1b2c3d4e5f6...
X-Webhook-Event: message.received
X-Instance-UUID: 550e8400-e29b-41d4-a716-446655440000
User-Agent: Zapini-Webhook/1.0
Headers del Webhook
| Header | Descripción |
|---|---|
X-Webhook-Signature |
Firma HMAC-SHA256 del payload JSON usando tu clave secreta |
X-Webhook-Event |
El tipo de evento que disparó este webhook |
X-Instance-UUID |
UUID de la instancia de WhatsApp |
User-Agent |
Zapini-Webhook/1.0 |
Ejemplos de Payload
message.received
{
"event": "message.received",
"instance_uuid": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2025-01-15T10:30:00+00:00",
"data": {
"message_id": "055f01b2-da7b-476b-9a5d-dcecb3fe510c",
"whatsapp_message_id": "3EB0ABC123456789",
"sender_number": "5511999999999",
"sender_name": "John Doe",
"content": "Hello, I need help!",
"media_type": null,
"media_url": null,
"timestamp": "2025-01-15T10:30:00+00:00",
"conversation_id": 123
}
}
message.sent
{
"event": "message.sent",
"instance_uuid": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2025-01-15T10:31:00+00:00",
"data": {
"message_id": "f4a2e8c9-7b3d-4e5f-8a1c-2d9e6f0a3b7c",
"whatsapp_message_id": "3EB0ABC123456789",
"recipient_number": "5511888888888",
"content": "Thanks for contacting us!",
"media_type": null,
"media_url": null,
"timestamp": "2025-01-15T10:31:00+00:00",
"conversation_id": 123
}
}
message.status
{
"event": "message.status",
"instance_uuid": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2025-01-15T10:32:00+00:00",
"data": {
"message_id": "f4a2e8c9-7b3d-4e5f-8a1c-2d9e6f0a3b7c",
"whatsapp_message_id": "3EB0ABC123456789",
"previous_status": "sent",
"new_status": "delivered",
"recipient_number": "5511888888888",
"timestamp": "2025-01-15T10:32:00+00:00"
}
}
instance.connected
{
"event": "instance.connected",
"instance_uuid": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2025-01-15T10:00:00+00:00",
"data": {
"previous_status": "qr_ready",
"new_status": "connected",
"phone_number": "5511999999999"
}
}
/webhooks/instance/{uuid}/incoming
Recibe mensajes entrantes de las instancias WhatsApp.
Formato del Payload
{
"remoteJid": "5511999999999@s.whatsapp.net",
"message": {
"conversation": "Hello, how are you?",
"extendedTextMessage": null,
"imageMessage": null,
"videoMessage": null,
"audioMessage": null,
"documentMessage": null
},
"messageTimestamp": 1705312200,
"pushName": "John Doe",
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"fromMe": false,
"id": "3EB0ABC123456789"
},
"participant": null,
"isGroup": false
}
Tipos de Mensaje
| Tipo | Campo | Descripción |
|---|---|---|
| Text | message.conversation |
Mensaje de texto simple |
| Extended Text | message.extendedTextMessage |
Texto con vista previa de enlace |
| Image | message.imageMessage |
Imagen con leyenda |
| Video | message.videoMessage |
Mensaje de video |
| Audio | message.audioMessage |
Mensaje de audio/voz |
| Document | message.documentMessage |
Archivo/documento |
Ejemplo - Mensaje de Texto
curl -X POST https://zapini.app/webhooks/instance/{uuid}/incoming \
-H "Content-Type: application/json" \
-d '{
"remoteJid": "5511999999999@s.whatsapp.net",
"message": {
"conversation": "Hello!"
},
"messageTimestamp": 1705312200,
"pushName": "Customer Name",
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"fromMe": false,
"id": "ABC123"
}
}'
/webhooks/instance/{uuid}/status
Recibe actualizaciones de estado de mensajes enviados.
Formato del Payload
{
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"id": "3EB0ABC123456789",
"fromMe": true
},
"status": 3,
"messageTimestamp": 1705312200
}
Códigos de Estado
| Código | Status | Descripción |
|---|---|---|
1 |
pending | Mensaje pendiente de envío |
2 |
sent | Mensaje enviado al servidor |
3 |
delivered | Mensaje entregado al destinatario |
4 |
read | Mensaje leído por el destinatario |
5 |
played | Audio/video reproducido |
/webhooks/instance/{uuid}/qr
Recibe actualizaciones de código QR para conexión.
Formato del Payload
{
"qr": "2@ABC123...",
"qr_image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"generated_at": "2025-01-15T10:30:00Z"
}
/webhooks/instance/{uuid}/connection
Recibe actualizaciones del estado de conexión de la instancia.
Formato del Payload
{
"status": "connected",
"phone_number": "5511999999999",
"timestamp": "2025-01-15T10:30:00Z"
}
Estados de Conexión
| Status | Descripción |
|---|---|
| connected | Instancia conectada y funcionando |
| qr_ready | Código QR listo para escanear |
| disconnected | Instancia desconectada |
| offline | Instancia offline |
/webhooks/instance/{uuid}/reaction
Recibe reacciones emoji en mensajes.
Formato del Payload
{
"key": {
"remoteJid": "5511999999999@s.whatsapp.net",
"id": "3EB0ABC123456789",
"fromMe": false
},
"reaction": {
"text": "👍",
"key": {
"id": "3EB0DEF987654321"
}
},
"senderJid": "5511888888888@s.whatsapp.net"
}
/instances/{uuid}/webhook
Configure una URL externa para recibir notificaciones de eventos.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
webhook_url |
string | Sí | URL que recibirá las notificaciones vía POST |
webhook_secret |
string | No | Clave secreta para firma de solicitudes |
events |
array | No | Eventos que dispararán el webhook |
is_active |
boolean | No | Activar o desactivar el webhook |
Eventos Disponibles
Ejemplo
curl -X PUT https://instance-{id}.zapini.app/instances/550e8400-e29b-41d4-a716-446655440000/webhook \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-server.com/webhook",
"webhook_secret": "your_secret_key_here",
"events": ["message.incoming", "message.status"],
"is_active": true
}'
Seguridad de Webhooks
Todas las solicitudes de webhook incluyen una firma HMAC para verificación de autenticidad.
Verificación de Firma
Cada solicitud incluye un header X-Webhook-Signature con la firma HMAC-SHA256 del payload.
Header:
X-Webhook-Signature: a1b2c3d4e5f6789...
Verificar Firma (PHP)
<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$secret = 'your_webhook_secret';
$expected = hash_hmac('sha256', $payload, $secret);
if (hash_equals($expected, $signature)) {
// Signature is valid
$data = json_decode($payload, true);
// Process webhook...
} else {
http_response_code(401);
exit('Invalid signature');
}
Verificar Firma (Node.js)
const crypto = require('crypto');
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const secret = 'your_webhook_secret';
const payload = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
if (crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
)) {
// Signature is valid
console.log('Webhook received:', req.body);
res.status(200).send('OK');
} else {
res.status(401).send('Invalid signature');
}
});
Buenas Prácticas
- Siempre verifique la firma antes de procesar el webhook.
- Responda rápidamente (dentro de 5 segundos) para evitar timeouts.
- Use una cola para procesar webhooks de forma asíncrona.
- Implemente idempotencia para manejar webhooks duplicados.
- Registre todos los webhooks recibidos para depuración.
Medios
Gestión de Medios
Envíe y gestione archivos de medios como imágenes, videos, audios y documentos.
/media/upload
Sube un archivo de medios para uso posterior.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
file |
file | Sí | Archivo de medios para subir (multipart/form-data) |
type |
string | No | image, video, audio, document (auto-detected) |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/media/upload \
-H "Authorization: Bearer {token}" \
-F "file=@/path/to/image.jpg" \
-F "type=image"
Respuesta
{
"success": true,
"data": {
"id": "media_abc123xyz",
"url": "https://storage.zapini.app/media/abc123xyz.jpg",
"type": "image",
"mime_type": "image/jpeg",
"size": 102400,
"filename": "image.jpg",
"expires_at": "2025-01-22T10:30:00Z"
}
}
/media/{id}
Devuelve información de un archivo de medios.
Respuesta
{
"success": true,
"data": {
"id": "media_abc123xyz",
"url": "https://storage.zapini.app/media/abc123xyz.jpg",
"type": "image",
"mime_type": "image/jpeg",
"size": 102400,
"filename": "image.jpg",
"created_at": "2025-01-15T10:30:00Z",
"expires_at": "2025-01-22T10:30:00Z"
}
}
/media/{id}
Elimina un archivo de medios.
Ejemplo
curl -X DELETE https://instance-{id}.zapini.app/media/media_abc123xyz \
-H "Authorization: Bearer {token}"
/messages/send-media
Envía un mensaje con medios adjuntos.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
instance_id |
string | Sí | ID da instância |
recipient |
string | Sí | Número de WhatsApp del destinatario (con código de país) |
media_url |
string | Sí* | URL pública del archivo de medios |
media_id |
string | Sí* | ID de un medio previamente subido |
media_type |
string | Sí | image, video, audio, document |
caption |
string | No | Leyenda para imágenes y videos |
filename |
string | No | Nombre del archivo para documentos |
* Proporcione media_url O media_id
Ejemplo - Imagen
curl -X POST https://instance-{id}.zapini.app/messages/send-media \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"recipient": "+5511999999999",
"media_url": "https://example.com/image.jpg",
"media_type": "image",
"caption": "Check this image!"
}'
Ejemplo - Documento
curl -X POST https://instance-{id}.zapini.app/messages/send-media \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"recipient": "+5511999999999",
"media_url": "https://example.com/report.pdf",
"media_type": "document",
"filename": "Monthly_Report.pdf",
"caption": "Here is the monthly report"
}'
Límites de Medios
| Tipo | Tamaño Máximo | Formatos |
|---|---|---|
| Imágenes | 16 MB | jpg, jpeg, png, gif, webp |
| Videos | 64 MB | mp4, 3gp, mov, avi, mkv |
| Audio | 16 MB | mp3, ogg, wav, opus, aac, m4a |
| Documentos | 100 MB | pdf, doc, docx, xls, xlsx, ppt, pptx, txt, zip |
/messages/{uuid}/media
Descarga medios recibidos en un mensaje.
Ejemplo
curl -X GET https://instance-{id}.zapini.app/messages/660e8400-e29b-41d4-a716-446655440001/media \
-H "Authorization: Bearer {token}" \
--output downloaded_media.jpg
Respuesta
Devuelve el archivo binario con el Content-Type apropiado.
Grupos
Gestione grupos de WhatsApp a través de la API. Cree grupos, agregue/elimine participantes, actualice configuraciones y más.
/instances/{uuid}/groups
Devuelve todos los grupos de WhatsApp de la instancia.
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/instances/{uuid}/groups" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"data": {
"groups": [
{
"jid": "120363001234567890@g.us",
"subject": "Marketing Team",
"owner": "5511987654321@s.whatsapp.net",
"size": 25,
"description": "Team discussions"
}
],
"total": 5
}
}
/instances/{uuid}/groups
Crea un nuevo grupo de WhatsApp.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
subject |
string | Sí | api-docs.group_subject_desc |
participants |
array | Sí | api-docs.group_participants_desc |
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/instances/{uuid}/groups" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"subject": "My New Group",
"participants": ["5511987654321", "5511976543210"]
}'
Respuesta
{
"success": true,
"data": {
"group": {
"jid": "120363001234567890@g.us",
"subject": "My New Group"
},
"message": "Group created successfully"
}
}
/instances/{uuid}/groups/{jid}
Devuelve metadatos detallados de un grupo específico.
Respuesta
{
"success": true,
"data": {
"jid": "120363001234567890@g.us",
"subject": "Marketing Team",
"description": "Team discussions",
"owner": "5511987654321@s.whatsapp.net",
"participants": [
{"jid": "5511987654321@s.whatsapp.net", "admin": "superadmin"},
{"jid": "5511976543210@s.whatsapp.net", "admin": null}
],
"size": 25
}
}
/instances/{uuid}/groups/{jid}
Actualiza el nombre y/o descripción del grupo.
Cuerpo de la Solicitud
| Campo | Tipo | Descripción |
|---|---|---|
subject |
string | Nuevo nombre del grupo |
description |
string | Nueva descripción del grupo |
Ejemplo
curl -X PATCH "https://instance-{id}.zapini.app/instances/{uuid}/groups/{jid}" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"subject": "New Group Name",
"description": "Updated description"
}'
/instances/{uuid}/groups/{jid}/participants
Agrega uno o más participantes al grupo.
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/instances/{uuid}/groups/{jid}/participants" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"participants": ["5511987654321", "5511976543210"]
}'
/instances/{uuid}/groups/{jid}/participants
Elimina uno o más participantes del grupo.
Ejemplo
curl -X DELETE "https://instance-{id}.zapini.app/instances/{uuid}/groups/{jid}/participants" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"participants": ["5511987654321"]
}'
/instances/{uuid}/groups/{jid}/admins
api-docs.groups_promote_desc
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/instances/{uuid}/groups/{jid}/admins" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"participants": ["5511987654321"]
}'
/instances/{uuid}/groups/{jid}/admins
api-docs.groups_demote_desc
Ejemplo
curl -X DELETE "https://instance-{id}.zapini.app/instances/{uuid}/groups/{jid}/admins" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"participants": ["5511987654321"]
}'
/instances/{uuid}/groups/{jid}/leave
Hace que la instancia salga de un grupo.
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/instances/{uuid}/groups/{jid}/leave" \
-H "Authorization: Bearer {token}"
/instances/{uuid}/groups/{jid}/invite
api-docs.groups_invite_get_desc
Respuesta
{
"success": true,
"data": {
"code": "AbCdEfGhIjKl",
"invite_link": "https://chat.whatsapp.com/AbCdEfGhIjKl"
}
}
/instances/{uuid}/groups/{jid}/invite
api-docs.groups_invite_revoke_desc
Respuesta
{
"success": true,
"data": {
"new_code": "MnOpQrStUvWx",
"new_invite_link": "https://chat.whatsapp.com/MnOpQrStUvWx"
},
"message": "Invite link revoked"
}
Etiquetas
Gestione etiquetas de conversaciones para organizar y categorizar chats. Las etiquetas están limitadas por tenant y pueden asignarse a múltiples conversaciones.
/tags
Lista todas las etiquetas del tenant actual.
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/tags" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"data": {
"tags": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "VIP",
"color": "#f59e0b",
"conversations_count": 15,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"name": "Support",
"color": "#3b82f6",
"conversations_count": 42,
"created_at": "2025-01-15T10:35:00Z",
"updated_at": "2025-01-15T10:35:00Z"
}
]
}
}
/tags
Crea una nueva etiqueta.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name |
string | Sí | Nombre de la etiqueta (único por tenant) (max 50) |
color |
string | Sí | Código de color hexadecimal para la etiqueta (#RRGGBB) |
Ejemplo
curl -X POST "https://instance-{id}.zapini.app/tags" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Important",
"color": "#ef4444"
}'
Respuesta
{
"success": true,
"message": "Tag created successfully",
"data": {
"tag": {
"id": "550e8400-e29b-41d4-a716-446655440003",
"name": "Important",
"color": "#ef4444",
"conversations_count": 0,
"created_at": "2025-01-15T12:00:00Z",
"updated_at": "2025-01-15T12:00:00Z"
}
}
}
/tags/{uuid}
Devuelve detalles de una etiqueta específica.
Ejemplo
curl -X GET "https://instance-{id}.zapini.app/tags/550e8400-e29b-41d4-a716-446655440001" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
/tags/{uuid}
Actualiza una etiqueta existente.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name |
string | No | Nombre de la etiqueta (único por tenant) (max 50) |
color |
string | No | Código de color hexadecimal para la etiqueta (#RRGGBB) |
Ejemplo
curl -X PATCH "https://instance-{id}.zapini.app/tags/550e8400-e29b-41d4-a716-446655440001" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Very Important",
"color": "#dc2626"
}'
/tags/{uuid}
Elimina una etiqueta. La etiqueta se eliminará automáticamente de todas las conversaciones.
Ejemplo
curl -X DELETE "https://instance-{id}.zapini.app/tags/550e8400-e29b-41d4-a716-446655440001" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"
Respuesta
{
"success": true,
"message": "Tag deleted successfully"
}
/conversations/{uuid}/tags
Actualiza las etiquetas asignadas a una conversación. Esto reemplaza todas las etiquetas existentes con la lista proporcionada.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tag_ids |
array | Sí | Array de UUIDs de etiquetas para asignar a la conversación |
Ejemplo
curl -X PUT "https://instance-{id}.zapini.app/conversations/550e8400-e29b-41d4-a716-446655440000/tags" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"tag_ids": ["550e8400-e29b-41d4-a716-446655440001", "550e8400-e29b-41d4-a716-446655440002"]
}'
Respuesta
{
"success": true,
"message": "Conversation tags updated",
"data": {
"tags": [
{"id": "550e8400-e29b-41d4-a716-446655440001", "name": "VIP", "color": "#f59e0b"},
{"id": "550e8400-e29b-41d4-a716-446655440002", "name": "Support", "color": "#3b82f6"},
{"id": "550e8400-e29b-41d4-a716-446655440003", "name": "Important", "color": "#ef4444"}
]
}
}
Para eliminar todas las etiquetas de una conversación, envíe un array vacío: {"tag_ids": []}
Chat API
OPTIMIZADO PARA UIEndpoints optimizados para crear interfaces de chat tipo WhatsApp. Devuelve datos preformateados con @menciones resueltas, reacciones agrupadas y helpers de alineación.
formatted_body
@menciones pre-resueltas en formato HTML
grouped_reactions
Reacciones agrupadas con conteo
is_from_me
Alineación fácil con is_from_me
tags
Tags de conversaciones incluidos
La Chat API devuelve los mismos datos que los endpoints estándar, pero con campos adicionales optimizados para renderizado de UI. También puede usar ?format=chat en los endpoints estándar.
/api/v1/conversations?format=chat
/api/v1/chat/conversations
Lista conversaciones con tags, fotos de perfil y conteo de no leídos optimizado para UI de lista de chat.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
instance_id |
string | Filtrar por instancia (UUID) |
search |
string | Buscar por nombre o número |
unread |
boolean | Mostrar solo conversaciones no leídas |
per_page |
integer | Items por página (máx 100) |
Ejemplo
curl -X GET "https://zapini.app/api/v1/chat/conversations?unread=true" \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440045",
"contact_number": "5521999999999",
"display_name": "John Doe",
"is_group": false,
"profile_picture_url": "https://...",
"last_message": "Hello!",
"last_message_at": "2025-12-16T10:00:00Z",
"unread_count": 3,
"tags": [
{"id": "bf287f4d-037c-4280-8413-c7b7d08df5a0", "name": "VIP", "color": "#f59e0b"}
],
"instance": {
"uuid": "21ed5c9b-51a0-4569-85db-05433ea414b7",
"phone_number": "5511988887777",
"status": "connected"
}
}
],
"meta": {
"pagination": {
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4
}
}
}
/api/v1/chat/conversations/{uuid}/messages
Devuelve mensajes con formatted_body (@menciones resueltas) y reacciones agrupadas.
Parámetros de Consulta
| Campo | Tipo | Descripción |
|---|---|---|
before_id |
integer | Mensajes antes de este ID |
after_id |
integer | Mensajes después de este ID |
limit |
integer | Límite de mensajes (máx 100) |
Ejemplo
curl -X GET "https://zapini.app/api/v1/chat/conversations/550e8400-e29b-41d4-a716-446655440045/messages?limit=50" \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"data": {
"messages": [
{
"id": 456,
"unique_id": "msg-abc-123",
"direction": "incoming",
"is_from_me": false,
"message_body": "Ola @5521999999999!",
"formatted_body": "Ola <span class=\"mention\" data-phone=\"5521999999999\">@John Doe</span>!",
"mentioned_jids": ["5521999999999@s.whatsapp.net"],
"sender_name": "Maria",
"status": "read",
"grouped_reactions": [
{
"emoji": "👍",
"count": 2,
"has_my_reaction": true,
"reactors": ["5521988887777", "5521966665555"],
"reactor_names": ["Carlos", "Ana"]
}
],
"created_at": "2025-12-16T10:00:00Z"
}
],
"has_more": true,
"oldest_id": 400,
"newest_id": 456
}
}
Características Principales
formatted_body
Texto del mensaje con @menciones resueltas a nombres de contactos. Devuelve HTML con spans clicables.
Hola @Juan García!
is_from_me
Boolean indicando si el mensaje fue enviado por tu instancia. Usar para alineación de mensajes.
grouped_reactions
Reacciones agrupadas por emoji con conteos e información de los reactores.
{"emoji": "👍", "count": 2, "has_my_reaction": true}
mentioned_jids
Array de JIDs de WhatsApp mencionados en el mensaje.
/api/v1/chat/send
Envía un mensaje de texto y devuelve el mensaje en formato optimizado para chat.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
instance_id |
string | Sí | UUID de la instancia (requerido) |
recipient |
string | Sí | Número de teléfono del destinatario con código de país |
message |
string | Sí | Contenido del mensaje de texto |
reply_to |
string | No | ID del mensaje para responder |
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/send" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "777",
"recipient": "5521999999999",
"message": "Hello from Chat API!"
}'
/api/v1/chat/send-media
Envía media (imagen, video, audio, documento) y devuelve respuesta optimizada para chat.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
instance_id |
string | Sí | UUID de la instancia (requerido) |
recipient |
string | Sí | Número de teléfono del destinatario con código de país |
media_url |
string | Sí | URL del archivo de media a enviar |
media_type |
string | Sí | Tipo de media (image, video, audio, document) |
caption |
string | No | Leyenda para imagen/video |
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/send-media" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_id": "777",
"recipient": "5521999999999",
"media_url": "https://example.com/image.jpg",
"media_type": "image",
"caption": "Check this out!"
}'
/api/v1/chat/messages/{uuid}
Edita el contenido de un mensaje enviado.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
message |
string | Sí | Nuevo contenido del mensaje |
Ejemplo
curl -X PATCH "https://zapini.app/api/v1/chat/messages/msg-abc-123" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"message": "Updated message content"}'
/api/v1/chat/messages/{uuid}
Elimina un mensaje enviado.
Ejemplo
curl -X DELETE "https://zapini.app/api/v1/chat/messages/msg-abc-123" \
-H "Authorization: Bearer {token}"
/api/v1/chat/messages/{uuid}/reaction
Agrega una reacción emoji a un mensaje.
Parámetros
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
emoji |
string | Sí | Emoji para reaccionar |
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/messages/msg-abc-123/reaction" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"emoji": "👍"}'
/api/v1/chat/messages/{uuid}/reaction
Elimina una reacción de un mensaje.
Ejemplo
curl -X DELETE "https://zapini.app/api/v1/chat/messages/msg-abc-123/reaction" \
-H "Authorization: Bearer {token}"
/api/v1/chat/conversations/{uuid}/mark-read
Marca una conversación como leída.
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/conversations/550e8400-e29b-41d4-a716-446655440045/mark-read" \
-H "Authorization: Bearer {token}"
/api/v1/chat/conversations/{uuid}/archive
Archiva una conversación.
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/conversations/550e8400-e29b-41d4-a716-446655440045/archive" \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"message": "Conversation archived.",
"data": {
"archived_id": "550e8400-e29b-41d4-a716-446655440045",
"archived_at": "2025-12-29T12:00:00.000000Z"
}
}
/api/v1/chat/conversations/{uuid}/archive
Restaura una conversación archivada a estado activo.
El UUID debe ser de una conversación archivada. Use GET /conversations/archived para listar conversaciones archivadas.
Ejemplo
curl -X DELETE "https://zapini.app/api/v1/chat/conversations/550e8400-e29b-41d4-a716-446655440045/archive" \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"message": "Conversation restored.",
"data": {
"conversation_id": "550e8400-e29b-41d4-a716-446655440045",
"restored": true
}
}
/api/v1/chat/conversations/{uuid}/pause-automation
Pausar la automatización de una conversación para permitir el envío de mensajes manuales.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
reason |
string | No | Razón opcional para pausar la automatización |
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/conversations/550e8400-e29b-41d4-a716-446655440045/pause-automation" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"reason": "Manual takeover"}'
/api/v1/chat/conversations/{uuid}/resume-automation
Reanudar la automatización de una conversación, devolviendo el control al sistema automatizado.
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/conversations/550e8400-e29b-41d4-a716-446655440045/resume-automation" \
-H "Authorization: Bearer {token}"
Transcripción de Audio
Los campos de transcripción también se incluyen en el objeto de mensaje retornado por el endpoint de mensajes. Los mensajes de audio con auto-transcripción habilitada tendrán las transcripciones pobladas automáticamente.
/api/v1/chat/messages/{uuid}/transcription
Obtiene el estado y texto de la transcripción de un mensaje de audio.
Ejemplo
curl -X GET "https://zapini.app/api/v1/chat/messages/msg-abc-123/transcription" \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"data": {
"message_id": "msg-abc-123",
"audio_transcription": "Olá, tudo bem? Gostaria de saber mais sobre o produto.",
"transcription_status": "completed",
"transcription_language": "pt",
"transcription_error": null,
"transcription_completed_at": "2026-02-21T10:30:00.000000Z"
}
}
Campos de Respuesta
| Campo | Tipo | Descripción |
|---|---|---|
audio_transcription |
string|null | El texto transcrito (null si aún no está completado) |
transcription_status |
string|null | Estado: pending, processing, completed o failed |
transcription_language |
string|null | Código de idioma detectado o configurado (ej. pt, en, es) |
transcription_error |
string|null | Mensaje de error si la transcripción falló |
transcription_completed_at |
string|null | Timestamp de cuando la transcripción fue completada |
/api/v1/chat/messages/{uuid}/transcription
Solicita la transcripción de un mensaje de audio. Si ya fue completada, retorna la transcripción existente. Soporta proveedores Whisper, Gemini y ElevenLabs.
Ejemplo
curl -X POST "https://zapini.app/api/v1/chat/messages/msg-abc-123/transcription" \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"message": "Transcription queued successfully.",
"data": {
"message_id": "msg-abc-123",
"transcription_status": "pending"
}
}
Automatizaciones
IMPORTANTEAviso Importante sobre Automatizaciones
Si tu instancia tiene automatizaciones (flujos o integraciones) activas, el envío de mensajes vía API puede estar bloqueado. Lee esta sección para entender cómo funciona.
¿Qué son las Automatizaciones?
Las automatizaciones son flujos automatizados que responden mensajes automáticamente. El sistema tiene dos tipos de automatización:
Flujos
Flujos de conversación creados en el editor visual que responden automáticamente basándose en reglas y condiciones.
Integraciones
Conexiones con sistemas externos (webhooks, APIs, IA) que procesan y responden mensajes automáticamente.
Bloqueo de Mensajes
Cuando una conversación tiene automatización activa, el envío de mensajes vía API está bloqueado para evitar conflictos entre respuestas automáticas y manuales.
Respuesta de Error
{
"success": false,
"error": {
"code": "AUTOMATION_ACTIVE",
"message": "Cannot send messages. This conversation has active automation. Pause the automation first to send messages manually.",
"conversation_id": 123
}
}
¿Cuándo se Bloquea el Envío?
- • La instancia tiene un flujo o integración activa
- • La conversación no fue pausada manualmente
- • La conversación todavía está siendo gestionada por la automatización
Cómo Enviar Mensajes con Automatización Activa
Para enviar mensajes manualmente cuando hay automatización activa, necesitas pausar la automatización para la conversación específica:
Verifica el Estado
Usa el endpoint de detalles de la conversación para verificar el campo automation_status.
Pausa la Automatización
Si automation_status es "active", usa el endpoint de pausa para permitir mensajes manuales.
Envía el Mensaje
Después de pausar, puedes enviar mensajes normalmente vía API.
/api/v1/chat/conversations/{uuid}
Verifica el estado de automatización de una conversación antes de intentar enviar mensajes.
Campos de Respuesta
| Campo | Tipo | Descripción |
|---|---|---|
automation_status |
string | Estado actual de la automatización (active o paused) |
can_send_manual_message |
boolean | Si puedes enviar mensajes manuales |
automation_paused_at |
datetime|null | Fecha/hora cuando la automatización fue pausada |
Valores de Estado
| Status | Descripción | ¿Puede Enviar vía API? |
|---|---|---|
active |
La automatización está respondiendo mensajes automáticamente | No |
paused |
Automatización pausada, el usuario ha tomado el control | Sí |
/api/v1/chat/conversations/{uuid}/pause-automation
Pausa la automatización para permitir envío de mensajes manuales vía API.
Cuerpo de la Solicitud (optional)
| Campo | Tipo | Descripción |
|---|---|---|
reason |
string | Motivo opcional para pausar (ej.: "Intervención manual requerida") |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/api/v1/chat/conversations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/pause-automation \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"reason": "Manual intervention required"}'
Ejemplo de Respuesta
{
"success": true,
"message": "Automation paused successfully",
"data": {
"conversation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"automation_paused": true,
"paused_at": "2025-01-15T10:30:00+00:00",
"paused_by": "John Doe",
"reason": "Manual intervention required"
}
}
/api/v1/chat/conversations/{uuid}/resume-automation
Reanuda la automatización, devolviendo el control al sistema automatizado.
Ejemplo
curl -X POST https://instance-{id}.zapini.app/api/v1/chat/conversations/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resume-automation \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json"
Ejemplo de Respuesta
{
"success": true,
"message": "Automation resumed successfully",
"data": {
"conversation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"automation_paused": false,
"resumed_at": "2025-01-15T11:00:00+00:00"
}
}
Operaciones en Lote
Pausa o reanuda la automatización de múltiples conversaciones a la vez. Útil para mantenimiento, campañas o procesamiento por lotes. Máximo de 100 conversaciones por solicitud.
/api/v1/conversations/automation/bulk-pause
Pausa la automatización de múltiples conversaciones a la vez. Omite conversaciones que ya están pausadas o no tienen automatización activa.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
conversation_ids |
array | Sí | Array de UUIDs de conversaciones (máx 100) |
reason |
string | No | Motivo opcional para pausar (ej.: "Intervención manual requerida") |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/api/v1/conversations/automation/bulk-pause \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"conversation_ids": [
"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"b2c3d4e5-f6a7-8901-bcde-f12345678901"
],
"reason": "Bulk pause for maintenance"
}'
Respuesta
{
"success": true,
"message": "2 conversations paused",
"data": {
"paused": 2,
"skipped": 0,
"errors": 0
}
}
/api/v1/conversations/automation/bulk-resume
Reanuda la automatización de múltiples conversaciones a la vez. Omite conversaciones que no están pausadas o no tienen automatización activa.
Cuerpo de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
conversation_ids |
array | Sí | Array de UUIDs de conversaciones (máx 100) |
Ejemplo
curl -X POST https://instance-{id}.zapini.app/api/v1/conversations/automation/bulk-resume \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"conversation_ids": [
"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"b2c3d4e5-f6a7-8901-bcde-f12345678901"
]
}'
Respuesta
{
"success": true,
"message": "2 automations resumed",
"data": {
"resumed": 2,
"skipped": 0,
"errors": 0
}
}
Mejores Prácticas
- Siempre verifica can_send_manual_message antes de enviar mensajes para evitar errores.
- Pausa la automatización solo cuando sea necesario para intervención humana.
- Reanuda la automatización después del servicio manual para mantener una experiencia consistente.
API de Voz & IVR
62 endpointsVisión General de la API de Voz
La API de Voz permite gestionar toda la infraestructura de telefonía programáticamente: números de teléfono, configuración IVR, llamadas, colas, callbacks, skills de agentes y clonación de voz.
URL Base
https://zapini.app/api/v1/voice
Autenticación
Autenticación Bearer Token + Permiso Twilio Voice
Endpoints
62 endpoints disponibles
Esta API requiere que la funcionalidad Twilio Voice esté habilitada en su tenant. Contacte al administrador para activarla.
Números de Teléfono
Gestione números de teléfono: registrar, configurar modo de atención (IA, humano, IVR), grabación, SIP y más.
Modos de atención disponibles
/voice/numbers
Gestione números de teléfono: registrar, configurar modo de atención (IA, humano, IVR), grabación, SIP y más.
Ejemplo
curl -X GET https://zapini.app/api/v1/voice/numbers \
-H "Authorization: Bearer {token}"
Respuesta
{
"success": true,
"data": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"phone_number": "+5511999999999",
"friendly_name": "Main Line",
"status": "active",
"connection_type": "twilio",
"call_handling_mode": "ai_only",
"ai_enabled": true,
"recording_enabled": false,
"ivr_enabled": false,
"created_at": "2026-02-14T10:00:00Z"
}
]
}
/voice/numbers
Register a new phone number.
Parámetros
| Parâmetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| phone_number | string | yes | E.164 format (+5511999999999) |
| friendly_name | string | no | Display name |
| connection_type | string | no | twilio, asterisk_sip, asterisk_hardphone |
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/numbers \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+5511999999999",
"friendly_name": "Main Line",
"connection_type": "twilio"
}'
/voice/numbers/{uuid}
Get full details of a phone number including AI config, SIP settings and business hours summary.
/voice/numbers/{uuid}
Update phone number settings.
Parámetros
| Parâmetro | Tipo | Descripción |
|---|---|---|
| friendly_name | string | Display name |
| call_handling_mode | string | ai_only, human_only, ai_with_handoff, ivr_menu |
| ai_system_prompt | string | AI system prompt for calls |
| ai_voice | string | AI voice ID |
| recording_enabled | boolean | Enable call recording |
| sip_enabled | boolean | Enable SIP |
| status | string | active, inactive |
/voice/numbers/{uuid}
Delete/release a phone number. Returns 204 on success.
Horario de Atención & Festivos
Configure horarios de atención y festivos para cada número. Las llamadas fuera de horario pueden redirigirse automáticamente.
/voice/numbers/{uuid}/business-hours
Get business hours schedule and current status (open/closed).
Respuesta
{
"success": true,
"data": {
"enabled": true,
"timezone": "America/Sao_Paulo",
"is_currently_open": true,
"schedule": {
"monday": { "enabled": true, "open": "09:00", "close": "18:00" },
"tuesday": { "enabled": true, "open": "09:00", "close": "18:00" },
"wednesday": { "enabled": true, "open": "09:00", "close": "18:00" },
"thursday": { "enabled": true, "open": "09:00", "close": "18:00" },
"friday": { "enabled": true, "open": "09:00", "close": "17:00" },
"saturday": { "enabled": false },
"sunday": { "enabled": false }
},
"outside_hours_action": "voicemail",
"outside_hours_message": "We are currently closed."
}
}
/voice/numbers/{uuid}/business-hours
Set full business hours schedule. Send the complete schedule object.
/voice/numbers/{uuid}/holidays
Gestione festivos con mensajes personalizados. Soporta festivos recurrentes (anuales) y fechas específicas.
Respuesta
{
"success": true,
"data": {
"holidays": [
{
"index": 0,
"name": "Christmas",
"date": "2026-12-25",
"recurring": true,
"message": "Merry Christmas!"
}
]
}
}
/voice/numbers/{uuid}/holidays
Add a single holiday. Required: name, date. Optional: recurring, message.
/voice/numbers/{uuid}/holidays
Replace all holidays. Send an array of holiday objects.
/voice/numbers/{uuid}/holidays/{index}
Remove a holiday by its index (0-based).
Configuración IVR
Configure menús interactivos de voz con opciones numéricas, mensajes TTS, recolección de datos, transferencias y más.
Tipos de Opción IVR
/voice/numbers/{uuid}/ivr
Get full IVR configuration including messages, timeouts and options.
Respuesta
{
"success": true,
"data": {
"ivr_enabled": true,
"ivr_welcome_message": "Welcome to our company.",
"ivr_menu_intro": "Press 1 for sales, 2 for support.",
"ivr_invalid_option_message": "Invalid option.",
"ivr_goodbye_message": "Goodbye!",
"ivr_input_timeout": 5,
"ivr_max_attempts": 3,
"options": [
{
"uuid": "a1b2c3d4...",
"digit": "1",
"label": "Sales",
"type": "transfer_agent",
"is_enabled": true,
"order": 1
}
]
}
}
/voice/numbers/{uuid}/ivr
Update IVR configuration.
Parámetros
| Parâmetro | Tipo | Descripción |
|---|---|---|
| ivr_enabled | boolean | Campos de configuración IVR |
| ivr_welcome_message | string | Mensaje de bienvenida reproducido al contestar |
| ivr_menu_intro | string | Texto del menú con las opciones disponibles |
| ivr_invalid_option_message | string | Mensaje para opción inválida |
| ivr_goodbye_message | string | Mensaje de despedida |
| ivr_input_timeout | integer | Tiempo de espera por input (1-30 segundos) |
| ivr_max_attempts | integer | Máximo de intentos inválidos (1-10) |
/voice/numbers/{uuid}/ivr/types
List all available IVR option types with descriptions.
/voice/numbers/{uuid}/ivr/options
Create a new IVR menu option.
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/numbers/{uuid}/ivr/options \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"digit": "1",
"label": "Sales Department",
"type": "transfer_agent",
"message": "Transferring you to our sales team.",
"is_enabled": true
}'
/voice/numbers/{uuid}/ivr/options
List all IVR menu options for a number, ordered by position.
/voice/numbers/{uuid}/ivr/options/{optionUuid}
Update an IVR option (digit, label, type, message, enabled).
/voice/numbers/{uuid}/ivr/options/{optionUuid}
Delete an IVR option.
/voice/numbers/{uuid}/ivr/options/reorder
Reorder IVR options. Send array of UUIDs in desired order.
{ "order": ["uuid-option-2", "uuid-option-1", "uuid-option-3"] }
/voice/numbers/{uuid}/ivr/regenerate-audio
Regenerate TTS audio cache for IVR messages. Optional: voice_id, language.
Llamantes VIP
Gestione llamantes prioritarios con enrutamiento personalizado. Los llamantes VIP pueden saltar la cola o recibir servicio diferenciado.
Niveles de prioridad
/voice/numbers/{uuid}/vip-callers
List all VIP callers for a phone number.
/voice/numbers/{uuid}/vip-callers
Add a VIP caller.
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/numbers/{uuid}/vip-callers \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+5511988887777",
"name": "John CEO",
"priority": "vip",
"notes": "Always connect immediately"
}'
/voice/numbers/{uuid}/vip-callers/check/{phone}
Check if a phone number is in the VIP list. Returns VIP details or is_vip: false.
/voice/numbers/{uuid}/vip-callers/{vipUuid}
|
DELETE
/voice/numbers/{uuid}/vip-callers/{vipUuid}
Update or delete a VIP caller by UUID.
Gestión de Cola
Configure y monitoree colas de atención con música de espera, anuncio de posición y callback automático.
/voice/numbers/{uuid}/queue
Get queue status, configuration and metrics.
Respuesta
{
"success": true,
"data": {
"config": {
"queue_enabled": true,
"max_queue_size": 10,
"max_wait_time": 300,
"hold_music_url": null,
"announce_position": true,
"callback_enabled": true
},
"status": {
"active_entries": 3,
"waiting_count": 2,
"connected_count": 1
}
}
}
/voice/numbers/{uuid}/queue
Update queue configuration (max_queue_size, max_wait_time, hold_music_url, announce_position, callback_enabled).
/voice/numbers/{uuid}/queue/entries
|
DELETE
/voice/numbers/{uuid}/queue/entries/{id}
List active queue entries or remove a specific entry from the queue.
Llamadas
Inicie, monitoree y gestione llamadas. Incluye transferencia a IA, estadísticas y costos detallados.
/voice/calls
List calls with filters.
Filtros disponibles
| Parâmetro | Tipo | Descripción |
|---|---|---|
| direction | string | inbound, outbound |
| status | string | ringing, in-progress, completed, failed, etc. |
| number_uuid | string | Filter by phone number UUID |
| date_from | date | YYYY-MM-DD |
| date_to | date | YYYY-MM-DD |
| per_page | integer | Results per page (default: 25) |
Ejemplo
curl -X GET "https://zapini.app/api/v1/voice/calls?direction=inbound&status=completed&per_page=10" \
-H "Authorization: Bearer {token}"
/voice/calls
Initiate an outbound call.
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/calls \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"from_number_uuid": "550e8400-e29b-41d4-a716-446655440000",
"to": "+5511988887777",
"record": true
}'
/voice/calls/statistics
Get call statistics: total, by direction, average duration, costs.
Respuesta
{
"success": true,
"data": {
"period": "monthly",
"total_calls": 150,
"inbound": 90,
"outbound": 60,
"total_duration_seconds": 45000,
"average_duration_seconds": 300,
"total_cost": 75.50,
"minutes_used": 750,
"minutes_limit": 1000,
"minutes_remaining": 250
}
}
/voice/calls/{uuid}
Get detailed call information with duration, costs, recording URL and transcript.
Call Actions:
/voice/calls/{uuid}/end
/voice/calls/{uuid}/transfer-to-ai
/voice/calls/{uuid}/reject
End an active call, transfer it to AI, or reject an incoming call.
Callbacks
Gestione solicitudes de callback: listar, ejecutar, cancelar y reprogramar.
/voice/callbacks
List callback requests. Filters: status (pending, completed, cancelled, expired), number_uuid, date_from, date_to.
Ejemplo
curl -X GET "https://zapini.app/api/v1/voice/callbacks?status=pending" \
-H "Authorization: Bearer {token}"
Callback Actions:
/voice/callbacks/{uuid}
/voice/callbacks/{uuid}/execute
/voice/callbacks/{uuid}/cancel
/voice/callbacks/{uuid}/reschedule
Get details, execute now, cancel, or reschedule a callback.
Reschedule requires: scheduled_for (ISO 8601 datetime)
Skills de Agentes
Gestione competencias de agentes para enrutamiento inteligente de llamadas basado en habilidades.
/voice/agents/skill-types
Get available skill types (sales, support, billing, technical, etc.).
Agent Skills CRUD:
/voice/agents/skills
/voice/agents/{userId}/skills
/voice/agents/{userId}/skills
/voice/agents/{userId}/skills/{skillId}
/voice/agents/{userId}/skills/{skillId}
Manage agent skills. Add skill requires: skill_type, proficiency (1-5).
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/agents/{userId}/skills \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"skill_type": "sales",
"proficiency": 5
}'
Voces Clonadas
Clone voces usando IA para IVR y servicio automatizado. Suba muestras de audio para crear voces personalizadas.
/voice/voices
List all cloned voices for the tenant.
/voice/voices
Clone a new voice from audio samples (multipart/form-data).
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/voices \
-H "Authorization: Bearer {token}" \
-F "name=My Voice Clone" \
-F "description=Custom voice for IVR" \
-F "samples[]=@sample1.mp3" \
-F "samples[]=@sample2.mp3"
/voice/voices/{uuid}
|
PATCH
/voice/voices/{uuid}
|
DELETE
/voice/voices/{uuid}
Get details, update name/description, or delete a cloned voice.
Credenciales Twilio
Gestione credenciales de acceso a Twilio: Account SID, Auth Token y API Keys para WebRTC.
/voice/credentials
Get credential status (masked values, never exposes secrets).
Respuesta
{
"success": true,
"data": {
"configured": true,
"is_verified": true,
"account_sid_masked": "AC****1234",
"has_api_keys": true,
"api_key_sid_masked": "SK****5678",
"created_at": "2026-02-14T10:00:00Z"
}
}
/voice/credentials
Save Twilio credentials.
Parámetros
| Parâmetro | Requerido | Descripción |
|---|---|---|
| account_sid | yes | Twilio Account SID (ACxxxxxxx) |
| auth_token | yes | Twilio Auth Token |
| api_key_sid | no | API Key SID for WebRTC (SKxxxxxxx) |
| api_key_secret | no | API Key Secret for WebRTC |
/voice/credentials/verify
|
PATCH
/voice/credentials
|
DELETE
/voice/credentials
Verify credentials against Twilio API, update, or remove credentials entirely.
Audio & WebRTC
Suba audio para IVR y genere previews TTS. Obtenga tokens WebRTC para softphone.
/voice/audio/upload
Upload audio file for IVR greetings, hold music, etc. (multipart/form-data)
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/audio/upload \
-H "Authorization: Bearer {token}" \
-F "audio=@greeting.mp3" \
-F "type=ivr_greeting"
/voice/audio/tts-preview
Generate a TTS (Text-to-Speech) audio preview.
Ejemplo
curl -X POST https://zapini.app/api/v1/voice/audio/tts-preview \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to our company. How can I help you?",
"voice_id": "optional-elevenlabs-voice-id",
"language": "pt-BR"
}'
/voice/token
Get WebRTC capability token for browser-based softphone.
Respuesta
{
"success": true,
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"identity": "tenant_29",
"expires_in": 3600
}
}
Códigos de Error
| Code | HTTP | Descripción |
|---|---|---|
| NO_VOICE_ACCESS | 403 | Funcionalidad Twilio Voice no habilitada en el tenant |
| NO_CREDENTIALS | 400 | Credenciales Twilio no configuradas |
| NUMBER_NOT_FOUND | 404 | Número de teléfono no encontrado o no autorizado |
| CALL_NOT_FOUND | 404 | Llamada no encontrada o no autorizada |
| MINUTES_EXCEEDED | 429 | Límite mensual de minutos excedido |
| CALL_NOT_ACTIVE | 400 | La llamada no está en curso |
| CALLBACK_EXPIRED | 400 | Callback expirado o ya ejecutado |
| IVR_NOT_ENABLED | 400 | IVR no está habilitado en este número |
Configuración Completa
Para usar la API de Voz, siga estos pasos:
1. Guarde sus credenciales Twilio vía POST /credentials
2. Verifique las credenciales vía POST /credentials/verify
3. Registre un número vía POST /numbers
4. Configure el modo de atención (IA, humano o IVR)
5. Si IVR: configure opciones vía POST /numbers/{uuid}/ivr/options
6. Realice llamadas vía POST /calls o reciba vía WebRTC
API Kanban
21 endpointsAPI Kanban
Gestiona tableros Kanban, columnas y leads programáticamente. Automatiza tu pipeline de ventas e intégrate con CRMs o herramientas de reporte.
URL Base
/api/v1/kanban
Autenticación
Bearer Token (sk_*)
Endpoints
21 endpoints
Acceso a Kanban requerido
Esta API requiere kanban_enabled en tu cuenta. Contacta al administrador para habilitar Kanban.
Tableros
/api/v1/kanban/boards
Lista todos los tableros Kanban de la instancia actual.
curl -s -H "Authorization: Bearer sk_your_token" \ "https://zapini.app/api/v1/kanban/boards"
/api/v1/kanban/boards
Crea un nuevo tablero Kanban con columnas predeterminadas.
curl -s -X POST \
-H "Authorization: Bearer sk_your_token" \
-H "Content-Type: application/json" \
-d '{"name":"Sales Pipeline","is_default":true}' \
"https://zapini.app/api/v1/kanban/boards"
name*, description, is_default
/api/v1/kanban/boards/{uuid}
Obtiene detalles del tablero incluyendo columnas y estadísticas.
// Response includes stats + columns
{
"uuid": "...",
"name": "Sales Pipeline",
"stats": {
"total_leads": 12, "open_leads": 9, "won_leads": 2, "lost_leads": 1,
"total_value": 15000.00, "won_value": 5000.00,
"conversion_rate": 66.7, "avg_time_to_close": 14.5
},
"columns": [...]
}
/api/v1/kanban/boards/{uuid}
Actualiza nombre, descripción o configuración del tablero.
/api/v1/kanban/boards/{uuid}
Elimina un tablero y todas sus columnas y leads.
Columnas
/api/v1/kanban/boards/{uuid}/columns
Lista columnas de un tablero (ordenadas por posición).
/api/v1/kanban/boards/{uuid}/columns
Crea una nueva columna en un tablero.
/api/v1/kanban/boards/{uuid}/columns/reorder
Reordena columnas proporcionando array ordenado de UUIDs.
/api/v1/kanban/columns/{uuid}
Actualiza nombre, color o configuración de la columna.
/api/v1/kanban/columns/{uuid}
Elimina una columna, opcionalmente moviendo leads a otra columna.
Ejemplo — Reorder Columns
curl -s -X POST \
-H "Authorization: Bearer sk_your_token" \
-H "Content-Type: application/json" \
-d '{"order":["col-uuid-1","col-uuid-2","col-uuid-3"]}' \
"https://zapini.app/api/v1/kanban/boards/{board-uuid}/columns/reorder"
Leads
/api/v1/kanban/boards/{uuid}/leads
Lista leads de un tablero con filtros opcionales.
/api/v1/kanban/leads
Crea un nuevo lead en un tablero.
/api/v1/kanban/leads/{uuid}
Obtiene detalles del lead incluyendo notas, campos personalizados y análisis IA.
/api/v1/kanban/leads/{uuid}
Actualiza campos del lead (título, valor, prioridad, etc.).
/api/v1/kanban/leads/{uuid}
Elimina (soft delete) un lead.
/api/v1/kanban/leads/{uuid}/move
Mueve un lead a una columna diferente.
/api/v1/kanban/leads/{uuid}/won
Marca un lead como ganado.
/api/v1/kanban/leads/{uuid}/lost
Marca un lead como perdido con razón opcional.
/api/v1/kanban/leads/{uuid}/note
Agrega una nota con timestamp a un lead.
/api/v1/kanban/leads/{uuid}/activities
Obtiene el historial de actividades de un lead.
/api/v1/kanban/leads/{uuid}/ai-qualify
Ejecuta análisis de calificación IA en el lead.
Ejemplo — Crea un nuevo lead en un tablero.
curl -s -X POST \
-H "Authorization: Bearer sk_your_token" \
-H "Content-Type: application/json" \
-d '{
"board_uuid": "board-uuid-here",
"title": "John Doe - Pro Plan",
"phone_number": "5511999999999",
"email": "john@example.com",
"value": 299.00,
"priority": "high",
"notes": "Interested in annual subscription"
}' \
"https://zapini.app/api/v1/kanban/leads"
Respuesta:
{
"success": true,
"data": {
"uuid": "...",
"title": "John Doe - Pro Plan",
"phone_number": "5511999999999",
"value": "299.00",
"value_formatted": "R$ 299,00",
"priority": "high",
"priority_label": "High",
"source": "api",
"ai_score": null,
"is_open": true, "is_won": false, "is_lost": false,
"column": { "uuid": "...", "name": "New Lead", "color": "#3B82F6" }
}
}
Parámetros de Consulta — GET /boards/{uuid}/leads
| Campo | Descripción |
|---|---|
| status | open | won | lost | all (default: open) |
| priority | low | medium | high | urgent |
| column_uuid | Filtrar por UUID de columna |
| search | Buscar por nombre o número |
API Calendario
9 endpointsAPI Calendario
Gestiona citas y eventos de calendario. Crea, actualiza y rastrea transiciones de estado de citas programáticamente.
URL Base
/api/v1/calendar
Autenticación
Bearer Token (sk_*)
Endpoints
9 endpoints
Estados de Citas
scheduled Estado inicial — cita reservadaconfirmed Cliente confirmó asistenciacompleted Cita fue completadacancelled Cita fue canceladano_show Cliente no se presentóCitas
/api/v1/calendar/appointments
Lista citas para un rango de fechas (predeterminado: mes actual).
/api/v1/calendar/appointments
Crea una nueva cita.
/api/v1/calendar/appointments/{uuid}
Obtiene detalles de una cita.
/api/v1/calendar/appointments/{uuid}
Actualiza detalles o estado de la cita.
/api/v1/calendar/appointments/{uuid}
Elimina una cita.
/api/v1/calendar/appointments/{uuid}/confirm
Transiciona estado de la cita a confirmado.
/api/v1/calendar/appointments/{uuid}/complete
Transiciona estado de la cita a completado.
/api/v1/calendar/appointments/{uuid}/cancel
Cancela una cita (no se puede cancelar citas ya completadas).
/api/v1/calendar/appointments/{uuid}/to-kanban
Crea un lead Kanban a partir de esta cita.
Ejemplo — Create Appointment
curl -s -X POST \
-H "Authorization: Bearer sk_your_token" \
-H "Content-Type: application/json" \
-d '{
"title": "Consultation with John Doe",
"client_name": "John Doe",
"client_phone": "5511999999999",
"client_email": "john@example.com",
"starts_at": "2026-05-01T10:00:00",
"ends_at": "2026-05-01T11:00:00",
"location": "Online - Google Meet",
"reminder_minutes": 30
}' \
"https://zapini.app/api/v1/calendar/appointments"
Respuesta:
{
"success": true,
"data": {
"uuid": "...",
"title": "Consultation with John Doe",
"client_name": "John Doe",
"client_phone": "5511999999999",
"starts_at": "2026-05-01T10:00:00+00:00",
"ends_at": "2026-05-01T11:00:00+00:00",
"duration_minutes": 60,
"status": "scheduled",
"color": "#3b82f6",
"reminder_minutes": 30,
"created_at": "2026-01-01T00:00:00+00:00"
}
}
Parámetros de Consulta — GET /calendar/appointments
| Campo | Descripción | Default |
|---|---|---|
| start | Fecha inicial (ISO 8601) | Start of month |
| end | Fecha final (ISO 8601) | End of month |
| status | scheduled | confirmed | completed | cancelled | no_show | — |
| per_page | Items por página (máx 100) | 50 |
Endpoint to-kanban
Convierte una cita en un lead Kanban. Requiere kanban_enabled en tu cuenta. Opcionalmente especifica board_uuid; de lo contrario se usa el tablero predeterminado.
curl -s -X POST \
-H "Authorization: Bearer sk_your_token" \
-H "Content-Type: application/json" \
-d '{"board_uuid": "optional-board-uuid"}' \
"https://zapini.app/api/v1/calendar/appointments/{uuid}/to-kanban"
API de Funciones de IA
9 endpointsAPI de Funciones de IA
Gestione funciones de IA (herramientas basadas en webhook) que su agente de IA puede llamar durante las conversaciones. Cree, configure, pruebe y monitoree funciones personalizadas que amplían las capacidades de su agente de IA.
⚡ Requiere una integración de Agente de IA activa en su cuenta.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/ai-functions | Listar Funciones de IA |
| POST | /api/v1/ai-functions | Crear Función de IA |
| GET | /api/v1/ai-functions/{uuid} | Obtener Función de IA |
| PUT | /api/v1/ai-functions/{uuid} | Actualizar Función de IA |
| DELETE | /api/v1/ai-functions/{uuid} | Eliminar Función de IA |
| POST | /api/v1/ai-functions/{uuid}/toggle | Alternar Función de IA |
| POST | /api/v1/ai-functions/{uuid}/test | Probar Función de IA |
| GET | /api/v1/ai-functions/{uuid}/executions | Listar Ejecuciones |
| GET | /api/v1/ai-functions/executions/{uuid} | Detalles de Ejecución |
/api/v1/ai-functions
Devuelve una lista paginada de todas las funciones de IA de su cuenta.
Query Parameters
| integration_uuid | Filtrar por UUID de integración |
| type | Filtrar por tipo de función |
| enabled | Filtrar por estado de activación |
| search | Buscar por nombre o descripción |
| per_page | Results per page (max 100, default 20) |
Example
curl -X GET "https://zapini.app/api/v1/ai-functions?type=fetch_data&enabled=true" \
-H "Authorization: Bearer {token}"
/api/v1/ai-functions
Crea una nueva función de IA con parámetros opcionales. La función debe estar vinculada a una integración de Agente de IA.
Body Parameters
| integration_uuid * | UUID de la integración de Agente de IA |
| name * | Nombre de la función (minúsculas, solo guiones bajos) |
| display_name * | Nombre de visualización amigable |
| description * | Descripción mostrada al agente de IA |
| type * | Tipo de función: fetch_data, collect_submit, action |
| endpoint_url | URL del webhook a llamar |
| http_method | Método HTTP (GET, POST, PUT, PATCH, DELETE) |
| auth_type | Tipo de autenticación: none, bearer, basic, api_key, custom |
| parameters | Array de parámetros de la función |
| is_enabled | Si la función está activa |
Example
curl -X POST "https://zapini.app/api/v1/ai-functions" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"integration_uuid": "abc-123-def",
"name": "check_order_status",
"display_name": "Check Order Status",
"description": "Checks the status of a customer order by order number",
"type": "fetch_data",
"endpoint_url": "https://api.myshop.com/orders/status",
"http_method": "GET",
"auth_type": "bearer",
"auth_config": {"token": "my-shop-api-key"},
"parameters": [
{
"name": "order_number",
"display_name": "Order Number",
"description": "The customer order number",
"type": "string",
"is_required": true,
"collect_from_user": true
}
]
}'
/api/v1/ai-functions/{uuid}/toggle
Alterna el estado activado/desactivado de una función de IA.
curl -X POST "https://zapini.app/api/v1/ai-functions/{uuid}/toggle" \
-H "Authorization: Bearer {token}"
/api/v1/ai-functions/{uuid}/test
Ejecuta una llamada de prueba al endpoint de la función con los parámetros proporcionados.
curl -X POST "https://zapini.app/api/v1/ai-functions/{uuid}/test" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"parameters": {"order_number": "ORD-12345"}}'
Error Codes
| AI_AGENT_NOT_ENABLED | 403 — AI_AGENT_NOT_ENABLED — Sin integración de Agente de IA activa |
| DUPLICATE_NAME | 422 — DUPLICATE_NAME — El nombre de la función ya existe |
| ACTIVE_EXECUTIONS | 409 — ACTIVE_EXECUTIONS — No se puede eliminar mientras hay ejecuciones en curso |
| INVALID_INTEGRATION_TYPE | 422 — INVALID_INTEGRATION_TYPE — La integración no es de tipo Agente de IA |
API de Funciones Externas
8 endpointsAPI de Funciones Externas
Gestione funciones externas — endpoints de webhook que permiten a sistemas externos activar acciones de WhatsApp (enviar mensajes, gestionar contactos, controlar automatizaciones). Cada función recibe una clave API única para autenticación.
⚡ Requiere una integración de Agente de IA activa en su cuenta.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/external-functions | Listar Funciones Externas |
| POST | /api/v1/external-functions | Crear Función Externa |
| GET | /api/v1/external-functions/{uuid} | Obtener Función Externa |
| PUT | /api/v1/external-functions/{uuid} | Actualizar Función Externa |
| DELETE | /api/v1/external-functions/{uuid} | Eliminar Función Externa |
| POST | /api/v1/external-functions/{uuid}/toggle | Alternar Función Externa |
| POST | /api/v1/external-functions/{uuid}/regenerate-key | Regenerar Clave API |
| GET | /api/v1/external-functions/{uuid}/logs | Listar Logs |
/api/v1/external-functions
Crea una nueva función externa con una clave API generada automáticamente. La clave API en texto plano solo se devuelve una vez — almacénela de forma segura.
Body Parameters
| instance_uuid * | UUID de la instancia de WhatsApp |
| name * | Nombre de la función |
| slug * | Slug de la URL (minúsculas, solo guiones) |
| action_type * | Tipo de acción: send_message, send_buttons, send_media, create_contact, update_contact, create_lead, update_lead, pause_automation, resume_automation |
| description | Descripción de la función |
| config | Configuración específica de la acción |
| rate_limit | Máximo de llamadas por día (por defecto: 1000) |
| allowed_ips | Array de direcciones IP permitidas (vacío = todas permitidas) |
| is_enabled | Si la función está activa |
Example
curl -X POST "https://zapini.app/api/v1/external-functions" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"instance_uuid": "abc-123-def",
"name": "CRM Order Notification",
"slug": "crm-order-notify",
"action_type": "send_message",
"description": "Sends order status updates from CRM",
"config": {
"message_template": "Order {{order_id}}: {{status}}"
},
"rate_limit": 500,
"allowed_ips": ["203.0.113.10"]
}'
⚠️ The api_key is returned only once in the create response. Store it securely — it cannot be retrieved later.
/api/v1/external-functions/{uuid}/regenerate-key
Genera una nueva clave API e invalida la anterior. La nueva clave solo se devuelve una vez.
curl -X POST "https://zapini.app/api/v1/external-functions/{uuid}/regenerate-key" \
-H "Authorization: Bearer {token}"
Tipos de Acción Disponibles
| send_message | send_message — Enviar un mensaje de texto |
| send_buttons | send_buttons — Enviar un mensaje con botones |
| send_media | send_media — Enviar multimedia (imagen, video, documento) |
| create_contact | create_contact — Crear un nuevo contacto |
| update_contact | update_contact — Actualizar un contacto existente |
| create_lead | create_lead — Crear un lead en Kanban |
| update_lead | update_lead — Actualizar un lead en Kanban |
| pause_automation | pause_automation — Pausar automatización de IA de una conversación |
| resume_automation | resume_automation — Reanudar automatización de IA de una conversación |
Error Codes
| AI_AGENT_NOT_ENABLED | 403 — AI_AGENT_NOT_ENABLED — Sin integración de Agente de IA activa |
| DUPLICATE_SLUG | 422 — DUPLICATE_SLUG — El slug ya existe para esta cuenta |
¿Listo para Comenzar?
Crea tu cuenta ahora y comienza a integrar WhatsApp en tus aplicaciones con nuestra API potente y fácil de usar.