Webhooks do GitHub: configuração, eventos e verificação de assinatura | We.Inc
Crie um webhook do GitHub, escolha os eventos, verifique o header X-Hub-Signature-256 com código que funciona e reenvie entregas que falharam. Inclui um verificador de assinatura no navegador.
Um webhook do GitHub é uma mensagem que o GitHub envia para a URL do seu servidor sempre que algo acontece num repositório, como um push, uma nova issue ou um release. Você o adiciona em Settings, Webhooks do repositório. Defina um secret para poder verificar o header X-Hub-Signature-256 e rejeitar entregas falsas.
Fatos sobre webhooks do GitHub que vale conhecer (docs.github.com, outubro de 2026)
Item
O que o GitHub documenta
Header de assinatura
X-Hub-Signature-256, o valor começa com sha256=
Método de assinatura
Digest HMAC em hex com SHA-256, usando o seu secret como chave
Tempo de resposta
Mais de 10 segundos é registrado como entrega com falha
Novas tentativas automáticas
Nenhuma; entregas com falha não são reenviadas automaticamente
Reenvio manual
Entregas dos últimos 3 dias
Limite de tamanho do payload
25 MB; payloads maiores não são entregues
Os webhooks permitem que o GitHub avise o seu site ou app sobre mudanças no momento em que acontecem, para você reconstruir um site a cada push, publicar uma mensagem quando uma issue é aberta ou atualizar um changelog a cada release. A parte importante que a maioria dos guias rápidos pula é verificar se uma entrega veio mesmo do GitHub. O verificador abaixo calcula a mesma assinatura que o GitHub envia, direto no seu navegador.
Abra o repositório, clique em Settings, depois em Webhooks na barra lateral esquerda e então em Add webhook.
Digite o seu endpoint em Payload URL e escolha application/json como content type, para que o corpo chegue como JSON puro.
Informe uma string aleatória longa em Secret e guarde o mesmo valor nas variáveis de ambiente do seu servidor.
Em Which events would you like to trigger this webhook, escolha só o evento push ou selecione eventos individuais, marque Active e salve.
O GitHub envia um evento ping na hora; confira em Recent Deliveries para ter certeza de que o seu servidor respondeu.
Responda rápido. Devolva um status 2xx em instantes e faça o trabalho demorado depois, num job em segundo plano, porque uma resposta mais lenta que 10 segundos conta como falha.
Calcule a assinatura sobre os bytes brutos do corpo, antes de qualquer parsing de JSON. Fazer o parsing e serializar de novo muda os bytes e a verificação falha.
Compare assinaturas com uma função de tempo constante, como crypto.timingSafeEqual, nunca com uma comparação == simples.
Use o X-GitHub-Delivery, um ID único por entrega, para ignorar duplicatas quando reenviar manualmente.
Assine apenas os eventos que você trata. Menos eventos significa menos requisições ao seu servidor e menos coisa para proteger.
Perguntas frequentes
O GitHub tenta de novo webhooks que falharam?
Não. A documentação do GitHub diz que ele não reenvia automaticamente entregas com falha. Você pode reenviar uma manualmente em Recent Deliveries, para entregas feitas nos últimos 3 dias.
O que é o header X-Hub-Signature-256?
Ele é enviado quando o webhook tem um secret. O GitHub pega o corpo da requisição, calcula um HMAC com SHA-256 usando o seu secret como chave e envia o resultado em hex com o prefixo sha256=. O seu servidor repete o cálculo e compara.
Quais eventos um webhook pode receber?
Muitos, incluindo push, pull_request, issues, release e workflow_run. O header X-GitHub-Event indica o evento que disparou cada entrega, e o ping chega quando você cria o hook.
Posso testar um webhook sem um servidor público?
O seu endpoint precisa ser acessível pela internet, porque o GitHub envia requisições para ele. Para trabalho local, rode uma ferramenta de túnel que dê à sua máquina uma URL pública temporária e use essa URL como Payload URL.
Webhook ou polling na API?
Um webhook envia cada mudança para você assim que ela acontece; polling é consultar a API em intervalos. Webhooks usam menos requisições e chegam antes, o que importa porque as chamadas à API contam para os limites de taxa.
O que chega com cada entrega
Toda entrega é um POST com headers que a descrevem: X-GitHub-Event indica o evento, X-GitHub-Delivery é um ID único, X-GitHub-Hook-ID identifica o webhook e o User-Agent sempre começa com GitHub-Hookshot/.
O corpo é o payload do evento. Num push, ele lista os commits e a referência da branch, para que um script de deploy possa ignorar pushes em branches diferentes da que ele publica.
Conferir o seu código de verificação com os valores de teste do GitHub
O GitHub publica uma entrada conhecida para você provar que o seu código está certo antes de ir para produção: o secret It's a Secret to Everybody e o payload Hello, World! devem gerar uma assinatura que começa com 757107ea.
O verificador desta página vem preenchido com esses valores. Se o seu servidor calcular o mesmo resultado a partir deles, o seu código de verificação está correto.
Esta rota do Express lê o corpo bruto, calcula o HMAC com o seu secret e o compara em tempo constante antes de confiar no payload.
O express.raw mantém exatamente os bytes que o GitHub assinou. O secret vem de uma variável de ambiente, nunca do código.
Headers da entrega
Headers em toda entrega de webhook do GitHub
Header
O que contém
X-GitHub-Event
O nome do evento, como push ou issues
X-GitHub-Delivery
Um ID único (GUID) para esta entrega
X-GitHub-Hook-ID
O ID do webhook que a enviou
X-Hub-Signature-256
sha256= mais o HMAC do corpo, só quando há um secret definido
User-Agent
Sempre começa com GitHub-Hookshot/
Verificador de assinatura de webhook
Digite um secret e um corpo de requisição bruto para ver o valor de X-Hub-Signature-256 que o GitHub enviaria. Roda no seu navegador com a Web Crypto API; nada é enviado.
Secret do webhook
Corpo bruto da requisição
Header de assinatura que você recebeu (opcional)
sha256=...
Assinatura calculada
Confere: a assinatura desta entrega é válida para esse secret e esse corpo.
Não confere: o secret, os bytes do corpo ou o header são diferentes.
Carregar os valores de teste do GitHub
Com os valores de teste do GitHub, o resultado deve ser igual a: