Complete endpoint specification for the ERP team: - 10 GET (download) endpoints returning PDF/Excel files - 6 POST (upload) endpoints receiving WhatsApp form data - Auth headers, request/response schemas, and endpoint_key mapping table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
498 lines
14 KiB
Markdown
498 lines
14 KiB
Markdown
# Especificación de Endpoints — ERP Palmas360 ↔ Bot WhatsApp
|
|
|
|
> **Para el equipo de Palmas360:** Este documento describe todos los endpoints que el ERP debe implementar para que el bot de WhatsApp funcione correctamente. Los endpoints marcados con ⚠️ actualmente apuntan a URLs de prueba (`httpbin.org/post`) y deben ser reemplazados con las URLs reales del ERP.
|
|
|
|
---
|
|
|
|
## Autenticación
|
|
|
|
Todas las llamadas del bot al ERP incluyen dos headers de autenticación:
|
|
|
|
```
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
```
|
|
|
|
El `api_key` es la clave configurada para Palmas360 en el bot. Validar cualquiera de los dos headers es suficiente.
|
|
|
|
---
|
|
|
|
## Resumen de endpoints
|
|
|
|
| # | Tipo | Endpoint ERP | Descripción | Estado |
|
|
|---|------|--------------|-------------|--------|
|
|
| 1 | GET | `/fincas` | Lista de fincas activas | Pendiente |
|
|
| 2 | GET | `/ciclos/cosecha` | Informe ciclos cosecha | Pendiente |
|
|
| 3 | GET | `/ciclos/sanidad/censo` | Informe ciclos censo | Pendiente |
|
|
| 4 | GET | `/ciclos/sanidad/plagas` | Informe ciclos plagas | Pendiente |
|
|
| 5 | GET | `/ciclos/sanidad/palm` | Informe RHYN. PALM. | Pendiente |
|
|
| 6 | GET | `/ciclos/sanidad/tratamientos` | Informe ciclos tratamientos | Pendiente |
|
|
| 7 | GET | `/ciclos/polinizacion` | Informe ciclos polinización | Pendiente |
|
|
| 8 | GET | `/produccion/kilos-finca` | Kilos facturados por finca | Pendiente |
|
|
| 9 | GET | `/produccion/kilos-lotes` | Kilos por lotes (rango fechas) | Pendiente |
|
|
| 10 | GET | `/mantenimiento` | Ciclos mantenimiento a la fecha | Pendiente |
|
|
| 11 | POST | `/ciclos/cosecha` | Registrar ciclo cosecha | ⚠️ Test |
|
|
| 12 | POST | `/ciclos/sanidad` | Registrar ciclo sanidad | ⚠️ Test |
|
|
| 13 | POST | `/ciclos/polinizacion` | Registrar ciclo polinización | ⚠️ Test |
|
|
| 14 | POST | `/tiquetes` | Registrar tiquete báscula | ⚠️ Test |
|
|
| 15 | POST | `/ausentismos` | Registrar ausentismo | ⚠️ Test |
|
|
| 16 | POST | `/pluviometria` | Registrar lecturas pluviometría | ⚠️ Test |
|
|
|
|
---
|
|
|
|
## Endpoints de DESCARGA (GET) — Bot consulta, ERP responde con archivo
|
|
|
|
El bot llama estos endpoints y reenvía la respuesta como documento al usuario de WhatsApp. **La respuesta debe ser un archivo descargable** (PDF o Excel).
|
|
|
|
### 1. Lista de fincas
|
|
|
|
Usado para mostrar la lista de fincas en flujos dinámicos (Producción kilos por finca, Pluviometría).
|
|
|
|
```
|
|
GET {url_base}/fincas
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
```
|
|
|
|
**Respuesta esperada (JSON, 200):**
|
|
```json
|
|
[
|
|
{ "id": "finca_001", "label": "Finca La Palma" },
|
|
{ "id": "finca_002", "label": "Finca El Diamante" },
|
|
{ "id": "finca_003", "label": "Finca Los Almendros" }
|
|
]
|
|
```
|
|
|
|
> El campo `id` es el valor que el bot usará internamente; `label` es lo que ve el usuario en WhatsApp.
|
|
|
|
---
|
|
|
|
### 2. Ciclos cosecha
|
|
|
|
```
|
|
GET {url_base}/ciclos/cosecha
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD) — fecha inicio del período
|
|
fecha_hasta (YYYY-MM-DD) — fecha fin del período
|
|
```
|
|
|
|
El bot envía automáticamente:
|
|
- **"Día actual"** → `fecha_desde` y `fecha_hasta` = hoy
|
|
- **"Histórico 30 días"** → `fecha_desde` = hace 30 días, `fecha_hasta` = hoy
|
|
|
|
**Respuesta esperada:** Archivo binario (PDF o Excel)
|
|
```
|
|
Content-Type: application/pdf
|
|
Content-Disposition: attachment; filename="ciclos_cosecha.pdf"
|
|
[bytes del archivo]
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Ciclos sanidad — Censo
|
|
|
|
```
|
|
GET {url_base}/ciclos/sanidad/censo
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel.
|
|
|
|
---
|
|
|
|
### 4. Ciclos sanidad — Plagas
|
|
|
|
```
|
|
GET {url_base}/ciclos/sanidad/plagas
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel.
|
|
|
|
---
|
|
|
|
### 5. Ciclos sanidad — RHYN. PALM.
|
|
|
|
```
|
|
GET {url_base}/ciclos/sanidad/palm
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel.
|
|
|
|
---
|
|
|
|
### 6. Ciclos sanidad — Tratamientos
|
|
|
|
```
|
|
GET {url_base}/ciclos/sanidad/tratamientos
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel.
|
|
|
|
---
|
|
|
|
### 7. Ciclos polinización
|
|
|
|
```
|
|
GET {url_base}/ciclos/polinizacion
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel.
|
|
|
|
---
|
|
|
|
### 8. Producción kilos por finca
|
|
|
|
```
|
|
GET {url_base}/produccion/kilos-finca
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
finca_id — ID de la finca seleccionada por el usuario (viene de /fincas)
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel con kilos facturados para esa finca.
|
|
|
|
---
|
|
|
|
### 9. Producción kilos por lotes
|
|
|
|
```
|
|
GET {url_base}/produccion/kilos-lotes
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD) — ingresada por el usuario
|
|
fecha_hasta (YYYY-MM-DD) — ingresada por el usuario
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel con kilos por lote en el rango de fechas.
|
|
|
|
---
|
|
|
|
### 10. Mantenimiento
|
|
|
|
```
|
|
GET {url_base}/mantenimiento
|
|
Headers:
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
Query params:
|
|
fecha_desde (YYYY-MM-DD)
|
|
fecha_hasta (YYYY-MM-DD)
|
|
```
|
|
|
|
**Respuesta:** Archivo PDF o Excel con ciclos de mantenimiento.
|
|
|
|
---
|
|
|
|
## Endpoints de SUBIDA (POST) — Bot envía datos capturados del usuario ⚠️
|
|
|
|
El bot guía al usuario campo por campo, muestra un resumen, pide confirmación, y luego hace un POST al ERP con los datos. El usuario que envía incluye siempre su número de teléfono y nombre de perfil de WhatsApp.
|
|
|
|
**Headers en todos los POST:**
|
|
```
|
|
Content-Type: application/json
|
|
Authorization: Bearer {api_key}
|
|
X-API-Key: {api_key}
|
|
```
|
|
|
|
**Respuesta esperada en todos los POST (200):**
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"message": "Registro guardado correctamente"
|
|
}
|
|
```
|
|
|
|
Si hay error (400/500):
|
|
```json
|
|
{
|
|
"status": "error",
|
|
"message": "Descripción del error"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 11. ⚠️ Registrar ciclo cosecha
|
|
|
|
```
|
|
POST {url_base}/ciclos/cosecha
|
|
```
|
|
|
|
**Body JSON:**
|
|
```json
|
|
{
|
|
"fecha": "2026-06-30",
|
|
"finca": "La Palma",
|
|
"lote": "Lote 3A",
|
|
"racimos": "120",
|
|
"telefono": "573168950803",
|
|
"nombre": "Juan Pérez"
|
|
}
|
|
```
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| `fecha` | string (YYYY-MM-DD o texto libre) | Fecha del ciclo ingresada por el usuario |
|
|
| `finca` | string | Nombre de la finca |
|
|
| `lote` | string | Identificador del lote |
|
|
| `racimos` | string | Cantidad de racimos |
|
|
| `telefono` | string | Número WhatsApp del usuario que reporta |
|
|
| `nombre` | string | Nombre del perfil WhatsApp del usuario |
|
|
|
|
---
|
|
|
|
### 12. ⚠️ Registrar ciclo sanidad
|
|
|
|
```
|
|
POST {url_base}/ciclos/sanidad
|
|
```
|
|
|
|
**Body JSON:**
|
|
```json
|
|
{
|
|
"fecha": "2026-06-30",
|
|
"finca": "La Palma",
|
|
"tipo_ciclo": "Censo",
|
|
"observaciones":"Sin novedades",
|
|
"telefono": "573168950803",
|
|
"nombre": "Juan Pérez"
|
|
}
|
|
```
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| `fecha` | string | Fecha del ciclo |
|
|
| `finca` | string | Nombre de la finca |
|
|
| `tipo_ciclo` | string | Tipo de ciclo (Censo, Plagas, RHYN, Tratamiento…) |
|
|
| `observaciones` | string | Observaciones libres del usuario |
|
|
| `telefono` | string | Número WhatsApp |
|
|
| `nombre` | string | Nombre perfil WhatsApp |
|
|
|
|
---
|
|
|
|
### 13. ⚠️ Registrar ciclo polinización
|
|
|
|
```
|
|
POST {url_base}/ciclos/polinizacion
|
|
```
|
|
|
|
**Body JSON:**
|
|
```json
|
|
{
|
|
"fecha": "2026-06-30",
|
|
"finca": "La Palma",
|
|
"lote": "Lote 2B",
|
|
"palmas_polinizadas": "85",
|
|
"telefono": "573168950803",
|
|
"nombre": "Juan Pérez"
|
|
}
|
|
```
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| `fecha` | string | Fecha del ciclo |
|
|
| `finca` | string | Nombre de la finca |
|
|
| `lote` | string | Lote trabajado |
|
|
| `palmas_polinizadas` | string | Número de palmas polinizadas |
|
|
| `telefono` | string | Número WhatsApp |
|
|
| `nombre` | string | Nombre perfil WhatsApp |
|
|
|
|
---
|
|
|
|
### 14. ⚠️ Registrar tiquete báscula
|
|
|
|
```
|
|
POST {url_base}/tiquetes
|
|
```
|
|
|
|
**Body JSON:**
|
|
```json
|
|
{
|
|
"fecha": "2026-06-30",
|
|
"numero_tiquete": "T-00452",
|
|
"finca": "El Diamante",
|
|
"kilos": "3450",
|
|
"telefono": "573168950803",
|
|
"nombre": "Juan Pérez"
|
|
}
|
|
```
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| `fecha` | string | Fecha del tiquete |
|
|
| `numero_tiquete` | string | Número del tiquete de báscula |
|
|
| `finca` | string | Finca de origen |
|
|
| `kilos` | string | Kilos registrados en báscula |
|
|
| `telefono` | string | Número WhatsApp |
|
|
| `nombre` | string | Nombre perfil WhatsApp |
|
|
|
|
---
|
|
|
|
### 15. ⚠️ Registrar ausentismo
|
|
|
|
```
|
|
POST {url_base}/ausentismos
|
|
```
|
|
|
|
**Body JSON:**
|
|
```json
|
|
{
|
|
"fecha": "2026-06-30",
|
|
"empleado": "Carlos Ramírez",
|
|
"motivo": "Incapacidad médica",
|
|
"dias": "3",
|
|
"telefono": "573168950803",
|
|
"nombre": "Juan Pérez"
|
|
}
|
|
```
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| `fecha` | string | Fecha de inicio del ausentismo |
|
|
| `empleado` | string | Nombre del empleado ausente |
|
|
| `motivo` | string | Motivo del ausentismo |
|
|
| `dias` | string | Días de ausentismo |
|
|
| `telefono` | string | Número WhatsApp |
|
|
| `nombre` | string | Nombre perfil WhatsApp |
|
|
|
|
---
|
|
|
|
### 16. ⚠️ Registrar pluviometría
|
|
|
|
Este endpoint es diferente: el bot pregunta el valor por cada finca (usando la lista de `/fincas`) y envía **un array** con todas las lecturas en una sola llamada.
|
|
|
|
```
|
|
POST {url_base}/pluviometria
|
|
```
|
|
|
|
**Body JSON:**
|
|
```json
|
|
{
|
|
"fecha": "2026-06-30",
|
|
"telefono": "573168950803",
|
|
"nombre": "Juan Pérez",
|
|
"lecturas": [
|
|
{ "id": "finca_001", "label": "Finca La Palma", "valor": "45" },
|
|
{ "id": "finca_002", "label": "Finca El Diamante", "valor": "38" },
|
|
{ "id": "finca_003", "label": "Finca Los Almendros", "valor": "52" }
|
|
]
|
|
}
|
|
```
|
|
|
|
| Campo | Tipo | Descripción |
|
|
|-------|------|-------------|
|
|
| `fecha` | string | Fecha de la medición |
|
|
| `telefono` | string | Número WhatsApp |
|
|
| `nombre` | string | Nombre perfil WhatsApp |
|
|
| `lecturas[].id` | string | ID de la finca (viene de `/fincas`) |
|
|
| `lecturas[].label` | string | Nombre de la finca |
|
|
| `lecturas[].valor` | string | Milímetros registrados (texto libre del usuario) |
|
|
|
|
---
|
|
|
|
## Formato de respuesta para archivos (endpoints GET)
|
|
|
|
El bot espera recibir el archivo directamente en la respuesta HTTP. Formatos soportados:
|
|
|
|
| Content-Type | Extensión | Notas |
|
|
|---|---|---|
|
|
| `application/pdf` | `.pdf` | Preferido para informes |
|
|
| `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` | `.xlsx` | Excel moderno |
|
|
| `application/vnd.ms-excel` | `.xls` | Excel legacy |
|
|
|
|
**Headers recomendados en la respuesta:**
|
|
```
|
|
Content-Type: application/pdf
|
|
Content-Disposition: attachment; filename="reporte_cosecha_2026-06-30.pdf"
|
|
Content-Length: {tamaño en bytes}
|
|
```
|
|
|
|
> Si el archivo pesa más de **16 MB**, WhatsApp rechazará el envío. Para reportes grandes, considerar dividirlos por período o reducir el rango de fechas.
|
|
|
|
---
|
|
|
|
## Configuración en el bot
|
|
|
|
Una vez que el ERP tenga los endpoints listos, hay que actualizar las URLs en:
|
|
|
|
**Admin → Bot Config → Endpoints** (`https://admin.palmas360.com/admin/bot-config?id=2`)
|
|
|
|
Los `endpoint_key` que debe buscar y actualizar son:
|
|
|
|
| endpoint_key | URL actual (test) | URL real a colocar |
|
|
|---|---|---|
|
|
| `fincas_list_dn` | — | `{url_base}/fincas` |
|
|
| `cosecha_dn` | — | `{url_base}/ciclos/cosecha` |
|
|
| `ciclo_censo_dn` | — | `{url_base}/ciclos/sanidad/censo` |
|
|
| `ciclo_plagas_dn` | — | `{url_base}/ciclos/sanidad/plagas` |
|
|
| `ciclo_palm_dn` | — | `{url_base}/ciclos/sanidad/palm` |
|
|
| `ciclo_tratamiento_dn` | — | `{url_base}/ciclos/sanidad/tratamientos` |
|
|
| `ciclo_polinizacion_dn` | — | `{url_base}/ciclos/polinizacion` |
|
|
| `kilos_finca_dn` | — | `{url_base}/produccion/kilos-finca` |
|
|
| `produccion_lotes_dn` | — | `{url_base}/produccion/kilos-lotes` |
|
|
| `mantenimiento_dn` | — | `{url_base}/mantenimiento` |
|
|
| `ciclos_cosecha_up` | `https://httpbin.org/post` | `{url_base}/ciclos/cosecha` |
|
|
| `ciclos_sanidad_up` | `https://httpbin.org/post` | `{url_base}/ciclos/sanidad` |
|
|
| `ciclos_polinizacion_up` | `https://httpbin.org/post` | `{url_base}/ciclos/polinizacion` |
|
|
| `tiquetes_up` | `https://httpbin.org/post` | `{url_base}/tiquetes` |
|
|
| `ausentismos_up` | `https://httpbin.org/post` | `{url_base}/ausentismos` |
|
|
| `pluvio_upload` | `https://httpbin.org/post` | `{url_base}/pluviometria` |
|
|
|
|
---
|
|
|
|
## Preguntas frecuentes
|
|
|
|
**¿Los valores numéricos (kilos, días, racimos) vienen como número o texto?**
|
|
Vienen como `string` (texto libre que escribió el usuario). El ERP debe convertirlos al tipo necesario.
|
|
|
|
**¿El campo `fecha` está en formato ISO?**
|
|
El usuario la escribe libremente (puede ser "30/06/2026", "hoy", "30 de junio"...). Se recomienda que el ERP acepte texto y aplique parsing, o el bot puede configurarse para validar el formato antes de enviar (a coordinar).
|
|
|
|
**¿Qué pasa si el ERP responde un error?**
|
|
Si el ERP devuelve HTTP 4xx o 5xx, el bot muestra al usuario: *"Hubo un error al enviar los datos. Intenta nuevamente."*
|
|
|
|
**¿Cómo se prueba antes de tener el ERP listo?**
|
|
Los endpoints de upload actualmente apuntan a `https://httpbin.org/post`, que devuelve el body recibido. Sirve para confirmar que el bot está enviando los datos correctamente.
|
|
|
|
**¿Con qué frecuencia llaman los informes?**
|
|
Solo cuando el usuario lo solicita manualmente vía WhatsApp. No hay llamadas automáticas o en segundo plano.
|