* feat(docs): mirror every docs/ page in all 65 locales Extends the documentation mirrors from the 22-page core set (#13940) to every Markdown page under docs/: 152 sources x 65 locales = 9,880 mirrors (6,208 new), language bars rewritten for the full locale list, state adopted so the blocking drift gate now covers all 152 pages. run-translation.mjs: an oversized block made only of table rows or list items (PROVIDER_REFERENCE.md 244-row table, FREE_TIERS.md 71-item list) is cut at item boundaries and rejoined without a blank line — the single 16-40 KB request outlived the backend socket for verbose scripts. 48 older mirrors whose tables had lost rows were retranslated with --force. * docs(i18n): refresh mirrors for the sources the base changed since the branch cut Section-level retranslation of the 29 docs (and README.md) whose source or mirrors moved on release/v3.8.51 during the run, then state adoption; the drift gate is green again on the merged tree.
15 KiB
Webhooks (Español)
🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW
Fuente de referencia:
src/lib/webhookDispatcher.ts,src/lib/db/webhooks.ts,src/app/api/webhooks/Última actualización: 2026-06-28 — v3.8.40
OmniRoute puede activar webhooks HTTP en respuesta a eventos de la plataforma. Úselos para integrarse con Slack, PagerDuty, Datadog, servicios internos de alertas o cualquier receptor HTTP.
El despachador firma cada entrega con HMAC-SHA256, reintenta ante fallos transitorios, supervisa el estado de las entregas de cada webhook y deshabilita automáticamente los endpoints que siguen fallando.
Eventos compatibles
El tipo WebhookEvent (src/lib/webhooks/eventDescriptions.ts, utilizado por src/lib/webhookDispatcher.ts) actualmente modela exactamente cuatro eventos:
| Evento | Se activa cuando |
|---|---|
request.completed |
Una solicitud enviada mediante proxy finaliza correctamente |
request.failed |
Una solicitud enviada mediante proxy falla tras todos los reintentos/mecanismos alternativos |
quota.exceeded |
Una clave de API supera un umbral de presupuesto/cuota |
test.ping |
Evento sintético utilizado por el endpoint de prueba |
Las suscripciones aceptan el literal "*" para recibir todos los eventos. Los nombres de eventos
desconocidos en events se ignoran en el momento del despacho.
Nota: la API del despachador está conectada, pero los puntos de llamada de producción para algunos de los eventos distintos de
test.pingaún se están incorporando. Consultegrep dispatchEventpara comprobar qué rutas invocan actualmente al despachador en su versión.
Arquitectura
Invocador (controlador, servicio, monitor)
dispatchEvent(event, data) [src/lib/webhookDispatcher.ts]
-> getEnabledWebhooks() [src/lib/db/webhooks.ts]
-> filtrar por webhook.events
-> para cada coincidencia (en paralelo):
deliverWebhook(url, payload, secret)
crear la carga útil { event, timestamp, data }
firmar el cuerpo con HMAC-SHA256 (si hay un secreto)
POST con un tiempo de espera de 10 s
reintentar hasta 3 veces ante errores 5xx/de red
recordWebhookDelivery(id, status, success)
-> disableWebhooksWithHighFailures(10)
El despacho no bloquea ni espera resultados para el invocador: Promise.allSettled absorbe los
errores de cada webhook, de modo que un receptor defectuoso no pueda bloquear a los demás.
Firma HMAC
Cuando un webhook tiene un secret, OmniRoute firma el cuerpo JSON y envía:
Content-Type: application/json
User-Agent: OmniRoute-Webhook/1.0
X-Webhook-Event: <event>
X-Webhook-Timestamp: <ISO-8601>
X-Webhook-Signature: sha256=<hex HMAC-SHA256(secret, body)>
Los nombres de las cabeceras utilizan el prefijo
X-Webhook-*(noX-OmniRoute-*). El valor de la firma essha256=<hex>; verifique el prefijo completo.
Si se llama a createWebhook sin un secreto, el módulo de la base de datos genera uno
(whsec_<48 hex>), por lo que todos los webhooks se firman de forma predeterminada.
Verificación en el receptor
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody: string, signature: string, secret: string) {
const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signature);
return a.length === b.length && timingSafeEqual(a, b);
}
Verifique siempre la firma con respecto al cuerpo sin procesar de la solicitud, antes de cualquier análisis de JSON.
Política de reintentos y fallos
deliverWebhook(url, payload, secret, maxRetries = 3):
- Tiempo de espera de 10 segundos por intento (
AbortController). - Una respuesta HTTP 2xx se considera un éxito.
- Una respuesta HTTP 3xx/4xx se considera un estado final no reintentable — se registra como entregada
con
success = res.ok. - Las respuestas HTTP 5xx y los errores de red se reintentan con retroceso exponencial:
2^attempt * 1000 ms(1s, 2s, 4s). - Después de
maxRetries, la entrega se registra como fallida. - Cada entrega actualiza
last_triggered_at,last_statusy restablece o incrementafailure_count. - El despachador llama a
disableWebhooksWithHighFailures(10)después de cada distribución, por lo que cualquier webhook confailure_count >= 10se deshabilita automáticamente.
Base de datos
Tabla webhooks (migración 011_webhooks.sql):
| Columna | Tipo | Notas |
|---|---|---|
id |
TEXT PK | UUID |
url |
TEXT | URL de destino |
events |
TEXT | Matriz JSON; valor predeterminado ["*"] |
secret |
TEXT | Secreto HMAC (generado automáticamente si no se proporciona) |
enabled |
INT | 0/1; valor predeterminado 1 |
description |
TEXT | Etiqueta legible opcional |
created_at |
TEXT | datetime('now') |
last_triggered_at |
TEXT | Se actualiza en cada intento de entrega |
last_status |
INT | Estado HTTP del último intento (0 = red) |
failure_count |
INT | Se restablece a 0 en caso de éxito, +1 en caso de fallo |
El historial de entregas se conserva en la tabla específica webhook_deliveries
(migración 069_webhook_deliveries.sql, escrito mediante
src/lib/db/webhookDeliveries.ts::insertDelivery en cada intento), además
de los contadores agregados en la fila de webhooks. Los metadatos de tipo (Slack / Discord /
Telegram / transformadores de carga útil personalizados) se añadieron mediante 070_webhooks_kind_metadata.sql.
API REST
Todos los endpoints requieren autenticación de administración (requireManagementAuth).
| Endpoint | Método | Descripción |
|---|---|---|
/api/webhooks |
GET | Enumera los webhooks (secretos enmascarados) |
/api/webhooks |
POST | Crea un webhook |
/api/webhooks/[id] |
GET | Detalles del webhook (secreto completo) |
/api/webhooks/[id] |
PUT | Actualiza los campos |
/api/webhooks/[id] |
DELETE | Elimina |
/api/webhooks/[id]/test |
POST | Envía un test.ping (sin reintentos) |
/api/webhooks/[id]/deliveries |
GET | Intentos de entrega recientes de un webhook |
/api/webhooks/validate-url |
POST | Validación preliminar de la URL (protección contra SSRF) |
GET /api/webhooks enmascara el secreto como <primeros 10 caracteres>... para evitar filtrarlo
en las páginas de listado. Utilice el GET de [id] cuando realmente necesite el secreto.
Crear un webhook
curl -X POST http://localhost:20128/api/webhooks \
-H "Cookie: auth_token=..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.slack.com/services/...",
"secret": "whsec_my_shared_secret",
"events": ["quota.exceeded", "request.failed"],
"description": "Alertas de Slack"
}'
Si se omite secret, el servidor genera un secreto whsec_<hex> y lo devuelve
en la respuesta.
Probar un webhook
curl -X POST http://localhost:20128/api/webhooks/<id>/test \
-H "Cookie: auth_token=..."
Devuelve { delivered, status, error }. No se realizan reintentos, lo que resulta útil para
validar rápidamente que el receptor acepta la carga útil y la firma.
Panel de control
La página del panel de control en /dashboard/webhooks (consulte
src/app/(dashboard)/dashboard/webhooks/page.tsx) permite:
- Crear/editar webhooks con un selector de eventos
- Indicador de estado (activo / inactivo / con errores) basado en
enabled,failure_countylast_status - Entrega de prueba con un solo clic
- Activación/desactivación manual
Ejemplos de payloads
request.completed
{
"event": "request.completed",
"timestamp": "2026-05-13T20:30:00.123Z",
"data": {
"trace_id": "...",
"api_key_id": "...",
"provider": "openai",
"model": "gpt-5",
"status": 200,
"tokens_in": 142,
"tokens_out": 350,
"cost_usd": 0.0042
}
}
test.ping
{
"event": "test.ping",
"timestamp": "2026-05-13T20:32:00.000Z",
"data": {
"message": "Test webhook delivery from OmniRoute",
"webhookId": "<uuid>"
}
}
La estructura de los campos para los eventos distintos de test.ping está definida por los puntos de llamada que los emiten; trate el objeto data como compatible con versiones futuras (añada campos, no dependa de su ausencia).
Prácticas recomendadas
- Verifique la firma en cada entrega comparándola con el cuerpo sin procesar; esto evita solicitudes POST falsificadas de cualquiera que adivine la URL de su webhook.
- Responda con un código 2xx en un plazo de ~5 segundos; el tiempo de espera del despachador se agota a los 10 s. Los receptores
lentos consumirán reintentos e incrementarán
failure_count. - Haga que los controladores sean idempotentes; los reintentos y la semántica de entrega de al menos una vez implican que puede haber duplicados.
- Suscríbase de forma selectiva; incluya solo los eventos que realmente consume;
"*"añadirá costes en receptores que no controla. - Supervise
failure_count; los endpoints se desactivan automáticamente tras 10 fallos consecutivos; restablézcalos llamando aPUT /api/webhooks/[id]conenabled: truedespués de corregir el receptor. - Rote los secretos periódicamente; envíe mediante
PUTun nuevosecret, despliegue el nuevo valor en el receptor y confírmelo mediante el endpoint de prueba.
Véase también
- API_REFERENCE.md — referencia completa de la API de administración
- RESILIENCE_GUIDE.md — semántica del disyuntor / período de espera
utilizada para los fallos de proveedores expuestos mediante
request.failed - Código fuente:
src/lib/webhookDispatcher.ts,src/lib/db/webhooks.ts