Webhooks
Assine eventos, valide a assinatura HMAC e gerencie tudo por chave — sem precisar de dono logado.
Assine eventos e receba um POST a cada ocorrência. CRUD completo por chave (GET, POST, PATCH, DELETE /webhooks), escopo webhooks.manage — nenhum dono logado precisa intervir.
curl -X POST https://api.staging.growthaisystem.com/api/v1/webhooks \
-H "Authorization: Bearer gos_SEU_TOKEN_AQUI" \
-H "Content-Type: application/json" \
-d '{"url":"https://seu-sistema.com/hooks","events":["contact.created"]}'Eventos disponíveis
contact.created/contact.updated— precisa decontacts.read.opportunity.created/opportunity.stage_changed/opportunity.won/opportunity.lost— precisa deopportunities.read.meeting.booked/meeting.rescheduled/meeting.canceled/meeting.outcome— precisa decalendars.read.
Assinar um evento exige o escopo de leitura correspondente listado acima, além de webhooks.manage — se esse escopo for revogado depois, a assinatura desativa sozinha na próxima entrega (disabledReason: "scope_revoked").
Validando a assinatura
Cada entrega chega com o header X-Gos-Signature, no formato t=<timestamp>,v1=<assinatura>. A assinatura é um HMAC-SHA256 do texto {timestamp}.{corpo} (timestamp e corpo colados com um ponto), calculado com o secret devolvido (uma única vez) na criação da assinatura — mesmo modelo do Stripe, se você já validou webhook deles antes.
t, assinaturaRecebida = extrair de "t=...,v1=..." esperada = hmac_sha256(secret, t + "." + corpoCru) se não bater (comparação em tempo constante) → rejeitar se abs(agora - t) > alguns minutos → rejeitar (proteção contra replay)
Use o corpo cru da requisição no cálculo (antes de qualquer parse de JSON) — reformatar o JSON muda os bytes e quebra a conta.
Reentrega e desativação automática
Falhou a entrega (timeout, seu sistema fora do ar, resposta não-2xx)? Novas tentativas em 1min, 5min, 30min, 2h e 12h — 6 tentativas no total, depois a entrega vira dead. 3 dias seguidos falhando desativa a assinatura inteira sozinha (disabledReason: "circuit_breaker") — reative manualmente depois de corrigir o seu lado. Redirecionamento (3xx) conta como falha: a entrega não segue redirect.