Documentação · Webhooks

Webhooks: estado real e desenho técnico

Nenhum webhook do GenOpt dispara hoje. Esta página documenta o que a API responde agora (um 501 honesto) e o desenho planejado para o Sprint 4E — rotulado como desenho, não como contrato.

Estado: planejado — Sprint 4E

Não há evento sendo emitido, cadastro de URL nem segredo para gerar. Tudo abaixo da seção "O que a API responde hoje" é desenho sujeito a mudança até a primeira emissão real. Contexto e motivação em /webhooks; previsão pública no /roadmap.

O que a API responde hoje

A rota /v1/webhooks existe — e responde 501 Not Implemented com o status real, em GET e POST. É deliberado: um 404 se confunde com "digitei o path errado"; um 501 diz "existe no plano, ainda não foi implementada". A mesma rota consta no spec OpenAPI (/v1/openapi.json) com o 501 como única resposta documentada — o spec nunca descreve comportamento que não existe.

hoje, em produção
$ curl -si -X POST https://api.genopt.ai/v1/webhooks
HTTP/1.1 501 Not Implemented
content-type: application/json; charset=utf-8

{"status":"planned","roadmap":"Sprint 4E"}

Desenho: entrega assinada com HMAC-SHA256

Cada entrega será um POST JSON na URL cadastrada, assinada com HMAC-SHA256 sobre o corpo bruto mais um timestamp — o padrão de Stripe e GitHub, escolhido porque seus desenvolvedores provavelmente já verificaram esse esquema uma vez na vida. O segredo de assinatura será exibido uma única vez no cadastro e armazenado como hash do nosso lado — o mesmo tratamento que já damos às API keys e à evidência.

headers planejados (desenho, não contrato)
POST https://sua-url.exemplo.com/genopt
Content-Type: application/json
X-GenOpt-Event: measurement.completed
X-GenOpt-Timestamp: 1770854400
X-GenOpt-Signature: sha256=3f2a...c91b
verificação da assinatura (desenho, não contrato)
// Verificação no seu servidor (Node, desenho):
import { createHmac, timingSafeEqual } from 'node:crypto'

const esperado = createHmac('sha256', process.env.GENOPT_WEBHOOK_SECRET)
  .update(`${timestamp}.${corpoBruto}`)
  .digest('hex')

// compare com timingSafeEqual e rejeite timestamps
// com mais de 5 minutos (anti-replay)

Anti-replay: a assinatura cobre o timestamp, e a recomendação será rejeitar entregas com timestamp mais velho que 5 minutos. Falha de entrega: retentativa com backoff exponencial. Os nomes finais dos eventos saem junto com a implementação — a primeira leva planejada cobre medição concluída, confabulação nova detectada e mudança de classificação de citação. Publicar nome de evento antes do código é convidar integração quebrada, então os exemplos desta página usam nomes ilustrativos.

Enquanto isso

Consumo programático que existe hoje: a API v1 (pull, não push), o servidor MCP e os SDKs. O estado de todas as integrações está em /docs/integrations. Se a sua integração depende de webhooks, escreva para contato@genopt.ai contando o caso de uso — a ordem do roadmap é decidida com isso.