Webhooks
El endpoint de webhook permite que un sistema externo (un ERP, un formulario, un CRM, una herramienta de CI/CD, etc.) dispare la ejecución de un proceso de NORA enviando una sola petición HTTP. Es la vía más directa para integrar NORA con eventos de negocio: cuando ocurre algo en tu sistema, lanzas un job.
Endpoint
Sección titulada «Endpoint»POST /api/v1/webhooks/trigger/{process_id}- URL base de producción:
https://nora.valisoftconsulting.com process_id(en la ruta): UUID del proceso a ejecutar.- Devuelve
201 Createdcon el job creado.
Autenticación
Sección titulada «Autenticación»La autenticación es por API key, igual que el resto de la superficie pública. Envía la cabecera:
X-API-Key: nora_ak_...La key se crea en Settings → API Keys y debe estar activa y no expirada. A diferencia de /jobs/trigger, este endpoint no exige un scope concreto (jobs:write): basta con una API key válida del tenant cuyo plan incluya la feature webhooks. Si la key define una lista de IPs permitidas, la IP de origen debe estar en ella.
Además de la autenticación, la petición pasa por estas comprobaciones, en orden:
- La feature
webhooksestá disponible en el plan del tenant. - La cuota mensual de ejecuciones no está agotada (se incrementa de forma atómica en cada disparo).
- La suscripción del tenant está activa.
- El proceso existe, pertenece al tenant de la key y está activo (
is_active = true). Si no,404.
Cuerpo de la petición
Sección titulada «Cuerpo de la petición»El cuerpo es JSON con el esquema WebhookTriggerRequest:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
machine_id | UUID | Sí | Máquina (robot) donde se ejecutará el job. |
input_data | objeto JSON | No | Datos de entrada que se pasan al proceso. |
{ "machine_id": "8f2b1c9e-3a44-4b2e-9d1a-6c0f5e7a2b11", "input_data": { "numero_factura": "F001-000123", "monto": 1500.50 }}Validación del payload (JSON Schema)
Sección titulada «Validación del payload (JSON Schema)»Si el proceso define un input_schema (un JSON Schema configurado en el proceso), NORA valida input_data contra él antes de crear el job:
- Si el proceso tiene
input_schemay no envíasinput_data, recibes422con el mensaje: “El proceso requiere input_data según su schema”. - Si
input_datano cumple el esquema, recibes422con el detalle del error de validación de JSON Schema, por ejemplo: “input_data no cumple el schema del proceso: ‘monto’ is a required property”.
Si el proceso no define input_schema, input_data se acepta tal cual (sin validación de forma) y se entrega al proceso.
flowchart TD
A[POST /webhooks/trigger/process_id] --> B{API key válida?}
B -- No --> E1[401 / 403]
B -- Sí --> C{Plan incluye webhooks + cuota + suscripción?}
C -- No --> E2[403 / límite]
C -- Sí --> D{Proceso existe, del tenant y activo?}
D -- No --> E3[404]
D -- Sí --> F{Proceso tiene input_schema?}
F -- Sí --> G{input_data cumple el schema?}
G -- No --> E4[422]
G -- Sí --> H[Crear job]
F -- No --> H
H --> I[201 Created con el job]
Rate limit
Sección titulada «Rate limit»El endpoint está limitado a 60 peticiones por minuto. El cupo se aplica por API key (no por IP): si la cabecera X-API-Key está presente, todas las peticiones con esa key comparten el mismo cupo aunque provengan de distintas IPs. Al superarlo, la API responde con 429 Too Many Requests.
Respuesta
Sección titulada «Respuesta»La respuesta sigue el envoltorio estándar de la API: {"success": true, "data": ...}. En data viaja el job creado (JobResponse), inicialmente en estado pending.
{ "success": true, "data": { "id": "b3d8a1f0-7c2e-4a59-9f12-0a4d6e8c1b22", "tenant_id": "1a2b3c4d-0000-0000-0000-000000000001", "process_id": "5e6f7a8b-1111-2222-3333-444455556666", "machine_id": "8f2b1c9e-3a44-4b2e-9d1a-6c0f5e7a2b11", "status": "pending", "priority": 3, "input_data": { "numero_factura": "F001-000123", "monto": 1500.50 }, "output_data": null, "logs": null, "error_message": null, "started_at": null, "finished_at": null, "retry_count": 0, "stop_requested": false, "created_at": "2026-06-19T12:00:00Z", "updated_at": "2026-06-19T12:00:00Z" }}Cada disparo queda registrado en el audit log del tenant con action = "trigger_job" y source = "webhook".
Ejemplo con curl
Sección titulada «Ejemplo con curl»curl -X POST \ "https://nora-api.valisoftconsulting.com/api/v1/webhooks/trigger/5e6f7a8b-1111-2222-3333-444455556666" \ -H "X-API-Key: nora_ak_xxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "machine_id": "8f2b1c9e-3a44-4b2e-9d1a-6c0f5e7a2b11", "input_data": { "numero_factura": "F001-000123", "monto": 1500.50 } }'Webhook vs. /jobs/trigger
Sección titulada «Webhook vs. /jobs/trigger»Ambos endpoints crean un job con una API key, pero están pensados para usos distintos:
| Aspecto | POST /webhooks/trigger/{process_id} | POST /jobs/trigger |
|---|---|---|
process_id | En la ruta (URL) | En el cuerpo |
| Scope requerido | Ninguno (solo key válida) | jobs:write |
| Feature de plan | webhooks (Pro/Enterprise) | api_keys (Pro/Enterprise) |
machine_id | Obligatorio | Opcional (NORA auto-selecciona una máquina online y activa) |
priority | No configurable (queda en el valor por defecto) | Configurable (1–5) |
Validación contra input_schema | Sí, si el proceso lo define | No |
| Rate limit | 60/min por key | 30/min por key |
| Pensado para | URL fija por proceso para integraciones tipo “webhook” externas | Disparo programático genérico desde tu backend |
Errores comunes
Sección titulada «Errores comunes»| Código | Causa |
|---|---|
401 | Falta la cabecera X-API-Key, o la key es inválida/revocada/expirada. |
403 | El plan no incluye webhooks, la IP no está autorizada para la key, o la suscripción no está activa. |
404 | El proceso no existe, no pertenece al tenant o está inactivo. |
422 | El cuerpo no cumple el esquema (machine_id faltante/ inválido) o input_data no cumple el input_schema del proceso. |
429 | Se superó el límite de 60 peticiones por minuto. |
Consulta también autenticación y la guía de jobs.