docs: API spec for ERP Palmas360 — all 16 endpoints documented
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>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
904a1be6ea
commit
fb28140e23
@@ -0,0 +1,497 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user