- README principal con descripción del proyecto - Documento de diseño completo (arquitectura, DB, flujos) - Documentación de API REST y WebSocket - Guía del Flow Builder (30+ tipos de nodos) - Documentación de integración con Odoo - Guía de despliegue con Docker - Esquema de base de datos - Estructura de carpetas del proyecto - Archivo .env.example con todas las variables Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
747 lines
12 KiB
Markdown
747 lines
12 KiB
Markdown
# API Reference
|
|
|
|
## Información General
|
|
|
|
- **Base URL:** `https://tu-dominio.com/api`
|
|
- **Autenticación:** Bearer Token (JWT)
|
|
- **Content-Type:** `application/json`
|
|
|
|
## Autenticación
|
|
|
|
### Login
|
|
```http
|
|
POST /auth/login
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "usuario@empresa.com",
|
|
"password": "tu_password"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
|
"token_type": "bearer",
|
|
"user": {
|
|
"id": "uuid",
|
|
"email": "usuario@empresa.com",
|
|
"name": "Usuario",
|
|
"role": "admin"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Refresh Token
|
|
```http
|
|
POST /auth/refresh
|
|
```
|
|
|
|
### Logout
|
|
```http
|
|
POST /auth/logout
|
|
```
|
|
|
|
### Usuario Actual
|
|
```http
|
|
GET /auth/me
|
|
```
|
|
|
|
---
|
|
|
|
## Usuarios
|
|
|
|
### Listar Usuarios
|
|
```http
|
|
GET /api/users
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| role | string | Filtrar por rol (admin, supervisor, agent) |
|
|
| status | string | Filtrar por estado (online, offline, away) |
|
|
| page | int | Página (default: 1) |
|
|
| limit | int | Límite por página (default: 20) |
|
|
|
|
### Crear Usuario
|
|
```http
|
|
POST /api/users
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"email": "nuevo@empresa.com",
|
|
"password": "password123",
|
|
"name": "Nuevo Usuario",
|
|
"role": "agent"
|
|
}
|
|
```
|
|
|
|
### Obtener Usuario
|
|
```http
|
|
GET /api/users/{user_id}
|
|
```
|
|
|
|
### Actualizar Usuario
|
|
```http
|
|
PUT /api/users/{user_id}
|
|
```
|
|
|
|
### Eliminar Usuario
|
|
```http
|
|
DELETE /api/users/{user_id}
|
|
```
|
|
|
|
### Cambiar Estado
|
|
```http
|
|
PUT /api/users/{user_id}/status
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"status": "away"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Cuentas WhatsApp
|
|
|
|
### Listar Cuentas
|
|
```http
|
|
GET /api/whatsapp/accounts
|
|
```
|
|
|
|
### Crear Cuenta (Iniciar conexión)
|
|
```http
|
|
POST /api/whatsapp/accounts
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"name": "Ventas Principal"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"name": "Ventas Principal",
|
|
"status": "disconnected",
|
|
"qr_code": null
|
|
}
|
|
```
|
|
|
|
### Obtener QR Code
|
|
```http
|
|
GET /api/whatsapp/accounts/{account_id}/qr
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"qr_code": "data:image/png;base64,..."
|
|
}
|
|
```
|
|
|
|
### Estado de Cuenta
|
|
```http
|
|
GET /api/whatsapp/accounts/{account_id}/status
|
|
```
|
|
|
|
### Desconectar Cuenta
|
|
```http
|
|
POST /api/whatsapp/accounts/{account_id}/disconnect
|
|
```
|
|
|
|
### Reconectar Cuenta
|
|
```http
|
|
POST /api/whatsapp/accounts/{account_id}/reconnect
|
|
```
|
|
|
|
---
|
|
|
|
## Contactos
|
|
|
|
### Listar Contactos
|
|
```http
|
|
GET /api/contacts
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| search | string | Buscar por nombre, teléfono o email |
|
|
| tags | string[] | Filtrar por etiquetas |
|
|
| has_odoo | boolean | Filtrar sincronizados con Odoo |
|
|
| page | int | Página |
|
|
| limit | int | Límite |
|
|
|
|
### Crear Contacto
|
|
```http
|
|
POST /api/contacts
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"phone_number": "+525551234567",
|
|
"name": "Juan Pérez",
|
|
"email": "juan@email.com",
|
|
"company": "Empresa ABC",
|
|
"tags": ["lead", "interesado"],
|
|
"metadata": {
|
|
"producto_interes": "Laptop Pro"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Obtener Contacto
|
|
```http
|
|
GET /api/contacts/{contact_id}
|
|
```
|
|
|
|
### Actualizar Contacto
|
|
```http
|
|
PUT /api/contacts/{contact_id}
|
|
```
|
|
|
|
### Agregar Etiquetas
|
|
```http
|
|
POST /api/contacts/{contact_id}/tags
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"tags": ["vip", "cliente"]
|
|
}
|
|
```
|
|
|
|
### Sincronizar con Odoo
|
|
```http
|
|
POST /api/contacts/{contact_id}/sync-odoo
|
|
```
|
|
|
|
---
|
|
|
|
## Conversaciones
|
|
|
|
### Listar Conversaciones
|
|
```http
|
|
GET /api/conversations
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| status | string | bot, waiting, active, resolved |
|
|
| queue_id | uuid | Filtrar por cola |
|
|
| assigned_to | uuid | Filtrar por agente |
|
|
| priority | string | low, normal, high, urgent |
|
|
| page | int | Página |
|
|
| limit | int | Límite |
|
|
|
|
### Obtener Conversación
|
|
```http
|
|
GET /api/conversations/{conversation_id}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"contact": {
|
|
"id": "uuid",
|
|
"name": "Juan Pérez",
|
|
"phone_number": "+525551234567"
|
|
},
|
|
"whatsapp_account": {
|
|
"id": "uuid",
|
|
"name": "Ventas Principal"
|
|
},
|
|
"status": "active",
|
|
"priority": "normal",
|
|
"assigned_to": {
|
|
"id": "uuid",
|
|
"name": "María García"
|
|
},
|
|
"queue": {
|
|
"id": "uuid",
|
|
"name": "Ventas"
|
|
},
|
|
"current_flow": null,
|
|
"sla_first_response_met": true,
|
|
"last_message_at": "2024-01-15T14:30:00Z",
|
|
"created_at": "2024-01-15T14:25:00Z"
|
|
}
|
|
```
|
|
|
|
### Asignar Conversación
|
|
```http
|
|
POST /api/conversations/{conversation_id}/assign
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"user_id": "uuid"
|
|
}
|
|
```
|
|
|
|
### Transferir a Cola
|
|
```http
|
|
POST /api/conversations/{conversation_id}/transfer
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"queue_id": "uuid"
|
|
}
|
|
```
|
|
|
|
### Resolver Conversación
|
|
```http
|
|
POST /api/conversations/{conversation_id}/resolve
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"resolution_note": "Problema resuelto"
|
|
}
|
|
```
|
|
|
|
### Reabrir Conversación
|
|
```http
|
|
POST /api/conversations/{conversation_id}/reopen
|
|
```
|
|
|
|
---
|
|
|
|
## Mensajes
|
|
|
|
### Listar Mensajes de Conversación
|
|
```http
|
|
GET /api/conversations/{conversation_id}/messages
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| before | uuid | Mensajes antes de este ID |
|
|
| limit | int | Límite (default: 50) |
|
|
|
|
### Enviar Mensaje
|
|
```http
|
|
POST /api/conversations/{conversation_id}/messages
|
|
```
|
|
|
|
**Request (texto):**
|
|
```json
|
|
{
|
|
"type": "text",
|
|
"content": "Hola, ¿en qué te puedo ayudar?"
|
|
}
|
|
```
|
|
|
|
**Request (imagen):**
|
|
```json
|
|
{
|
|
"type": "image",
|
|
"media_url": "https://example.com/image.jpg",
|
|
"content": "Caption opcional"
|
|
}
|
|
```
|
|
|
|
**Request (botones):**
|
|
```json
|
|
{
|
|
"type": "buttons",
|
|
"content": "¿Qué necesitas?",
|
|
"metadata": {
|
|
"buttons": [
|
|
{"id": "ventas", "text": "Ventas"},
|
|
{"id": "soporte", "text": "Soporte"},
|
|
{"id": "otro", "text": "Otro"}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
**Request (lista):**
|
|
```json
|
|
{
|
|
"type": "list",
|
|
"content": "Selecciona una opción:",
|
|
"metadata": {
|
|
"button_text": "Ver opciones",
|
|
"sections": [
|
|
{
|
|
"title": "Productos",
|
|
"rows": [
|
|
{"id": "laptop", "title": "Laptops", "description": "Ver laptops disponibles"},
|
|
{"id": "telefono", "title": "Teléfonos", "description": "Ver teléfonos"}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Enviar Nota Interna
|
|
```http
|
|
POST /api/conversations/{conversation_id}/notes
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"content": "Cliente interesado, dar seguimiento"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Flujos
|
|
|
|
### Listar Flujos
|
|
```http
|
|
GET /api/flows
|
|
```
|
|
|
|
### Crear Flujo
|
|
```http
|
|
POST /api/flows
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"name": "Bienvenida",
|
|
"description": "Flujo de bienvenida para nuevos contactos",
|
|
"trigger_type": "welcome",
|
|
"trigger_value": null,
|
|
"nodes": {
|
|
"nodes": [...],
|
|
"edges": [...],
|
|
"viewport": {...}
|
|
},
|
|
"is_active": true
|
|
}
|
|
```
|
|
|
|
### Obtener Flujo
|
|
```http
|
|
GET /api/flows/{flow_id}
|
|
```
|
|
|
|
### Actualizar Flujo
|
|
```http
|
|
PUT /api/flows/{flow_id}
|
|
```
|
|
|
|
### Duplicar Flujo
|
|
```http
|
|
POST /api/flows/{flow_id}/duplicate
|
|
```
|
|
|
|
### Activar/Desactivar Flujo
|
|
```http
|
|
PUT /api/flows/{flow_id}/toggle
|
|
```
|
|
|
|
### Probar Flujo
|
|
```http
|
|
POST /api/flows/{flow_id}/test
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"phone_number": "+525551234567",
|
|
"initial_message": "Hola"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Colas
|
|
|
|
### Listar Colas
|
|
```http
|
|
GET /api/queues
|
|
```
|
|
|
|
### Crear Cola
|
|
```http
|
|
POST /api/queues
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"name": "Ventas",
|
|
"description": "Cola de atención de ventas",
|
|
"assignment_method": "least_busy",
|
|
"max_per_agent": 8,
|
|
"sla_first_response": 180,
|
|
"sla_resolution": 3600,
|
|
"business_hours": {
|
|
"monday": {"start": "09:00", "end": "18:00"},
|
|
"tuesday": {"start": "09:00", "end": "18:00"},
|
|
"wednesday": {"start": "09:00", "end": "18:00"},
|
|
"thursday": {"start": "09:00", "end": "18:00"},
|
|
"friday": {"start": "09:00", "end": "17:00"},
|
|
"saturday": {"start": "10:00", "end": "14:00"},
|
|
"sunday": null
|
|
},
|
|
"fallback_flow_id": "uuid"
|
|
}
|
|
```
|
|
|
|
### Obtener Cola
|
|
```http
|
|
GET /api/queues/{queue_id}
|
|
```
|
|
|
|
### Actualizar Cola
|
|
```http
|
|
PUT /api/queues/{queue_id}
|
|
```
|
|
|
|
### Agregar Agente a Cola
|
|
```http
|
|
POST /api/queues/{queue_id}/agents
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"user_id": "uuid",
|
|
"is_supervisor": false,
|
|
"skills": ["ventas", "ingles"]
|
|
}
|
|
```
|
|
|
|
### Remover Agente de Cola
|
|
```http
|
|
DELETE /api/queues/{queue_id}/agents/{user_id}
|
|
```
|
|
|
|
### Estadísticas de Cola
|
|
```http
|
|
GET /api/queues/{queue_id}/stats
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"waiting": 5,
|
|
"active": 12,
|
|
"resolved_today": 47,
|
|
"avg_first_response": 142,
|
|
"avg_resolution": 1823,
|
|
"sla_compliance": 0.91,
|
|
"agents": [
|
|
{
|
|
"user_id": "uuid",
|
|
"name": "María García",
|
|
"status": "online",
|
|
"active_conversations": 5,
|
|
"resolved_today": 12
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Respuestas Rápidas
|
|
|
|
### Listar Respuestas Rápidas
|
|
```http
|
|
GET /api/quick-replies
|
|
```
|
|
|
|
### Crear Respuesta Rápida
|
|
```http
|
|
POST /api/quick-replies
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"shortcut": "/saludo",
|
|
"content": "¡Hola {{contact.name}}! Soy {{agent.name}}, ¿en qué te puedo ayudar?",
|
|
"queue_id": null
|
|
}
|
|
```
|
|
|
|
### Actualizar Respuesta Rápida
|
|
```http
|
|
PUT /api/quick-replies/{id}
|
|
```
|
|
|
|
### Eliminar Respuesta Rápida
|
|
```http
|
|
DELETE /api/quick-replies/{id}
|
|
```
|
|
|
|
---
|
|
|
|
## Odoo
|
|
|
|
### Probar Conexión
|
|
```http
|
|
POST /api/odoo/test-connection
|
|
```
|
|
|
|
### Sincronizar Contactos
|
|
```http
|
|
POST /api/odoo/sync-contacts
|
|
```
|
|
|
|
### Buscar Partner
|
|
```http
|
|
GET /api/odoo/partners/search
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| phone | string | Buscar por teléfono |
|
|
| email | string | Buscar por email |
|
|
| name | string | Buscar por nombre |
|
|
|
|
### Buscar Pedidos
|
|
```http
|
|
GET /api/odoo/orders
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Parámetro | Tipo | Descripción |
|
|
|-----------|------|-------------|
|
|
| partner_id | int | ID del partner en Odoo |
|
|
| state | string | Estado del pedido |
|
|
| limit | int | Límite |
|
|
|
|
### Consultar Stock
|
|
```http
|
|
GET /api/odoo/products/{product_id}/stock
|
|
```
|
|
|
|
### Crear Lead
|
|
```http
|
|
POST /api/odoo/leads
|
|
```
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"name": "Interés en Producto X",
|
|
"contact_name": "Juan Pérez",
|
|
"phone": "+525551234567",
|
|
"email": "juan@email.com",
|
|
"description": "Cliente interesado en laptops",
|
|
"expected_revenue": 5000
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## WebSocket
|
|
|
|
### Conexión
|
|
```javascript
|
|
const socket = io('wss://tu-dominio.com', {
|
|
auth: {
|
|
token: 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...'
|
|
}
|
|
});
|
|
```
|
|
|
|
### Eventos del Servidor
|
|
|
|
**Nuevo mensaje:**
|
|
```javascript
|
|
socket.on('new_message', (data) => {
|
|
// data: { conversation_id, message }
|
|
});
|
|
```
|
|
|
|
**Estado de mensaje:**
|
|
```javascript
|
|
socket.on('message_status', (data) => {
|
|
// data: { message_id, status: 'delivered' | 'read' }
|
|
});
|
|
```
|
|
|
|
**Conversación asignada:**
|
|
```javascript
|
|
socket.on('conversation_assigned', (data) => {
|
|
// data: { conversation_id, assigned_to }
|
|
});
|
|
```
|
|
|
|
**QR Code:**
|
|
```javascript
|
|
socket.on('qr_code', (data) => {
|
|
// data: { account_id, qr_code }
|
|
});
|
|
```
|
|
|
|
**Estado de conexión WhatsApp:**
|
|
```javascript
|
|
socket.on('connection_status', (data) => {
|
|
// data: { account_id, status: 'connected' | 'disconnected' }
|
|
});
|
|
```
|
|
|
|
### Eventos del Cliente
|
|
|
|
**Unirse a conversación:**
|
|
```javascript
|
|
socket.emit('join_conversation', { conversation_id: 'uuid' });
|
|
```
|
|
|
|
**Escribiendo:**
|
|
```javascript
|
|
socket.emit('typing', { conversation_id: 'uuid' });
|
|
```
|
|
|
|
---
|
|
|
|
## Códigos de Error
|
|
|
|
| Código | Descripción |
|
|
|--------|-------------|
|
|
| 400 | Bad Request - Datos inválidos |
|
|
| 401 | Unauthorized - Token inválido o expirado |
|
|
| 403 | Forbidden - Sin permisos |
|
|
| 404 | Not Found - Recurso no encontrado |
|
|
| 409 | Conflict - Conflicto de datos |
|
|
| 422 | Unprocessable Entity - Validación fallida |
|
|
| 429 | Too Many Requests - Rate limit excedido |
|
|
| 500 | Internal Server Error |
|
|
|
|
**Formato de error:**
|
|
```json
|
|
{
|
|
"detail": {
|
|
"code": "VALIDATION_ERROR",
|
|
"message": "El campo email es requerido",
|
|
"field": "email"
|
|
}
|
|
}
|
|
```
|