SOP — Módulo Integraciones (API REST v1 + Webhooks)
Tipo: procedimiento operativo estándar. Estado: demo-ready (F4b-DEMO). Ruta:
/integraciones. Fuente de verdad:lib/integraciones/,app/api/v1/,app/integraciones/page.tsx. RFC-2119 en español.
0. Contexto del módulo
El módulo de Integraciones expone una API REST v1 pública de demostración que permite a sistemas externos (ERP, WMS, SAT-connector) consumir datos del patio sin acceder a la interfaz web. Complementa con un panel de webhooks para recibir notificaciones de eventos del patio en sistemas terceros y con un ERP simulado que ejerce dichas llamadas en tiempo real durante la demo.
- API real, datos ILUSTRATIVOS. Los endpoints son funcionales y devuelven
respuestas estructuradas reales; el dataset proviene de
RFC_DEMO(tenant demo), no de un cliente productivo. Todas las respuestas llevan"demo": true. (D-011) - Sin ERP/WMS real conectado en esta fase. Los webhooks son de panel de configuración (ILUSTRATIVO); la entrega HTTP hacia destinos externos es CEO-gate.
- Supabase Auth activo (D-017). La sesión de usuario DEBE existir para abrir
/integraciones, pero las llamadas a/api/v1/*se autentican solo por API key (independiente de la sesión).
1. Propósito y alcance
Propósito: permitir que el rol admin configure, pruebe y documente el canal de
integración entre Patio Abierto y sistemas externos, sin necesidad de código adicional.
Alcance:
- Panel
/integraciones: visualización de endpoints, copia de API key, panel de webhooks, sandbox ERP. - API REST v1: tres endpoints GET autenticados por API key.
- Webhooks: catálogo de eventos suscribibles (configuración UI, entrega CEO-gate).
- Fuera de alcance: integración de Carta Porte / CFDI (módulo
/garita), módulo de facturación (/facturacion).
2. Roles y permisos
| Rol | Permiso requerido | Acceso a /integraciones | Llamadas a /api/v1/* |
|---|---|---|---|
admin | admin:gestionar | ✅ DEBE poder acceder | ✅ con API key demo |
supervisor | no tiene | ❌ redirige a /sin-acceso | ✅ con API key demo (HTTP directo) |
operador_garita | no tiene | ❌ redirige a /sin-acceso | ✅ con API key demo (HTTP directo) |
operador_patio | no tiene | ❌ redirige a /sin-acceso | ✅ con API key demo (HTTP directo) |
cliente_readonly | no tiene | ❌ redirige a /sin-acceso | ✅ con API key demo (HTTP directo) |
Nota: las llamadas a
/api/v1/*son API-key-gated, no session-gated. Cualquier sistema con la key demo puede llamarlas sin sesión. En producción con cliente real, la key DEBE ser por-tenant y hasheada (CEO-gate).
El gate server-side está en app/integraciones/page.tsx:
if (!usuario || !rolTienePermiso(usuario.rol, PERMISO.ADMIN_GESTIONAR)) redirect("/sin-acceso")
3. Precondiciones
- El usuario DEBE tener sesión activa en Supabase Auth (D-017).
- El usuario DEBE tener rol
admin(único conadmin:gestionar). - La app DEBE estar corriendo (local o Vercel). No se requiere
DATABASE_URL; los endpoints v1 funcionan con el store in-memory delib/patio(modo demo). - El consumidor externo DEBE disponer de la API key demo:
pa_demo_5f3c9b2a7e1d4680. En producción: la key DEBE ser secreta, por-tenant, hasheada. (CEO-gate)
4. Procedimiento paso a paso
4.1 Acceder al panel
- Iniciar sesión en Patio Abierto con un usuario de rol
admin. - Navegar a
/integraciones(enlace en el menú lateral bajo "Admin"). - El servidor valida el permiso
admin:gestionar; si falla, redirige a/sin-acceso. - El panel DEBE mostrar:
- Listado de endpoints v1 con método, ruta y descripción.
- API key demo copiable (
pa_demo_5f3c9b2a7e1d4680). - Catálogo de eventos de webhook suscribibles.
- Sección de ERP simulado (ILUSTRATIVO).
4.2 Consumir los endpoints de la API REST v1
Todos los endpoints son GET, base URL <origen>/api/v1/.
Autenticación (DEBE usar uno de los dos métodos):
Authorization: Bearer pa_demo_5f3c9b2a7e1d4680
# — o —
x-api-key: pa_demo_5f3c9b2a7e1d4680
Endpoints disponibles:
| Endpoint | Descripción | Parámetros |
|---|---|---|
GET /api/v1/inventario | Unidades en patio: ISO, estatus, posición, recinto, naviera, bloqueo, último movimiento. | — |
GET /api/v1/eventos | Bitácora de eventos del patio. Patrón incremental típico de sync ERP/WMS. | ?desde=<ISO 8601> (opcional) |
GET /api/v1/estado-cuenta | Totales de almacenaje: subtotal, maniobras, IVA, total en MXN y renglones de cargo. | — |
Sobre de respuesta estándar:
{
"demo": true,
"generado_at": "<ISO 8601>",
"total": 12,
"recurso": "inventario",
"data": [ ... ]
}
Procedimiento de prueba:
- Copiar la API key desde el panel.
- Ejecutar la llamada (curl, Postman, ERP simulado):
curl -H "Authorization: Bearer pa_demo_5f3c9b2a7e1d4680" \ https://<host>/api/v1/inventario - Verificar
"demo": trueen la respuesta (invariante D-011). - Para sync incremental de eventos, incluir
?desde=2026-07-01T00:00:00Z.
4.3 Configurar webhooks (ILUSTRATIVO en demo)
- En el panel de webhooks, seleccionar los eventos a suscribir:
contenedor.ingresocontenedor.salidacontenedor.avanza_etapasalida.bloqueadaestado_cuenta.actualizado
- Ingresar la URL del endpoint receptor en el ERP/WMS externo.
- Guardar la configuración.
- [ILUSTRATIVO] La entrega HTTP hacia destinos externos NO está activa en demo. La suscripción se persiste en UI únicamente. La activación de envío real es CEO-gate.
4.4 ERP simulado (ILUSTRATIVO)
El panel incluye un simulador que ejecuta las tres llamadas a /api/v1/* y muestra
las respuestas en tiempo real para propósitos de demostración ante prospectos.
- Hacer clic en "Simular ERP" (o equivalente en el panel).
- El simulador llama
inventario,eventosyestado-cuentacon la API key demo. - Las respuestas DEBEN mostrarse con
"demo": truevisible. - NO conectar este simulador a una base de datos de cliente real. (D-011)
5. Reglas e invariantes
DEBE cumplirse:
- Toda respuesta de
/api/v1/*DEBE incluir"demo": truemientras el tenant sea RFC_DEMO. (D-011) - La ruta
/integracionesDEBE validaradmin:gestionarserver-side en cada render. No confiar solo en el nav. - La API key demo PUEDE aparecer en la UI (es pública por diseño). La key de producción NO DEBE exponerse jamás.
- Los endpoints DEBEN devolver errores en JSON estructurado (nunca HTML). Usar
errorServidor()delib/integraciones/api.tspara errores 500. - La autenticación DEBE soportar tanto
Authorization: Bearer <key>comox-api-key: <key>(doble método para compatibilidad ERP). RFC_DEMODEBE estar hardcodeado en los routes de/api/v1/*; los routes NUNCA DEBEN leer el tenant de la sesión de usuario para la API demo (riesgo de data leak cross-tenant).
NO DEBE ocurrir:
- ❌ Exponer datos reales de un cliente bajo la API key demo.
- ❌ Usar la key demo
pa_demo_5f3c9b2a7e1d4680en producción con datos reales. - ❌ Activar la entrega de webhooks a URLs externas sin autorización del CEO.
- ❌ Quitar el campo
"demo": truede las respuestas sin haberlo reemplazado por la lógica multi-tenant real. - ❌ Devolver HTML (error de Next genérico) desde
/api/v1/*; siempre JSON. - ❌ Cachear las respuestas de la API v1 (
export const dynamic = "force-dynamic"en cada route).
6. Manejo de errores y escalamiento
| Código | Causa | Respuesta | Acción |
|---|---|---|---|
401 Unauthorized | API key ausente o inválida | { "error": "unauthorized", "demo": true } | El consumidor DEBE revisar el header Authorization o x-api-key. |
500 Internal Error | Fallo en getInventario / getEventosPatio / getEstadoCuenta | { "error": "internal_error", "demo": true } | Revisar logs del servidor (vercel → Runtime Logs). Escalar a G si persiste. |
403 / redirect | Usuario sin admin:gestionar accede a /integraciones | Redirect a /sin-acceso | Verificar rol del usuario en el selector de demo o en Supabase Auth. |
Escalamiento:
- Errores 401 repetidos desde un ERP/WMS: verificar que la key no tiene espacios extra ni saltos de línea.
- Errores 500 en producción con DB activa: revisar la conexión Prisma/Supabase y ejecutar
db:deploysi hay migraciones pendientes. - Cualquier exposición de datos de un cliente real bajo la key demo: 🔴 PARAR. Escalar al CEO de inmediato.
7. Notas de demo vs. producción
| Aspecto | Demo (estado actual) | Producción (CEO-gate) |
|---|---|---|
| API key | pa_demo_5f3c9b2a7e1d4680 (pública, un solo valor) | Por-tenant, generada y hasheada en BD, nunca expuesta en texto plano |
| Tenant | RFC_DEMO hardcodeado en cada route | Derivado de la API key: key → tenant_id → rfc |
| Datos | Inventario/eventos/estado-cuenta ILUSTRATIVOS | Datos reales del tenant |
| Webhooks | Configuración UI solamente; sin entrega HTTP | Entrega HTTP a URL del cliente con reintentos y firma HMAC |
| ERP simulado | Panel interactivo con datos demo | No aplica en prod (el ERP real se conecta directamente) |
"demo": true en respuestas | Siempre presente (D-011) | Ausente o "demo": false en entorno productivo |
[ILUSTRATIVO] Los webhooks, el ERP simulado y el panel de configuración de integraciones son funcionales como demostración. La activación de entrega a sistemas externos reales y la gestión de API keys por-tenant requieren aprobación CEO (D-016).