# Catálogo de eventos de webhook

> Conheça todos os eventos que o GS Engage envia por webhook, o formato de cada entrega e as boas práticas para recebê-los com segurança.

- URL canônica: https://docs.growthstation.app/docs/api/webhooks
- Idioma: pt-BR
- Última atualização: 2026-09-20T08:21:20.451Z



<PageHero emoji="📡" title="Catálogo de eventos de webhook" description="Deixe o GS Engage avisar o seu sistema no exato momento em que algo importante acontece — uma venda ganha, uma ligação transcrita, uma atividade concluída." gradient="brand" />

🎯 O que é um webhook (e por que ele te poupa trabalho) [#-o-que-é-um-webhook-e-por-que-ele-te-poupa-trabalho]

Um **webhook** é um aviso automático. Em vez de o seu sistema ficar perguntando à API "e aí, mudou alguma coisa?" a cada minuto, é o GS Engage que **liga para você** assim que um evento acontece. Ele faz isso enviando uma requisição `POST` para uma URL sua (o seu "endereço de recebimento").

Na prática: quando um vendedor marca uma prospecção como <TextHighlight>Ganha</TextHighlight>, o GS Engage dispara na hora um aviso para o seu CRM, planilha ou automação — sem ninguém precisar copiar e colar nada.

<Callout type="tip" title="Em uma frase">
  Você diz ao GS Engage "me avise quando X acontecer", e ele entrega os dados na sua URL toda vez que X acontece.
</Callout>

📖 Os eventos que você pode escutar [#-os-eventos-que-você-pode-escutar]

Cada evento tem um nome técnico (o que você declara ao criar o webhook, no campo `events`) e um recurso principal que vem dentro do campo `data` da entrega. A tabela abaixo é o catálogo completo.

| Evento (`event`)       | O que aconteceu no negócio                                             | O que vem em `data`                        |
| ---------------------- | ---------------------------------------------------------------------- | ------------------------------------------ |
| `prospection.started`  | Uma prospecção começou para um lead.                                   | A **prospecção** (com o lead e a cadência) |
| `prospection.won`      | Uma prospecção foi marcada como **Ganha** (`WON`).                     | A **prospecção** ganha                     |
| `prospection.lost`     | Uma prospecção foi marcada como **Perdida** (`LOST`).                  | A **prospecção** perdida (com o motivo)    |
| `activity.finished`    | Uma atividade da cadência foi concluída (ligar, e-mail, mensagem…).    | A **atividade** finalizada                 |
| `call.started`         | Uma ligação foi iniciada.                                              | A **ligação**                              |
| `call.finished`        | Uma ligação foi encerrada.                                             | A **ligação** encerrada                    |
| `call.transcribed`     | A transcrição de uma ligação ficou pronta.                             | A **ligação** com a transcrição            |
| `prospection.handover` | A prospecção trocou de responsável (passou de um vendedor para outro). | A **prospecção** com o novo responsável    |

<Callout type="info" title="Sobre o prospection.handover">
  O sistema **emite** o `prospection.handover` (troca de responsável) normalmente — o `data` é a **prospecção** com o novo responsável. Mas há uma pegadinha: o endpoint público de criar webhook (`POST /api/v1/webhooks`) **ainda não aceita** esse evento na lista `events` — hoje você só consegue assiná-lo pela **tela de configurações da plataforma**. Se precisar dele via integração, assine pela plataforma até o endpoint público passar a aceitá-lo.
</Callout>

<Callout type="tip" title="Escute só o que você usa">
  Você não precisa assinar todos os eventos. Ao criar o webhook, declare em `events` apenas os que interessam ao seu fluxo — por exemplo, só `prospection.won` para atualizar o seu CRM quando fecha uma venda.
</Callout>

📦 Como cada entrega chega: o envelope [#-como-cada-entrega-chega-o-envelope]

Todo evento chega no mesmo formato — um "envelope" com campos fixos. O recurso que mudou (a prospecção, a atividade ou a ligação) vai sempre dentro de `data`; os outros campos descrevem a própria entrega.

<FieldInfoGroup>
  <FieldInfo title="id">
    Identificador único **desta entrega**. Use-o para garantir **idempotência** (não processar o mesmo aviso duas vezes). Veja as boas práticas abaixo.
  </FieldInfo>

  <FieldInfo title="test">
    `true` quando a entrega é um disparo de teste; `false` quando é um evento real. Útil para separar tráfego de validação do tráfego de produção.
  </FieldInfo>

  <FieldInfo title="event">
    O nome do evento — um dos valores da tabela acima (ex.: `prospection.won`). É por ele que você decide o que fazer.
  </FieldInfo>

  <FieldInfo title="data">
    O recurso que disparou o evento. O conteúdo depende do `event`: uma prospecção, uma atividade ou uma ligação.
  </FieldInfo>

  <FieldInfo title="retries">
    Quantas vezes o GS Engage **reenviou automaticamente** esta entrega até agora (por não ter recebido um `2xx`). Começa em `0`.
  </FieldInfo>

  <FieldInfo title="manualRetries">
    Quantas vezes a entrega foi **reenviada manualmente** (por alguém, dentro da plataforma).
  </FieldInfo>

  <FieldInfo title="createdAt">
    Data e hora em que o evento foi gerado. Ajuda a ordenar e a descartar avisos muito antigos.
  </FieldInfo>
</FieldInfoGroup>

Um exemplo de entrega do evento `prospection.won`, do jeitinho que chega na sua URL:

```json
{
  "id": "9f3c8b2a-...",
  "test": false,
  "event": "prospection.won",
  "data": {
    "id": "prospection-id",
    "status": "WON",
    "lead": { "id": "lead-id", "fullName": "Marina Costa" },
    "routine": { "id": "routine-id", "name": "Inbound - Site" }
  },
  "retries": 0,
  "manualRetries": 0,
  "createdAt": "2026-07-17T14:32:10.000Z"
}
```

O que isso significa para o negócio: a prospecção da Marina foi fechada como **Ganha**. É o gatilho para, por exemplo, criar uma oportunidade no seu CRM ou disparar o onboarding do cliente.

✅ Boas práticas para receber sem dor de cabeça [#-boas-práticas-para-receber-sem-dor-de-cabeça]

Receber webhook é fácil; receber bem exige quatro cuidados. Eles evitam avisos perdidos, dados duplicados e fraudes.

<Steps>
  <Step num={1} title="Responda 2xx rápido — e processe depois">
    Assim que a entrega chegar, responda com um status **2xx** (por exemplo, `200 OK`) o mais rápido possível. Não espere terminar o processamento pesado (gravar no banco, chamar outro sistema) para responder. O GS Engage interpreta uma resposta lenta ou fora da faixa 2xx como falha e vai **reenviar**. A receita: enfileire o trabalho e responda 2xx na hora.
  </Step>

  <Step num={2} title="Garanta idempotência usando o id">
    A mesma entrega pode chegar **mais de uma vez** (por reenvio automático ou manual). Guarde o `id` de cada entrega processada e, se ele já apareceu, **ignore**. Assim, um reenvio nunca vira uma venda contada duas vezes no seu CRM.
  </Step>

  <Step num={3} title="Trate os reenvios com naturalidade">
    Se a sua URL não responde 2xx, o GS Engage tenta de novo — os campos `retries` e `manualRetries` contam essas tentativas. Isso é uma rede de segurança: uma instabilidade momentânea no seu servidor não faz você perder o aviso. Combine com a idempotência do passo anterior e os reenvios se tornam inofensivos.
  </Step>

  <Step num={4} title="Valide a assinatura antes de confiar">
    Cada entrega é **assinada** com HMAC SHA-256 (um código de autenticidade calculado a partir do corpo da mensagem e do seu `secret`). Recalcule a assinatura do seu lado e compare com a que veio no cabeçalho: se baterem, o aviso é legítimo. Se não confere, **descarte** — pode ser alguém tentando se passar pelo GS Engage. O passo a passo está no guia de [validação de assinatura](/docs/api/guias/validar-assinatura-webhook).
  </Step>
</Steps>

<DoDont>
  <DoDontItem type="do">
    Responder 2xx imediatamente e processar o evento em segundo plano.
  </DoDontItem>

  <DoDontItem type="do">
    Deduplicar pelo campo 

    `id`

     antes de agir sobre o evento.
  </DoDontItem>

  <DoDontItem type="do">
    Recalcular o HMAC SHA-256 e comparar com o cabeçalho de assinatura.
  </DoDontItem>

  <DoDontItem type="dont">
    Não faça trabalho pesado antes de responder — isso provoca reenvios.
  </DoDontItem>

  <DoDontItem type="dont">
    Não confie no corpo sem validar a assinatura.
  </DoDontItem>

  <DoDontItem type="dont">
    Não processe a mesma entrega duas vezes ignorando o 

    `id`

    .
  </DoDontItem>
</DoDont>

<Mermaid
  chart={`graph TD
A["Evento acontece no GS Engage"] --> B["POST assinado para a sua URL"]
B --> C{"Assinatura confere?"}
C -->|Nao| D["Descarta (nao e legitimo)"]
C -->|Sim| E{"Ja processei este id?"}
E -->|Sim| F["Ignora (duplicado)"]
E -->|Nao| G["Responde 2xx e enfileira o trabalho"]
G --> H["Processa em segundo plano"]`}
/>

🔧 Como criar, listar e remover webhooks [#-como-criar-listar-e-remover-webhooks]

Tudo acontece sob o caminho `/api/v1/webhooks`. Lembre que a `apiKey` vai como parâmetro na URL (`?apiKey=SUA_CHAVE`).

<Tabs items={['Criar', 'Listar', 'Remover']}>
  <Tab value="Criar">
    Para criar um webhook, envie um `name` (um apelido para você se organizar), a `url` que vai receber as entregas e a lista `events` com os eventos que você quer escutar.

    ```bash
    curl -X POST \
      "https://api.gsengage.com/api/v1/webhooks?apiKey=SUA_CHAVE" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Avisar CRM sobre vendas",
        "url": "https://seu-sistema.com.br/webhooks/gsengage",
        "events": ["prospection.won", "prospection.lost"]
      }'
    ```

    A resposta traz o webhook criado — **incluindo o `secret`**, que aparece **só nesta resposta**. Guarde-o na hora (veja o alerta abaixo).
  </Tab>

  <Tab value="Listar">
    Para ver os webhooks já configurados no projeto:

    ```bash
    curl "https://api.gsengage.com/api/v1/webhooks?apiKey=SUA_CHAVE"
    ```

    Atenção: este endpoint devolve os itens em `data`, mas **sem** `meta` — `{ "data": [ ... ] }` — pois retorna todos os webhooks, sem paginação. O `secret` **não** volta aqui — ele só é mostrado uma vez, na criação.
  </Tab>

  <Tab value="Remover">
    Para desativar um webhook, remova-o pelo seu `webhookId`:

    ```bash
    curl -X DELETE \
      "https://api.gsengage.com/api/v1/webhooks/WEBHOOK_ID?apiKey=SUA_CHAVE"
    ```

    Uma resposta **HTTP 204 (No Content)** confirma que o webhook foi removido e não vai mais receber entregas.
  </Tab>
</Tabs>

<Callout type="danger" title="O secret aparece uma única vez — copie na hora">
  Ao criar o webhook (`POST /api/v1/webhooks`), o campo `secret` é devolvido **apenas nessa resposta de criação**. Ele **não** aparece de novo ao listar (`GET /api/v1/webhooks`) nem em lugar nenhum depois. Guarde-o na hora, em local seguro (variável de ambiente ou cofre de segredos) — é ele que você usa para validar a assinatura HMAC SHA-256 de cada entrega. Perdeu? Crie um webhook novo para gerar outro `secret`.
</Callout>

<Callout type="warning" title="Toda chamada é real (não há sandbox)">
  O GS Engage não tem ambiente de teste separado. Criar ou remover um webhook afeta o projeto de produção na hora. Confira a `url` e os `events` antes de disparar.
</Callout>

🤖 Prefere não programar? [#-prefere-não-programar]

Você não precisa escrever um servidor para receber webhooks. Ferramentas <TextHighlight>Zapier</TextHighlight>, Make e n8n recebem essas entregas por você e disparam automações — o GS Engage inclusive expõe gatilhos nativos de webhook no Zapier. É o caminho mais rápido para, por exemplo, jogar uma venda ganha direto numa planilha ou no seu CRM.

❓ Perguntas frequentes [#-perguntas-frequentes]

<FAQ>
  <FAQItem question="Preciso assinar todos os eventos?">
    Não. Declare em `events`, na criação, apenas os que o seu fluxo usa. Você pode escutar um único evento (como `prospection.won`) ou vários de uma vez.
  </FAQItem>

  <FAQItem question="Perdi o secret. E agora?">
    O `secret` só é mostrado na resposta de criação e não pode ser recuperado depois. Crie um webhook novo (que gera outro `secret`) e remova o antigo com `DELETE /api/v1/webhooks/{webhookId}`.
  </FAQItem>

  <FAQItem question="Por que recebi a mesma entrega duas vezes?">
    Reenvios são normais: se a sua URL não respondeu 2xx a tempo, o GS Engage tenta de novo (os campos `retries` e `manualRetries` mostram quantas vezes). Por isso deduplique pelo campo `id` — assim um reenvio nunca é processado em dobro.
  </FAQItem>

  <FAQItem question="Como sei se uma entrega é de teste?">
    Pelo campo `test`: `true` indica um disparo de teste e `false`, um evento real. Você pode usar isso para não acionar automações de produção durante a validação.
  </FAQItem>

  <FAQItem question="A assinatura mudou de algoritmo?">
    Sim. A validação usa **HMAC SHA-256** (a versão anterior, em SHA-1, foi descontinuada). Se você tinha uma validação antiga em SHA-1, atualize para SHA-256.
  </FAQItem>
</FAQ>

Artigos Relacionados [#artigos-relacionados]

<RelatedArticles>
  <RelatedArticle href="/docs/api/guias/validar-assinatura-webhook" title="Validar a assinatura de um webhook" description="Recalcule o HMAC SHA-256 com o seu secret e confirme que a entrega é legítima." />

  <RelatedArticle href="/docs/api/no-code/zapier" title="Receber webhooks no Zapier" description="Capture eventos do GS Engage sem escrever código." />

  <RelatedArticle href="/docs/api/comece-aqui/escolha-seu-caminho" title="Comece aqui" description="Autenticação, primeiros passos e como usar a API com segurança." />

  <RelatedArticle href="/docs/api" title="Visão geral da API" description="O que dá para automatizar com o GS Engage, com e sem código." />
</RelatedArticles>
