# Webhooks Em vez de perguntar à API de tempos em tempos se algo mudou, você pode deixar o Festero **avisar**. Cada vez que um orçamento é aceito, uma parcela é paga ou uma visita é marcada, o Festero faz uma requisição `POST` para o endereço HTTPS do seu sistema, com um resumo do que aconteceu. O aviso é enxuto de propósito: traz o tipo do evento, identificadores, situação e datas. O detalhe você busca na API, com a sua credencial, pelo `resource_url` que vem no próprio aviso. Assim o webhook nunca vaza mais do que a API permite ler. ## Visão geral 1. Você cadastra o endereço e escolhe os eventos na tela **API do Festero**. 2. O Festero envia um teste (`ping`). Quando o seu endereço responde 2xx, ele fica **Ativo**. 3. A partir daí, cada evento escolhido vira uma requisição assinada para o seu endereço. 4. Você verifica a assinatura, responde 2xx rápido e processa depois. 5. Se o seu endereço falhar, o Festero tenta de novo, com intervalos crescentes. Quais eventos existem e o que cada um traz: [Eventos de webhook](https://developers.festero.com.br/webhooks/eventos.md). Como conferir a assinatura, com código em Node, Python e C#: [Verificar a assinatura](https://developers.festero.com.br/webhooks/assinatura.md). ## Cadastrar o endereço Webhooks fazem parte dos planos Premium e Enterprise. Quem tem a permissão **Gerenciar a API pública e as chaves MCP** cadastra o endereço na seção **Webhook** da tela **API do Festero** (item do menu lateral), em **Cadastrar endereço**. | Campo | Regra | |---|---| | Endereço (URL) | Começa com `https://`, usa a porta padrão 443, sem usuário e senha, sem `#` (fragmento) e com um **nome de domínio público** (não um número de IP, nem `localhost`, `.local` ou `.internal`). Até 2.048 caracteres. | | Eventos | Pelo menos um. Você só vê para assinar os eventos dos dados que você mesmo enxerga no Festero. | Outras regras: - **Um endereço por empresa.** Para mudar, edite o atual. - **O domínio precisa apontar para a internet pública.** O Festero recusa endereços que resolvem para redes internas, e confere o destino de novo a cada envio. - **O Festero não segue redirecionamentos.** Cadastre o endereço final: uma resposta 3xx conta como falha. - **O segredo aparece uma única vez**, ao cadastrar. Copie e guarde: ele é a chave para [verificar a assinatura](https://developers.festero.com.br/webhooks/assinatura.md). Se perder, use **Gerar novo segredo**. > **Atenção**: Guarde o segredo agora > > O segredo de assinatura (começa com `whsec_`) é mostrado só na criação e a cada troca. Depois de fechar a janela, não dá para vê-lo de novo. ## Teste e ativação Ao cadastrar, o endereço fica com o status **Aguardando teste** e o Festero envia um evento `ping`, assinado como qualquer outro. O endereço passa a **Ativo** quando responde 2xx a um `ping`. Antes disso, nenhum evento real é enviado. - Para repetir o teste, clique em **Enviar teste**. - Trocar a URL do endereço faz ele voltar a **Aguardando teste**, porque a URL nova ainda não provou que é sua. - O `ping` não conta como falha do endereço e não entra no limite por hora. Veja o `ping` em [Eventos de webhook](https://developers.festero.com.br/webhooks/eventos.md#ping). ## A requisição que você recebe ```http POST /webhooks/festero HTTP/1.1 Host: seusistema.com.br Content-Type: application/json; charset=utf-8 User-Agent: Festero-Webhooks/1.0 Festero-Event: quote.accepted Festero-Event-Id: c0a8e5b2-3f41-4d7a-9b16-2e8d5a7f1c04 Festero-Delivery-Id: 4b1e7d30-9a52-4c86-b3f0-2d8a6e1c5f97 Festero-Attempt: 1 Festero-Signature: t=1792593128,v1=b6de473caad2e5bc13c7df4254a8c1f8f9af543e99cadc5bb19b160083f20eee {"event_id":"c0a8e5b2-3f41-4d7a-9b16-2e8d5a7f1c04","type":"quote.accepted","occurred_at":"2026-10-21T14:32:08.4519833Z","workspace_id":"0f8fad5b-d9cb-469f-a165-70867728950e","api_version":"v1","resource_url":"https://platform.festero.com.br/v1/quotes/e4f6a9b2-3c71-4d85-9b0e-7a1c5d8f2634","data":{"id":"e4f6a9b2-3c71-4d85-9b0e-7a1c5d8f2634","status":"approved","event_id":"b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90"}} ``` | Cabeçalho | Significado | |---|---| | `Festero-Event` | O tipo do evento, por exemplo `quote.accepted`. | | `Festero-Event-Id` | Identificador do evento. Não muda entre reentregas e é igual ao `event_id` do corpo. Use-o para [deduplicar](#idempotencia-e-ordem). | | `Festero-Delivery-Id` | Identificador da entrega do evento ao seu endereço. | | `Festero-Attempt` | Número da tentativa: 1 na primeira e 2, 3... nas reentregas. | | `Festero-Signature` | A assinatura: `t=,v1=`. Durante a [troca do segredo](https://developers.festero.com.br/webhooks/assinatura.md#troca-do-segredo), traz também `v1_prev`. | | `Content-Type` | `application/json`. | | `User-Agent` | `Festero-Webhooks/1.0`. | O corpo é o envelope JSON descrito em [Eventos de webhook](https://developers.festero.com.br/webhooks/eventos.md#o-envelope). A verificação da assinatura usa esses bytes exatamente como chegaram. ## O que responder Responda com qualquer status **2xx em até 10 segundos**. O corpo da sua resposta é ignorado. - **Responda primeiro, processe depois.** Verifique a assinatura, grave o aviso numa fila e devolva `200`. Trabalho demorado dentro da requisição estoura os 10 segundos e vira falha. - Qualquer outra coisa conta como falha: 3xx, 4xx, 5xx, demora além de 10 segundos, ou falha de conexão ou de TLS. ## Reentregas Se o seu endereço não responde 2xx, o Festero tenta de novo, com intervalos crescentes. O mesmo evento volta com o mesmo `Festero-Event-Id`, o `Festero-Attempt` aumentado e uma assinatura nova (o `t` é o instante da nova tentativa). | Tentativa que falhou | Próxima tentativa | |---|---| | 1ª | depois de 1 minuto | | 2ª | depois de 5 minutos | | 3ª | depois de 30 minutos | | 4ª | depois de 2 horas | | 5ª | depois de 6 horas | | 6ª | depois de 24 horas | | 7ª | nenhuma: a entrega é **abandonada** | São, portanto, 7 tentativas (a primeira e 6 reentregas) ao longo de cerca de 33 horas. Casos especiais: - **Resposta 410 (Gone):** o Festero entende que o endereço não existe mais, abandona a entrega na hora e conta isso como 3 falhas. - **Falha do lado do Festero** (por exemplo, uma indisponibilidade nossa): a nova tentativa sai em 1 minuto e não conta contra o seu endereço nem entra nas 7 tentativas. - **Reenviar:** na tabela **Entregas recentes** da tela, o botão **Reenviar** manda de novo um evento entregue, que falhou ou que foi abandonado, desde que tenha até 7 dias. Uma entrega abandonada não é perdida para sempre: o dado continua na API. Busque o recurso pelo `resource_url` ou pelo filtro `updatedSince`. ## Desativação automática Um endereço que falha demais é desativado, para o Festero não insistir num destino fora do ar. A regra, que precisa ser cumprida **nas duas partes**: 1. **10 falhas seguidas** do seu endereço (cada tentativa que falha conta; o 410 conta por 3), e 2. a **primeira** dessas falhas aconteceu há **mais de 24 horas**. Qualquer resposta 2xx zera a contagem. Falhas do Festero e do `ping` não contam. Quando isso acontece: - o status do endereço passa a **Desativado** e as pessoas com a permissão de gerenciar a API recebem uma notificação no Festero; - os eventos que acontecem **enquanto ele está desativado não são enviados depois**. Para recuperar o período, consulte a API com `updatedSince` (veja [Paginação e datas](https://developers.festero.com.br/paginacao.md#sincronizacao-incremental)); - depois de corrigir o seu sistema, clique em **Reativar**. Se a URL já foi testada antes, ele volta direto a **Ativo**; senão, volta a **Aguardando teste**. Você também pode **Desativar** o endereço manualmente, a qualquer momento. ## Teto por hora Cada endereço recebe no máximo **3.000 entregas por hora**. Uma janela de uma hora começa na primeira entrega e se renova quando passa uma hora. O excedente não é descartado: as entregas ficam com o status **Adiada pelo limite por hora** e saem quando a janela seguinte abre. Se o acúmulo passa de **10.000 entregas adiadas**, ou a mais antiga espera há mais de **24 horas**, o endereço é desativado com o motivo "passou do limite de entregas por hora". As entregas pendentes ficam guardadas e seguem quando você reativa. ## Idempotência e ordem - **O mesmo aviso pode chegar mais de uma vez**, por reentrega ou por duplicidade na entrega. Guarde os `Festero-Event-Id` já processados e ignore os repetidos. Seu processamento deve dar o mesmo resultado se rodar duas vezes. - **A ordem é a melhor possível, mas não é garantida**, nem entre eventos de recursos diferentes. Um aviso reentregue chega depois de outros mais novos. Em vez de confiar na ordem de chegada, busque o estado atual pelo `resource_url`. ## O resource_url Todo aviso traz o endereço do recurso na API, por exemplo `https://platform.festero.com.br/v1/quotes/e4f6a9b2-...`. Chame-o com `Authorization: Bearer `, como qualquer rota da API. - Você recebe o estado **de agora**, que pode ser mais novo do que o do aviso. - A sua credencial precisa ter o escopo do recurso (`quotes:read` para um orçamento, e assim por diante). Veja a tabela em [Eventos de webhook](https://developers.festero.com.br/webhooks/eventos.md#escopos-e-assinatura). - Um recurso excluído responde `404` (por exemplo, depois de um `event.cancelled` com `reason` igual a `deleted`). ## Trocar o segredo Em **Gerar novo segredo**, o Festero cria um segredo novo e o mostra uma única vez. O anterior continua valendo por **24 horas**, e os avisos desse período trazem as duas assinaturas (`v1` e `v1_prev`). Detalhes e código em [Verificar a assinatura](https://developers.festero.com.br/webhooks/assinatura.md#troca-do-segredo). ## Acompanhar as entregas A tabela **Entregas recentes** da seção Webhook mostra cada entrega, com o status: | Status na tela | Significado | |---|---| | Na fila | Aguardando envio. | | Enviando | A requisição está a caminho. | | Entregue | Seu endereço respondeu 2xx. | | Falhou, vai tentar de novo | Há uma nova tentativa agendada. | | Abandonada | Esgotou as 7 tentativas, ou o endereço respondeu 410. | | Adiada pelo limite por hora | Passou do teto de 3.000 por hora e sai na próxima janela. | Ao abrir uma linha, você vê cada tentativa, com o código que o seu endereço respondeu, a duração e de quem foi a falha: **Falha do seu endereço** ou **Falha do Festero (não conta contra o seu endereço)**. O Festero não guarda o corpo das respostas do seu endereço. ## Contrato de entrega, em resumo | Item | Valor | |---|---| | Requisição | `POST` com corpo JSON e `Content-Type: application/json`. Somente HTTPS na porta 443. | | Cabeçalhos | `Festero-Event`, `Festero-Event-Id`, `Festero-Delivery-Id`, `Festero-Attempt` e `Festero-Signature: t=,v1=`. Na troca do segredo, também `v1_prev`, por 24 horas. | | Verificação | HMAC-SHA256 de `"."` com o segredo do endereço, comparado em tempo constante. Recuse se `t` estiver a mais de 5 minutos do relógio do seu servidor (em reentregas, `t` é o instante da tentativa). | | Resposta esperada | Qualquer 2xx em até 10 segundos. O corpo é ignorado. Responda primeiro e processe depois. | | Idempotência | O mesmo evento pode chegar mais de uma vez: deduplique por `Festero-Event-Id`. | | Ordem | Melhor esforço, nunca garantida. | | Reentregas | 7 tentativas, com 1 min, 5 min, 30 min, 2 h, 6 h e 24 h entre elas. Redirecionamentos não são seguidos. | | Desativação | 10 falhas seguidas, a primeira há mais de 24 horas. Reativável na tela **API do Festero**. | | Teto | 3.000 entregas por hora por endereço. O excedente é adiado para a hora seguinte, sem descartar. | | Segredo | Mostrado uma vez ao criar e ao trocar. | ## Checklist do seu endereço - [ ] Responde 2xx em poucos segundos, sem processar dentro da requisição. - [ ] Lê o corpo como bytes brutos e [verifica a assinatura](https://developers.festero.com.br/webhooks/assinatura.md). - [ ] Recusa assinatura inválida e `t` fora de 5 minutos. - [ ] Deduplica por `Festero-Event-Id`. - [ ] Busca o estado atual pelo `resource_url` em vez de confiar só no payload. - [ ] Tem um jeito de recuperar o que perdeu, com a API e `updatedSince`, caso fique fora do ar.