Endpoints de la API
URL base: https://chat.zelta.dev/api/v1
Todos los endpoints están bajo el ámbito /accounts/{account_id}/ y requieren autenticación mediante api_access_token. Consulta la para obtener tu token.
Conversaciones
Listar conversaciones
GET /accounts/{account_id}/conversationsParámetros de consulta:
| Parámetro | Tipo | Descripción |
|---|---|---|
assignee_type | string | Tipo de asignación: assigned, unassigned, mine |
status | string | Estado: open, resolved, pending, snoozed |
inbox_id | integer | Filtrar por bandeja de entrada |
team_id | integer | Filtrar por equipo |
label | string | Filtrar por etiqueta |
page | integer | Número de página |
Ejemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/conversations?status=open&assignee_type=mine&page=1" \
-H "api_access_token: tu_token_aqui"Respuesta:
{
"data": {
"meta": {
"mine_count": 5,
"assigned_count": 12,
"unassigned_count": 3,
"all_count": 15
},
"payload": [
{
"id": 42,
"account_id": 1,
"inbox_id": 3,
"status": "open",
"priority": "medium",
"labels": ["ventas", "vip"],
"custom_attributes": {},
"meta": {
"sender": {
"id": 7,
"name": "María García",
"email": "[email protected]",
"phone_number": "+50761234567"
},
"assignee": {
"id": 5,
"name": "Carlos López"
},
"team": {
"id": 2,
"name": "Equipo de Ventas"
}
},
"created_at": 1709145600,
"updated_at": 1709145600
}
]
}
}Crear conversación
POST /accounts/{account_id}/conversationsEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"inbox_id": 3,
"contact_id": 7,
"status": "open",
"assignee_id": 5,
"team_id": 2,
"message": {
"content": "Hola, bienvenida a nuestro servicio."
}
}'Obtener conversación
GET /accounts/{account_id}/conversations/{id}Ejemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/conversations/42" \
-H "api_access_token: tu_token_aqui"Actualizar conversación
PATCH /accounts/{account_id}/conversations/{id}Ejemplo:
curl -X PATCH "https://chat.zelta.dev/api/v1/accounts/1/conversations/42" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"priority": "high",
"labels": ["ventas", "urgente"]
}'Cambiar estado de conversación
POST /accounts/{account_id}/conversations/{id}/toggle_statusEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/toggle_status" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{ "status": "resolved" }'Estados disponibles:
| Estado | Valor numérico | Descripción |
|---|---|---|
open | 0 | Conversación abierta y activa |
resolved | 1 | Conversación resuelta |
pending | 2 | Conversación pendiente de acción |
snoozed | 3 | Conversación pospuesta temporalmente |
Cambiar prioridad
POST /accounts/{account_id}/conversations/{id}/toggle_priorityPrioridades disponibles:
| Prioridad | Valor numérico |
|---|---|
low | 0 |
medium | 1 |
high | 2 |
urgent | 3 |
Asignar conversación
POST /accounts/{account_id}/conversations/{id}/assignmentsAsigna un agente o equipo a la conversación.
Asignar a un agente:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/assignments" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{ "assignee_id": 5 }'Asignar a un equipo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/assignments" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{ "team_id": 2 }'Filtrar conversaciones
POST /accounts/{account_id}/conversations/filterPermite aplicar filtros avanzados con múltiples condiciones.
Ejemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/filter" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"payload": [
{
"attribute_key": "status",
"filter_operator": "equal_to",
"values": ["open"]
},
{
"attribute_key": "assignee_id",
"filter_operator": "equal_to",
"values": [5]
}
]
}'Buscar conversaciones
GET /accounts/{account_id}/conversations/search?q={texto}Ejemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/conversations/search?q=plan+enterprise" \
-H "api_access_token: tu_token_aqui"Mensajes
Listar mensajes de una conversación
GET /accounts/{account_id}/conversations/{conversation_id}/messagesEjemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/messages" \
-H "api_access_token: tu_token_aqui"Respuesta:
{
"meta": {
"contact": {
"id": 7,
"name": "María García"
}
},
"payload": [
{
"id": 101,
"content": "Hola, me interesa el plan Enterprise",
"inbox_id": 3,
"conversation_id": 42,
"message_type": 0,
"content_type": "text",
"status": "sent",
"private": false,
"created_at": 1709145600,
"sender": {
"id": 7,
"name": "María García",
"type": "contact"
},
"attachments": []
}
]
}Enviar mensaje
POST /accounts/{account_id}/conversations/{conversation_id}/messagesMensaje de texto:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/messages" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"content": "¡Hola María! Con gusto te comparto la información del plan Enterprise.",
"message_type": "outgoing",
"private": false
}'Nota interna (solo visible para agentes):
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/messages" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"content": "Cliente interesada en plan Enterprise. Ya le envié la cotización por email.",
"private": true
}'Notas internas
Cuando private es true, el mensaje se crea como nota interna visible únicamente para agentes y administradores. No se envía al contacto por ningún canal.
Mensaje con archivo adjunto (multipart/form-data):
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/conversations/42/messages" \
-H "api_access_token: tu_token_aqui" \
-F "content=Adjunto la cotización del Plan Enterprise" \
-F "message_type=outgoing" \
-F "private=false" \
-F "attachments[]=@/ruta/al/archivo/cotizacion.pdf"Respuesta de un mensaje creado:
{
"id": 102,
"content": "¡Hola María! Con gusto te comparto la información del plan Enterprise.",
"inbox_id": 3,
"conversation_id": 42,
"message_type": 1,
"content_type": "text",
"status": "sent",
"private": false,
"created_at": 1709145900,
"sender": {
"id": 5,
"name": "Carlos López",
"type": "user"
},
"attachments": []
}Tipos y estados de mensaje
Tipos de mensaje (message_type):
| Tipo | Valor numérico | Descripción |
|---|---|---|
incoming | 0 | Mensaje recibido del contacto |
outgoing | 1 | Mensaje enviado por un agente |
activity | 2 | Mensaje de actividad del sistema |
template | 3 | Mensaje de plantilla |
Estados de mensaje (status):
| Estado | Valor numérico | Descripción |
|---|---|---|
sent | 0 | Mensaje enviado |
delivered | 1 | Entregado al dispositivo del contacto |
read | 2 | Leído por el contacto |
failed | 3 | Error en el envío |
Contactos
Listar contactos
GET /accounts/{account_id}/contactsParámetros de consulta:
| Parámetro | Tipo | Descripción |
|---|---|---|
page | integer | Número de página |
sort | string | Campo de ordenamiento |
include_contact_inboxes | boolean | Incluir las bandejas asociadas al contacto |
Ejemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/contacts?page=1" \
-H "api_access_token: tu_token_aqui"Respuesta:
{
"meta": {
"count": 156,
"current_page": 1
},
"payload": [
{
"id": 7,
"name": "María García",
"email": "[email protected]",
"phone_number": "+50761234567",
"availability_status": "online",
"custom_attributes": {
"empresa": "Acme Corp"
},
"last_activity_at": 1709145600,
"created_at": 1709145600
}
]
}Buscar contactos
GET /accounts/{account_id}/contacts/search?q={texto}Busca contactos por nombre, correo electrónico o número de teléfono.
Ejemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/contacts/search?q=maria" \
-H "api_access_token: tu_token_aqui"Crear contacto
POST /accounts/{account_id}/contactsEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/contacts" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Juan Pérez",
"email": "[email protected]",
"phone_number": "+50769001234",
"custom_attributes": {
"empresa": "Tech Solutions",
"cargo": "Gerente de TI"
}
}'Obtener contacto
GET /accounts/{account_id}/contacts/{id}Ejemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/contacts/7" \
-H "api_access_token: tu_token_aqui"Actualizar contacto
PATCH /accounts/{account_id}/contacts/{id}Ejemplo:
curl -X PATCH "https://chat.zelta.dev/api/v1/accounts/1/contacts/7" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "María García de López",
"custom_attributes": {
"empresa": "Acme Corp",
"cargo": "Directora Comercial"
}
}'Eliminar contacto
DELETE /accounts/{account_id}/contacts/{id}Ejemplo:
curl -X DELETE "https://chat.zelta.dev/api/v1/accounts/1/contacts/7" \
-H "api_access_token: tu_token_aqui"Acción irreversible
Eliminar un contacto también elimina todas sus conversaciones y mensajes asociados. Esta acción no se puede deshacer.
Filtrar contactos
POST /accounts/{account_id}/contacts/filterPermite aplicar filtros avanzados con múltiples condiciones, de forma similar al filtro de conversaciones.
Importar contactos
POST /accounts/{account_id}/contacts/importImporta contactos desde un archivo CSV. Envía el archivo como multipart/form-data.
Ejemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/contacts/import" \
-H "api_access_token: tu_token_aqui" \
-F "import_file=@/ruta/al/archivo/contactos.csv"Exportar contactos
POST /accounts/{account_id}/contacts/exportInicia la exportación de contactos. El archivo se envía al correo del solicitante.
Bandejas de entrada (Inboxes)
En la API, los canales de comunicación se gestionan como bandejas de entrada (inboxes). Cada bandeja representa un canal conectado: WhatsApp, correo electrónico, chat web, Instagram, entre otros.
Listar bandejas de entrada
GET /accounts/{account_id}/inboxesEjemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/inboxes" \
-H "api_access_token: tu_token_aqui"Respuesta:
{
"payload": [
{
"id": 3,
"name": "WhatsApp Principal",
"channel_type": "Channel::Whatsapp",
"greeting_enabled": false,
"greeting_message": "",
"enable_auto_assignment": true,
"out_of_office_message": "",
"working_hours_enabled": false
},
{
"id": 4,
"name": "Soporte Email",
"channel_type": "Channel::Email",
"greeting_enabled": true,
"greeting_message": "¡Gracias por contactarnos! Responderemos a la brevedad.",
"enable_auto_assignment": true,
"out_of_office_message": "Nuestro horario es de lunes a viernes, 8am a 5pm.",
"working_hours_enabled": true
}
]
}Obtener bandeja de entrada
GET /accounts/{account_id}/inboxes/{id}Crear bandeja de entrada
POST /accounts/{account_id}/inboxesEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/inboxes" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Chat del Sitio Web",
"channel": {
"type": "web_widget",
"website_url": "https://miempresa.com"
}
}'Actualizar bandeja de entrada
PATCH /accounts/{account_id}/inboxes/{id}Ejemplo:
curl -X PATCH "https://chat.zelta.dev/api/v1/accounts/1/inboxes/3" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"enable_auto_assignment": false,
"greeting_enabled": true,
"greeting_message": "¡Hola! Un momento, por favor."
}'Eliminar bandeja de entrada
DELETE /accounts/{account_id}/inboxes/{id}Precaución
Eliminar una bandeja de entrada desconecta el canal. Las conversaciones existentes se conservan, pero no se podrán recibir ni enviar nuevos mensajes por ese canal.
Agentes
Listar agentes
GET /accounts/{account_id}/agentsEjemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/agents" \
-H "api_access_token: tu_token_aqui"Respuesta (arreglo directo):
[
{
"id": 5,
"name": "Carlos López",
"email": "[email protected]",
"role": "agent",
"availability_status": "online",
"confirmed": true
},
{
"id": 8,
"name": "Ana Rodríguez",
"email": "[email protected]",
"role": "administrator",
"availability_status": "busy",
"confirmed": true
}
]Formato de respuesta
La lista de agentes devuelve un arreglo directo, sin objeto envolvente data ni payload.
Invitar agente
POST /accounts/{account_id}/agentsEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/agents" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Roberto Morales",
"email": "[email protected]",
"role": "agent"
}'Actualizar agente
PATCH /accounts/{account_id}/agents/{id}Ejemplo:
curl -X PATCH "https://chat.zelta.dev/api/v1/accounts/1/agents/5" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"role": "administrator",
"availability": "online"
}'Eliminar agente
DELETE /accounts/{account_id}/agents/{id}Equipos
Listar equipos
GET /accounts/{account_id}/teamsEjemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/teams" \
-H "api_access_token: tu_token_aqui"Respuesta (arreglo directo):
[
{
"id": 2,
"name": "Equipo de Ventas",
"description": "Equipo dedicado a ventas y prospección",
"allow_auto_assign": true
},
{
"id": 3,
"name": "Soporte Técnico",
"description": "Atención de consultas técnicas y resolución de problemas",
"allow_auto_assign": true
}
]Crear equipo
POST /accounts/{account_id}/teamsEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/teams" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Equipo VIP",
"description": "Atención exclusiva para clientes premium",
"allow_auto_assign": true
}'Obtener equipo
GET /accounts/{account_id}/teams/{id}Actualizar equipo
PATCH /accounts/{account_id}/teams/{id}Eliminar equipo
DELETE /accounts/{account_id}/teams/{id}Etiquetas
Listar etiquetas
GET /accounts/{account_id}/labelsEjemplo:
curl -X GET "https://chat.zelta.dev/api/v1/accounts/1/labels" \
-H "api_access_token: tu_token_aqui"Crear etiqueta
POST /accounts/{account_id}/labelsEjemplo:
curl -X POST "https://chat.zelta.dev/api/v1/accounts/1/labels" \
-H "api_access_token: tu_token_aqui" \
-H "Content-Type: application/json" \
-d '{
"title": "vip",
"description": "Clientes con atención prioritaria",
"color": "#FF6B00",
"show_on_sidebar": true
}'Actualizar etiqueta
PATCH /accounts/{account_id}/labels/{id}Eliminar etiqueta
DELETE /accounts/{account_id}/labels/{id}Endpoints adicionales
Búsqueda global
GET /accounts/{account_id}/search?q={texto}Busca simultáneamente en conversaciones, mensajes y contactos.
Respuestas predefinidas
CRUD completo disponible en:
GET /accounts/{account_id}/canned_responses
POST /accounts/{account_id}/canned_responses
PATCH /accounts/{account_id}/canned_responses/{id}
DELETE /accounts/{account_id}/canned_responses/{id}Las respuestas predefinidas permiten a los agentes insertar textos frecuentes rápidamente usando atajos de teclado.
Atributos personalizados
CRUD completo disponible en:
GET /accounts/{account_id}/custom_attribute_definitions
POST /accounts/{account_id}/custom_attribute_definitions
PATCH /accounts/{account_id}/custom_attribute_definitions/{id}
DELETE /accounts/{account_id}/custom_attribute_definitions/{id}Define atributos personalizados para contactos y conversaciones (por ejemplo: empresa, plan contratado, origen del lead).
Webhooks
CRUD completo disponible en:
GET /accounts/{account_id}/webhooks
POST /accounts/{account_id}/webhooks
PATCH /accounts/{account_id}/webhooks/{id}
DELETE /accounts/{account_id}/webhooks/{id}Configura URLs para recibir notificaciones en tiempo real sobre eventos del sistema. Consulta la sección de para más detalles.
Reportes
GET /api/v2/accounts/{account_id}/reportsVersión de la API
Los reportes utilizan la versión 2 de la API (/api/v2/). Los sub-endpoints disponibles permiten obtener métricas de conversaciones, agentes, equipos y bandejas de entrada en distintos rangos de tiempo.
Códigos de respuesta
| Código | Descripción |
|---|---|
200 | Solicitud exitosa |
201 | Recurso creado exitosamente |
204 | Recurso eliminado exitosamente (sin contenido en la respuesta) |
400 | Solicitud mal formada |
401 | No autenticado o token inválido |
403 | Sin permisos suficientes para esta acción |
404 | Recurso no encontrado |
422 | Error de validación en los datos enviados |
429 | Límite de solicitudes excedido |
500 | Error interno del servidor |
Formato de error
{
"error": "invalid_params",
"message": "No se pudo procesar la solicitud",
"errors": [
"El campo 'name' es obligatorio"
]
}Límites de tasa
| Ámbito | Límite |
|---|---|
| General (por IP) | 3,000 solicitudes por minuto |
| Búsqueda | 100 solicitudes por minuto |
| Reportes (por usuario) | 100 solicitudes por minuto |
Cuando se excede el límite, la API responde con código 429 Too Many Requests. Espera el tiempo indicado en el encabezado Retry-After antes de reintentar.
Paginación
Los endpoints de listado que devuelven múltiples resultados incluyen metadatos de paginación. El formato varía según el recurso:
- Conversaciones: el objeto
metadentro dedatacontiene contadores (mine_count,assigned_count,unassigned_count,all_count) y los resultados están endata.payload. - Contactos: el objeto
metacontienecountycurrent_page, y los resultados están enpayload. - Mensajes: estructura similar con
metaypayload. - Agentes, equipos: devuelven arreglos directos sin paginación.
Utiliza el parámetro page para navegar entre páginas de resultados.