Um webhook é um callback HTTP automatizado: quando um evento ocorre, um sistema envia um POST com o payload para uma URL registrada por outro sistema. O termo — cunhado em 2007 como “user-defined HTTP callbacks” — nomeia a inversão que importa: em vez de o seu sistema perguntar repetidamente se algo mudou, o outro sistema avisa o seu no momento em que muda. É push construído com as peças mais simples da web: uma URL HTTPS, um POST, um corpo JSON e um 2xx de confirmação.
Principais pontos
| Pergunta | Resposta |
|---|---|
| O mecanismo | Registre uma URL → o evento dispara → o provedor envia o POST com o payload → você retorna 2xx |
| vs. uma API | APIs respondem quando perguntadas; webhooks falam quando algo acontece |
| A régua de segurança | HMAC sobre o corpo bruto, comparação em tempo constante, janela de timestamp |
| A verdade da entrega | At-least-once, sem ordem, com retries — deduplique e reconcilie |
| O mantra do receptor | Verifique · confirme rápido · processe async · deduplique por ID de evento |
A entrega, de ponta a ponta
CONFIG o receptor expõe https://api.example.com/hooks/payments
e a registra no provedor, escolhendo os eventos + um secret
EVENTO uma cobrança é aprovada no provedor
ENTREGA POST /hooks/payments
webhook-id: evt_8fk2 ← chave de deduplicação
webhook-timestamp: 1767024900 ← guarda anti-replay (dentro da assinatura)
webhook-signature: v1,d2Vio… ← HMAC-SHA256(secret, id.timestamp.body)
{ "type": "charge.succeeded", "orderId": "o-1187" }
ACK o receptor verifica a assinatura → 200 em segundos → o trabalho roda async
RETRY sem 2xx? backoff exponencial por horas/dias → duplicatas são NORMAIS
As duas direções do padrão em código — um trigger de dados como emissor, uma Cloud Function como receptor e o cliente apenas observando o resultado:
// JavaScript — Cloud Code (cloud/main.js): both directions of a webhook
// OUTGOING: any data change can notify an external system
Parse.Cloud.afterSave('Order', async (req) => {
if (req.object.get('status') !== 'paid') return;
await Parse.Cloud.httpRequest({
method: 'POST',
url: 'https://hooks.example.com/orders', // the receiver's registered URL
headers: { 'Content-Type': 'application/json' },
body: { event: 'order.paid', id: req.object.id },
});
});
// INCOMING: a Cloud Function is a ready-made webhook receiver
Parse.Cloud.define('paymentWebhook', async (req) => {
verifySignature(req.params, process.env.WEBHOOK_SECRET); // HMAC first
await markOrderPaid(req.params.orderId); // write fast, work async
return { received: true }; // 2xx before heavy processing
}); // Flutter / Dart — Back4app Flutter SDK
// The client's side of a webhook: watch its effect in real time
// (payment platform → Cloud Function receiver → database → Live Query → UI)
final orderQuery = QueryBuilder<ParseObject>(ParseObject('Order'))
..whereEqualTo('objectId', orderId);
final sub = await LiveQuery().client.subscribe(orderQuery);
sub.on(LiveQueryEvent.update, (order) {
if (order.get<String>('status') == 'paid') showReceipt();
});
// The webhook itself was handled server-side — clients just watch the data. // iOS / Swift — Back4app Swift SDK
// The client's side of a webhook: watch its effect in real time
// (payment platform → Cloud Function receiver → database → Live Query → UI)
let orderQuery = Order.query("objectId" == orderId)
let sub = try await orderQuery.subscribe()
sub.handleEvent { _, event in
if case .updated(let order) = event, order.status == "paid" {
showReceipt()
}
}
// The webhook itself was handled server-side — clients just watch the data. // Android / Kotlin — Back4app Android SDK
// The client's side of a webhook: watch its effect in real time
// (payment platform → Cloud Function receiver → database → Live Query → UI)
val orderQuery = ParseQuery.getQuery<ParseObject>("Order")
orderQuery.whereEqualTo("objectId", orderId)
val sub = ParseLiveQueryClient.Factory.getClient().subscribe(orderQuery)
sub.handleEvent(SubscriptionHandling.Event.UPDATE) { _, order ->
if (order.getString("status") == "paid") showReceipt()
}
// The webhook itself was handled server-side — clients just watch the data. Webhooks vs. APIs vs. polling
| Webhook | Chamada de API | Polling | |
|---|---|---|---|
| Iniciativa | O provedor empurra | O consumidor pergunta | O consumidor pergunta num timer |
| Timing | No evento | Sob demanda | No próximo intervalo |
| Tráfego desperdiçado | Nenhum em repouso | Nenhum | ~98% dos polls não acham nada |
| Direção | Notificação de mão única | Request/response de mão dupla | Mão dupla, repetida |
| Melhor em | ”Me avise quando" | "Faça isto / me dê aquilo” | Reconciliação, provedores sem webhooks |
O debate é em grande parte falso: integrações maduras usam os três — webhooks para saber das mudanças rápido, chamadas de API para buscar o estado autoritativo e agir, e um poll lento de reconciliação como a rede sob o trapézio.
O checklist do receptor
A lista que a documentação de todo provedor espalha e nenhum explicador reúne:
- Verifique o HMAC sobre o corpo bruto — antes do parse; JSON re-serializado quebra assinaturas.
- Compare em tempo constante — igualdade de strings vaza timing; use o comparador da sua biblioteca de criptografia.
- Aplique a janela de timestamp — rejeite entregas com mais de ~5 minutos; como o timestamp está dentro do conteúdo assinado, um atacante não consegue reenviar uma requisição antiga validamente assinada com um relógio novo.
- Retorne 2xx rápido — em segundos, antes do trabalho pesado; handlers lentos sofrem timeout e são reenviados até virarem tempestades de duplicatas.
- Processe de forma assíncrona — enfileire, confirme, depois trabalhe.
- Deduplique por ID de evento — com uma memória pelo menos tão longa quanto a janela de retry do provedor.
- Não confie no payload para ações críticas — trate o webhook como campainha; busque o estado atual na API do provedor antes de despachar mercadoria ou conceder acesso.
- Registre as entregas e alerte sobre falhas — silêncio é indistinguível de um endpoint quebrado.
Uma nota de desenvolvimento local que as páginas de definição pulam: localhost é inalcançável a partir da internet, então o desenvolvimento roda por uma ferramenta de túnel que empresta uma URL pública à sua máquina, mais uma ferramenta de captura para reproduzir payloads reais.
Semântica de entrega, com honestidade
A entrega de webhooks é at-least-once: o provedor tenta de novo até ser confirmado, então duplicatas são um recurso da confiabilidade, não um bug nela — entrega exactly-once sobre uma rede não confiável é formalmente impossível, e o equivalente prático é at-least-once mais o seu handler idempotente. A ordem não é garantida: retries e envios paralelos se intercalam, então updated pode chegar antes de created; aplique os eventos por ID e versão, ou rebusque o estado. E as janelas de retry acabam: um endpoint fora do ar por um fim de semana pode perder eventos permanentemente, e é por isso que integrações críticas que envolvem dinheiro combinam webhooks com reconciliação periódica — a mesma disciplina de at-least-once que os brokers formalizam, chegando por HTTP puro. A comparação generaliza: um webhook é push ponto a ponto para uma URL conhecida; pub/sub adiciona um broker, tópicos e fan-out; WebSockets e SSE servem clientes, não servidores. Webhooks são a resposta especificamente quando dois sistemas que não compartilham infraestrutura precisam saber dos eventos um do outro.
Construindo o lado do emissor
Emitir webhooks com confiabilidade é um pequeno sistema em si, e nenhuma página de ranking o esboça: uma fila por destino, para que um endpoint morto não bloqueie os demais; retries com backoff exponencial e jitter; um dead-letter store com ferramenta de reenvio para quando as tentativas acabam; assinatura HMAC com secrets por endpoint e rotação; inscrição por tipo de evento, para que os receptores optem só pelo que querem; e logs de entrega que seus clientes possam ler, porque “vocês enviaram?” é a primeira pergunta do suporte. Um item de segurança exclusivo do emissor: receptores registram URLs arbitrárias, então valide-as contra faixas de endereço internas — um atacante registrando http://10.0.0.5/admin como seu “endpoint de webhook” é server-side request forgery vestido de recurso de integração.
Casos de uso comuns
- Ciclo de vida de pagamentos — cobranças, reembolsos e mudanças de assinatura anunciadas ao seu backend conforme liquidam.
- Gatilhos de CI/CD — o clássico git push que dispara um build.
- Automação entre apps — ferramentas de formulário, plataformas de chat e CRMs encadeados pelos eventos uns dos outros.
- Notificações operacionais — alertas de monitoramento e atualizações de entrega caindo nos canais do time.
- Sincronização de dados — manter um espelho local de um sistema parceiro atualizado sem fazer polling da API inteira.
Você deveria usar um webhook? Matriz de decisão
| Situação | Escolha |
|---|---|
| O sistema de outra empresa precisa notificar o seu | Webhooks — o padrão de interoperabilidade |
| Seus serviços, sua infraestrutura | Pub/sub — com broker, buffer e fan-out |
| Navegadores/apps precisam de atualizações ao vivo | WebSockets / live queries |
| O provedor não oferece webhooks | Polling, com educação |
| Dinheiro ou acesso depende do evento | Webhook + verificar-e-rebuscar + reconciliação |
| Você é a plataforma que emite os eventos | Construa o lado do emissor acima — ou não prometa confiabilidade |
Limitações e trade-offs
- A entrega é best-effort além da janela de retry. Webhooks notificam; não garantem. Polls de reconciliação seguram tudo que não pode ser perdido.
- O receptor herda o dever de uptime. A disponibilidade do seu endpoint agora condiciona os eventos de outra pessoa — deploys, cold starts e timeouts viram bugs de integração.
- A segurança é opt-in. Um endpoint de webhook sem verificação é uma API de escrita sem autenticação; o checklist de HMAC é a diferença entre integração e injeção.
- O debug atravessa duas empresas. Logs de entrega dos dois lados e ferramenta de replay são o que transforma “não chegou” de um impasse em um diff.
- Payloads derivam. Provedores versionam os esquemas dos eventos; consumidores presos a formatos exatos quebram em silêncio — faça parse defensivo e ignore campos desconhecidos.
Webhooks no Back4app
O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. As duas metades do padrão estão a um construto de Cloud Code de distância, como as abas de código mostram. Saída: um trigger afterSave observando os seus dados chama Parse.Cloud.httpRequest para qualquer URL registrada — seu app vira um provedor de webhooks escrevendo a função, e as disciplinas do lado do emissor (retry em caso de falha, log das entregas) vivem no mesmo arquivo. Entrada: uma Cloud Function exposta via HTTPS é um receptor pronto — verifique o HMAC contra um secret na configuração do servidor, grave o resultado no banco de dados, retorne rápido — e a atualização então se espalha para toda tela aberta via Live Queries, fechando o ciclo que vai do evento em uma plataforma de pagamento até o recibo do usuário sem um servidor para operar em nenhuma das pontas.
Perguntas frequentes
O que é um webhook em termos simples?
Uma mensagem HTTP automática que um sistema envia a outro no momento em que algo acontece — uma campainha em vez de checar a porta toda hora. Você dá uma URL ao provedor; quando o evento dispara, ele envia um POST com os dados do evento para lá. O termo é de 2007: "user-defined HTTP callbacks".
Qual a diferença entre webhook e API?
Direção e iniciativa. Uma API é orientada a requisições — o cliente pergunta, o servidor responde. Um webhook é orientado a eventos — o servidor empurra quando algo acontece, sem ser perguntado. Um webhook é, na prática, um padrão construído sobre APIs, e a maioria das integrações reais usa os dois: webhooks para saber das mudanças, chamadas de API para agir sobre elas.
Qual a diferença entre webhooks e polling?
Polling pergunta num timer e quase sempre ouve "nada ainda" — uma medição em uma grande plataforma de automação ficou famosa ao constatar que cerca de 98% dos polls não retornam dados novos. Webhooks invertem isso: zero requisições em repouso, entrega imediata na mudança. O polling sobrevive como rede de reconciliação sob os webhooks, não como rival.
Como recebo um webhook?
Exponha um endpoint HTTPS que aceite POST, registre a URL no provedor e selecione os eventos que quer. No handler: verifique a assinatura, retorne um 2xx em segundos e faça o processamento de verdade de forma assíncrona. Teste com uma ferramenta de captura antes de ligar a lógica de produção.
Webhooks são seguros?
Não por padrão — o endpoint é uma URL pública em que qualquer um pode fazer POST. A defesa padrão é a assinatura HMAC: o provedor assina cada payload com um secret compartilhado, e você recomputa sobre o corpo bruto e compara em tempo constante, rejeitando timestamps velhos para bloquear replays. HTTPS sempre; allowlists de IP como enfeite.
O que acontece se meu endpoint estiver fora do ar?
Bons provedores tentam de novo com backoff exponencial, muitas vezes por horas ou dias — por isso a entrega é at-least-once e duplicatas são normais. Eventos ainda podem se perder além da janela de retry, então integrações críticas reconciliam com polls periódicos na API em vez de confiar só nos webhooks.
Como lido com entregas duplicadas de webhooks?
Deduplique pelo ID único do evento: registre os IDs processados e pule as repetições, mantendo o registro por pelo menos o tamanho da janela de retry do provedor. Entrega at-least-once mais um handler idempotente equivale, na prática, a processamento exactly-once — a metade do contrato de confiabilidade que cabe ao receptor.
Qual a diferença entre webhook e WebSocket?
Um webhook é uma notificação HTTP stateless, de mão única, de servidor para servidor; um WebSocket é uma conexão persistente e bidirecional, feita para tempo real voltado ao cliente, como chat e dashboards ao vivo. Servidor avisa servidor: webhook. Servidor transmite para interfaces de usuário: WebSocket.