* 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.
14 KiB
Webhooks (Português (Portugal))
🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇸 es · 🇪🇪 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-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW
Fonte fidedigna:
src/lib/webhookDispatcher.ts,src/lib/db/webhooks.ts,src/app/api/webhooks/Última atualização: 2026-06-28 — v3.8.40
O OmniRoute pode acionar webhooks HTTP em eventos da plataforma. Utilize-os para integrar com o Slack, PagerDuty, Datadog, serviços internos de alerta ou qualquer recetor HTTP.
O dispatcher assina cada entrega com HMAC-SHA256, efetua novas tentativas em caso de falhas transitórias, monitoriza o estado das entregas por webhook e desativa automaticamente os endpoints que continuam a falhar.
Eventos suportados
O tipo WebhookEvent (src/lib/webhooks/eventDescriptions.ts, utilizado por src/lib/webhookDispatcher.ts) modela atualmente exatamente quatro eventos:
| Evento | Acionado quando |
|---|---|
request.completed |
Um pedido encaminhado é concluído com êxito |
request.failed |
Um pedido encaminhado falha após todas as tentativas/fallback |
quota.exceeded |
Uma chave de API ultrapassa um limite de orçamento/quota |
test.ping |
Evento sintético utilizado pelo endpoint de teste |
As subscrições aceitam o literal "*" para receber todos os eventos. Os nomes de eventos
desconhecidos em events são ignorados durante o envio.
Nota: a API do dispatcher está ligada, mas os pontos de chamada em produção para alguns dos eventos que não são
test.pingainda estão a ser implementados. Consultegrep dispatchEventpara saber que fluxos invocam atualmente o dispatcher na sua versão.
Arquitetura
Chamador (handler, serviço, monitor)
dispatchEvent(event, data) [src/lib/webhookDispatcher.ts]
-> getEnabledWebhooks() [src/lib/db/webhooks.ts]
-> filtrar por webhook.events
-> para cada correspondência (em paralelo):
deliverWebhook(url, payload, secret)
criar payload { event, timestamp, data }
assinar o corpo com HMAC-SHA256 (se existir um segredo)
POST com timeout de 10 s
repetir até 3 vezes em caso de erro 5xx / erro de rede
recordWebhookDelivery(id, status, success)
-> disableWebhooksWithHighFailures(10)
O envio é efetuado sem aguardar o resultado para o chamador: Promise.allSettled ignora
os erros individuais de cada webhook, pelo que um recetor com problemas não pode bloquear os restantes.
Assinatura HMAC
Quando um webhook tem um secret, o OmniRoute assina o corpo JSON e envia:
Content-Type: application/json
User-Agent: OmniRoute-Webhook/1.0
X-Webhook-Event: <evento>
X-Webhook-Timestamp: <ISO-8601>
X-Webhook-Signature: sha256=<HMAC-SHA256(secret, corpo) em hexadecimal>
Os nomes dos cabeçalhos utilizam o prefixo
X-Webhook-*(e nãoX-OmniRoute-*). O valor da assinatura ésha256=<hex>— verifique o prefixo completo.
Se createWebhook for chamado sem um segredo, o módulo da BD gera um
(whsec_<48 hex>) para que todos os webhooks sejam assinados por predefinição.
Verificação no recetor
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 sempre utilizando o corpo em bruto do pedido, antes de qualquer análise do JSON.
Política de Repetição e Falhas
deliverWebhook(url, payload, secret, maxRetries = 3):
- Tempo limite de 10 segundos por tentativa (
AbortController). - Uma resposta HTTP 2xx é considerada um sucesso.
- Uma resposta HTTP 3xx/4xx é considerada um estado final não repetível — registada como entregue
com
success = res.ok. - Respostas HTTP 5xx e erros de rede são repetidos com espera exponencial:
2^attempt * 1000 ms(1s, 2s, 4s). - Após
maxRetries, a entrega é registada como falhada. - Cada entrega atualiza
last_triggered_at,last_statuse repõe a zero ou incrementafailure_count. - O despachante chama
disableWebhooksWithHighFailures(10)após cada distribuição, pelo que qualquer webhook comfailure_count >= 10é automaticamente desativado.
Base de Dados
Tabela webhooks (migração 011_webhooks.sql):
| Coluna | Tipo | Notas |
|---|---|---|
id |
TEXT PK | UUID |
url |
TEXT | URL de destino |
events |
TEXT | Matriz JSON; predefinição ["*"] |
secret |
TEXT | Segredo HMAC (gerado automaticamente se não for fornecido) |
enabled |
INT | 0/1; predefinição 1 |
description |
TEXT | Etiqueta descritiva opcional |
created_at |
TEXT | datetime('now') |
last_triggered_at |
TEXT | Atualizado em cada tentativa de entrega |
last_status |
INT | Estado HTTP da última tentativa (0 = rede) |
failure_count |
INT | Reposto a 0 em caso de sucesso, +1 em caso de falha |
O histórico de entregas é mantido na tabela dedicada webhook_deliveries
(migração 069_webhook_deliveries.sql, escrito através de
src/lib/db/webhookDeliveries.ts::insertDelivery em cada tentativa), além
dos contadores agregados na linha de webhooks. Os metadados de tipo (Slack / Discord /
Telegram / transformadores de payload personalizados) foram adicionados por 070_webhooks_kind_metadata.sql.
API REST
Todos os endpoints exigem autenticação de gestão (requireManagementAuth).
| Endpoint | Método | Descrição |
|---|---|---|
/api/webhooks |
GET | Listar webhooks (segredos ocultados) |
/api/webhooks |
POST | Criar webhook |
/api/webhooks/[id] |
GET | Detalhes do webhook (segredo completo) |
/api/webhooks/[id] |
PUT | Atualizar campos |
/api/webhooks/[id] |
DELETE | Remover |
/api/webhooks/[id]/test |
POST | Acionar um test.ping (sem repetições) |
/api/webhooks/[id]/deliveries |
GET | Tentativas de entrega recentes de um webhook |
/api/webhooks/validate-url |
POST | Validação prévia do URL (proteção contra SSRF) |
GET /api/webhooks oculta o segredo no formato <first 10 chars>... para evitar a sua exposição
nas páginas de listagem. Utilize o GET de [id] quando precisar efetivamente do segredo.
Criar 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": "Slack alerts"
}'
Se secret for omitido, o servidor gera um segredo whsec_<hex> e devolve-o
na resposta.
Testar webhook
curl -X POST http://localhost:20128/api/webhooks/<id>/test \
-H "Cookie: auth_token=..."
Devolve { delivered, status, error }. Não são efetuadas novas tentativas — útil para
validar rapidamente se o recetor aceita o payload e a assinatura.
Painel
A página do painel em /dashboard/webhooks (consulte
src/app/(dashboard)/dashboard/webhooks/page.tsx) disponibiliza:
- Criação/edição de webhooks com um seletor de eventos
- Indicador de estado (ativo / inativo / com erro) baseado em
enabled,failure_countelast_status - Envio de teste com um clique
- Alternância manual entre ativado/desativado
Exemplos 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>"
}
}
As estruturas dos campos para eventos que não sejam test.ping são definidas pelos locais de chamada que os emitem; considere o objeto data compatível com versões futuras (adicione campos, não dependa da respetiva ausência).
Boas práticas
- Verifique a assinatura em cada envio relativamente ao corpo bruto — isto impede pedidos POST falsificados por alguém que adivinhe o URL do seu webhook.
- Responda com 2xx dentro de ~5 segundos — o dispatcher excede o tempo limite aos 10 s. Os
recetores lentos consumirão novas tentativas e aumentarão
failure_count. - Torne os handlers idempotentes — as novas tentativas e a semântica de entrega pelo menos uma vez significam que podem ocorrer duplicados.
- Subscreva apenas o necessário — liste apenas os eventos que realmente consome;
"*"aumentará os custos nos recetores que não controla. - Monitorize
failure_count— os endpoints são desativados automaticamente após 10 falhas consecutivas; reponha o estado ao chamarPUT /api/webhooks/[id]comenabled: truedepois de corrigir o recetor. - Altere os segredos periodicamente — envie um pedido
PUTcom um novosecret, implemente o novo valor no recetor e confirme através do endpoint de teste.
Consulte também
- API_REFERENCE.md — superfície completa da API de gestão
- RESILIENCE_GUIDE.md — semântica de circuit breaker / cooldown
subjacente às falhas de fornecedores apresentadas através de
request.failed - Código-fonte:
src/lib/webhookDispatcher.ts,src/lib/db/webhooks.ts