Webhooks
Sistema de webhooks
Keirost permite registrar endpoints HTTP que reciben notificaciones cuando ocurren eventos en el sistema. Asi puedes integrar Keirost con sistemas externos (ERP externo, CRM, sistemas de contabilidad, etc.) en tiempo real.
Modelo de webhook
interface Webhook { id: string; name: string; // "Mi integracion CRM" url: string; // "https://mi-crm.com/webhook/keirost" method: 'POST' | 'GET'; events: WebhookEvent[]; headers?: Record<string, string>; secret?: string; // Para generar firma HMAC status: 'active' | 'inactive'; retry_policy: RetryPolicy; created_by: string; created_at: string;}
interface RetryPolicy { max_attempts: number; retry_delay_seconds: number[];}
type WebhookEvent = | 'document.created' | 'document.updated' | 'document.deleted' | 'document.sent' | 'document.locked' | 'document.cancelled' | 'payment.received' | 'payment.made' | 'stock.movement' | 'stock.low' | 'plugin.installed' | 'plugin.error' | 'user.created' | 'user.deleted' | 'automation.triggered' | 'notification.created' | '*'; // wildcard = todos los eventosEndpoints
| Metodo | Ruta | Descripcion |
|---|---|---|
| GET | /api/webhooks | Listar webhooks |
| POST | /api/webhooks | Crear webhook |
| GET | /api/webhooks/:id | Ver webhook |
| PATCH | /api/webhooks/:id | Actualizar webhook |
| DELETE | /api/webhooks/:id | Eliminar webhook |
| POST | /api/webhooks/:id/test | Enviar evento de prueba |
| GET | /api/webhooks/:id/logs | Ver logs de envios |
Crear webhook
POST /api/webhooksAuthorization: Bearer <token>Content-Type: application/json
{ "name": "Integracion miERP", "url": "https://mierp.com/webhook/keirost", "method": "POST", "events": ["document.created", "document.sent", "payment.received"], "headers": { "Authorization": "Bearer mi_api_key", "Content-Type": "application/json" }, "secret": "mi_webhook_secret_123", "retry_policy": { "max_attempts": 3, "retry_delay_seconds": [60, 300, 900] }}Eventos disponibles
| Evento | Descripcion |
|---|---|
document.created | Nuevo documento creado |
document.updated | Documento modificado |
document.deleted | Documento eliminado |
document.sent | Documento enviado por email |
document.locked | Documento asentado/bloqueado |
document.cancelled | Documento anulado |
payment.received | Pago recibido de cliente |
payment.made | Pago realizado a proveedor |
stock.movement | Movimiento de stock |
stock.low | Stock bajo el minimo |
user.created | Nuevo usuario creado |
user.deleted | Usuario eliminado |
automation.triggered | Automatizacion ejecutada |
notification.created | Nueva notificacion creada |
plugin.installed | Plugin instalado |
plugin.error | Error en plugin |
* | Todos los eventos |
Payload del webhook
Formato general
{ "id": "evt_001", "event": "document.created", "timestamp": "2026-05-08T10:00:00Z", "tenant_id": "tenant_demo", "data": { ... }}Ejemplo: documento creado
{ "id": "evt_001", "event": "document.created", "timestamp": "2026-05-08T10:00:00Z", "tenant_id": "tenant_demo", "data": { "document_type": "sales_invoice", "document_id": "inv_2026_0012", "series": "F", "number": 12, "partner_id": "bp_cliente1", "partner_name": "Acme S.L.", "total": 1210.00, "currency": "EUR", "status": "draft", "created_by": "user_admin", "created_at": "2026-05-08T10:00:00Z" }}Ejemplo: pago recibido
{ "id": "evt_002", "event": "payment.received", "timestamp": "2026-05-08T10:00:00Z", "tenant_id": "tenant_demo", "data": { "payment_id": "pay_in_001", "partner_id": "bp_cliente1", "amount": 1210.00, "payment_date": "2026-05-08", "payment_method": "transfer", "linked_document": { "type": "sales_invoice", "id": "inv_2026_0012", "new_status": "paid" } }}Seguridad: firma HMAC
Si configuras un secret, Keirost firma cada peticion con HMAC-SHA256:
X-Keirost-Signature: sha256=<hmac_hex>X-Keirost-Timestamp: <unix_timestamp>X-Keirost-Event: <event_name>Verificar firma en tu servidor
import crypto from 'crypto';
function verifyWebhookSignature( payload: string, signature: string, timestamp: string, secret: string): boolean { const body = `${timestamp}.${payload}`; const expected = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); return `sha256=${expected}` === signature;}Tambien verifica que el timestamp no sea mayor de 5 minutos para evitar replay attacks.
Logs de webhooks
GET /api/webhooks/:id/logs?from=2026-05-01&to=2026-05-08{ "data": [ { "id": "wlog_001", "event": "document.created", "document_id": "inv_2026_0012", "attempt": 1, "status": "success", "http_status": 200, "response_body": "OK", "response_time_ms": 145, "sent_at": "2026-05-08T10:00:00Z" }, { "id": "wlog_002", "event": "document.created", "document_id": "inv_2026_0013", "attempt": 3, "status": "failed", "http_status": 503, "error": "Service unavailable", "sent_at": "2026-05-08T10:05:00Z" } ]}Resumen de endpoints
| Metodo | Ruta | Descripcion |
|---|---|---|
| GET | /api/webhooks | Listar webhooks |
| POST | /api/webhooks | Crear webhook |
| GET | /api/webhooks/:id | Ver webhook |
| PATCH | /api/webhooks/:id | Actualizar webhook |
| DELETE | /api/webhooks/:id | Eliminar webhook |
| POST | /api/webhooks/:id/test | Enviar evento de prueba |
| GET | /api/webhooks/:id/logs | Ver logs de envios |