Pular para o conteúdo principal

Webhooks

Webhooks permitem reagir a eventos do Workfuse em tempo real, sem polling. São um recurso da plataforma: qualquer módulo pode emitir eventos, e você assina os que interessam. Quando um evento ocorre, o Workfuse faz um POST assinado para a URL que você registrou.

O catálogo de eventos cresce por módulo — veja, na doc de cada módulo, os eventos que ele emite. O mecanismo abaixo (configuração, envelope, assinatura, entrega) é o mesmo para todos.

Configurar

Webhooks são gerenciados no painel, em Configurações → Webhooks (perfil de administrador). Ao criar, você informa a URL de recebimento e os eventos que quer assinar (ou nenhum = todos). O secret de assinatura é exibido uma única vez na criação — guarde-o para validar as entregas.

Envelope do payload

Todo evento, de qualquer módulo, chega no mesmo envelope. O campo event identifica o tipo e data carrega o conteúdo específico daquele evento:

{
"id": "evt_...",
"event": "<modulo>.<acao>",
"data": { "...": "..." }
}

Verificar a assinatura (HMAC)

Cada entrega vem com o header X-Workfuse-Signature no formato sha256=<hex>, um HMAC-SHA256 do corpo cru usando o seu secret. Valide antes de confiar no payload:

import crypto from "node:crypto";

function isValid(rawBody: string, signatureHeader: string, secret: string): boolean {
if (!signatureHeader) return false;
const expected = `sha256=${crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex")}`;
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader);
// timingSafeEqual exige buffers do mesmo tamanho.
return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Dois detalhes que costumam quebrar a verificação:

  • Inclua o prefixo sha256= ao comparar (ou remova dos dois lados).
  • Calcule o HMAC sobre o corpo exatamente como recebido (os bytes crus) — não re-serialize o JSON, senão a assinatura não bate.

Código executável (Node, sem dependências): nodejs-webhook — receiver que valida a assinatura HMAC antes de processar o payload.

Entrega e retry

A entrega é best-effort e independente do processamento que originou o evento (uma falha de entrega não desfaz nem afeta o que já aconteceu na plataforma). Responda 2xx rapidamente e processe de forma assíncrona do seu lado.

Exemplo: eventos do módulo Correção

A título de exemplo, o módulo Correção de Redação emite:

EventoQuando dispara
essay.correctedA correção concluiu com sucesso.
essay.failedA correção falhou.

Entrega correspondente:

{
"id": "evt_...",
"event": "essay.corrected",
"data": { "essayId": "clz...", "...": "..." }
}

Aqui você usaria o data.essayId para consultar a redação completa via GET /essays/:id. Outros módulos seguem o mesmo formato, mudando apenas event e data.