Aparência
Eventos de webhook
São 13 eventos, mais o ping de verificação. Esta página diz quando cada um dispara e mostra o payload de exemplo. Como cadastrar o endereço, responder e tratar reentregas está em Webhooks; como conferir a assinatura, em Verificar a assinatura.
O envelope
Todo evento chega como um JSON com o mesmo envelope. O que muda é o conteúdo de data.
| Campo | Tipo | Descrição |
|---|---|---|
event_id | GUID | Identificador estável do evento. É o mesmo valor do cabeçalho Festero-Event-Id e a chave para deduplicar. |
type | texto | O tipo do evento, por exemplo quote.accepted. Igual ao cabeçalho Festero-Event. |
occurred_at | instante | Quando aconteceu, em UTC (ISO 8601, termina em Z). |
workspace_id | GUID | Identificador da sua empresa. |
api_version | texto | Versão da API. Hoje é v1. |
resource_url | texto | Endereço do recurso na API. Busque o estado atual por ele, com a sua credencial. |
data | objeto | Dados resumidos do evento. |
O data é enxuto de propósito: traz identificadores, situação e datas. Nunca traz custo, margem, contato de pessoas nem textos livres. Para o resto, use resource_url. Os nomes de campo do webhook usam snake_case (event_id, occurred_at), diferente da API, que usa camelCase.
O estado pode ter andado
Quando você busca o resource_url, recebe o estado de agora, que pode ser mais novo do que o do evento. Isso é o esperado: processe sempre o estado atual. Um recurso excluído responde 404.
Escopos e assinatura
Cada evento pertence a um conjunto de dados, e você só pode assinar os eventos dos conjuntos que você mesmo enxerga no Festero. Para buscar o recurso do aviso, a sua credencial precisa do escopo correspondente.
| Conjunto | Escopo | Eventos |
|---|---|---|
| Eventos | events:read | event.created, event.status_changed, event.cancelled |
| Orçamentos | quotes:read | quote.sent, quote.accepted, quote.rejected |
| Visitas | visits:read | visit.scheduled, visit.confirmed, visit.cancelled |
| CRM | crm:read | opportunity.created, opportunity.stage_changed |
| Financeiro | finance:read | receivable.paid, receivable.overdue |
Eventos
event.created
Quando dispara: um evento é criado: pelo cadastro de evento no Festero, pela importação de eventos ou quando um orçamento aprovado gera o evento (inclusive quando o cliente aceita a proposta pelo portal). Um evento cadastrado já como realizado dispara também um event.status_changed.
Campo de data | Descrição |
|---|---|
id | Identificador do evento. |
status | Situação do evento: draft, upcoming, confirmed, inprogress, completed ou cancelled. |
event_date | Data do evento (yyyy-MM-dd). |
json
{
"event_id": "5a2f9c40-8e17-4b63-a0d5-3c7e1b9f6d28",
"type": "event.created",
"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/events/b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"data": {
"id": "b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"status": "draft",
"event_date": "2027-03-20"
}
}event.status_changed
Quando dispara: a situação do evento muda. Se a situação nova é igual à antiga, nada é enviado. O campo source diz o que provocou a mudança.
Campo de data | Descrição |
|---|---|
id | Identificador do evento. |
from | Situação anterior. |
to | Situação nova. |
source | Origem da mudança (tabela abaixo). |
event_date | Data do evento (yyyy-MM-dd). |
source | O que significa |
|---|---|
status_change | A situação foi trocada diretamente no Festero. |
contract_sent | O envio do contrato moveu a situação. |
contract_signed | A assinatura do contrato levou o evento a upcoming (Agendado). |
contract_cancelled | O cancelamento do contrato moveu a situação. |
manual_contract_upload | O envio manual de um contrato (assinado ou enviado) moveu a situação. |
already_happened | O evento foi cadastrado já como realizado. |
import | A importação de eventos criou o evento já numa situação. |
Quando a situação nova é cancelled, o Festero envia também um event.cancelled.
json
{
"event_id": "9d4b7e12-0a63-4c85-b1f9-6e2a8c3d5f07",
"type": "event.status_changed",
"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/events/b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"data": {
"id": "b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"from": "draft",
"to": "upcoming",
"source": "contract_signed",
"event_date": "2027-03-20"
}
}event.cancelled
Quando dispara: um evento é cancelado ou excluído. O campo reason diz qual dos dois: cancelled quando a situação passa a cancelado (junto com um event.status_changed) e deleted quando o evento é excluído (inclusive ao desfazer uma importação). Um evento excluído deixa de existir na API: o resource_url responde 404.
Campo de data | Descrição |
|---|---|
id | Identificador do evento. |
reason | cancelled ou deleted. |
event_date | Data do evento (yyyy-MM-dd). |
json
{
"event_id": "e1c8a5f3-7b20-4d96-8a4e-0f3b6d9c2a15",
"type": "event.cancelled",
"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/events/b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"data": {
"id": "b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"reason": "cancelled",
"event_date": "2027-03-20"
}
}quote.sent
Quando dispara: um orçamento é enviado ao cliente. Também dispara quando a validade do orçamento é renovada; nesse caso reason vem como renewed.
Campo de data | Descrição |
|---|---|
id | Identificador do orçamento. |
status | Situação do orçamento (sent). |
reason | renewed na renovação da validade; null no envio normal. |
valid_until | Data até a qual o orçamento vale (yyyy-MM-dd). |
json
{
"event_id": "3b6e0d92-5c14-4a78-9e2f-8d1a7c4b0e63",
"type": "quote.sent",
"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": "sent",
"reason": null,
"valid_until": "2026-11-15"
}
}quote.accepted
Quando dispara: um orçamento é aceito (situação approved), seja pelo cliente, na resposta ao orçamento, seja pela empresa, ao aprovar no Festero. Quando o aceite gera um evento, event_id traz o identificador dele.
Campo de data | Descrição |
|---|---|
id | Identificador do orçamento. |
status | Situação do orçamento (approved). |
event_id | Evento criado a partir do orçamento, ou null se nenhum foi criado. |
json
{
"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"
}
}quote.rejected
Quando dispara: um orçamento é recusado (situação rejected), pelo cliente ou pela empresa.
Campo de data | Descrição |
|---|---|
id | Identificador do orçamento. |
status | Situação do orçamento (rejected). |
json
{
"event_id": "7f1d3a85-2e60-4b94-a8c7-5d0e9b3f1a42",
"type": "quote.rejected",
"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": "rejected"
}
}visit.scheduled
Quando dispara: uma visita é agendada ou reagendada. No reagendamento, rescheduled vem true.
Campo de data | Descrição |
|---|---|
id | Identificador da visita. |
status | Situação da visita. |
scheduled_start | Início agendado, em UTC (2026-10-24T13:00:00Z). |
rescheduled | true se é um reagendamento. |
json
{
"event_id": "a4e7c1d9-6b30-4f52-8d0a-1c9e5b3f7a68",
"type": "visit.scheduled",
"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/visits/4e9a1c68-d205-4b73-8f1e-b6c0a3d95e27",
"data": {
"id": "4e9a1c68-d205-4b73-8f1e-b6c0a3d95e27",
"status": "scheduled",
"scheduled_start": "2026-10-24T13:00:00Z",
"rescheduled": false
}
}visit.confirmed
Quando dispara: a empresa confirma um pedido de visita.
Campo de data | Descrição |
|---|---|
id | Identificador da visita. |
status | Situação da visita. |
scheduled_start | Início agendado, em UTC. |
json
{
"event_id": "2c9f6b04-d718-4e35-b0a1-7e4d8a2c5f91",
"type": "visit.confirmed",
"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/visits/4e9a1c68-d205-4b73-8f1e-b6c0a3d95e27",
"data": {
"id": "4e9a1c68-d205-4b73-8f1e-b6c0a3d95e27",
"status": "scheduled",
"scheduled_start": "2026-10-24T13:00:00Z"
}
}visit.cancelled
Quando dispara: uma visita é cancelada ou um pedido de visita é recusado. O campo reason diz qual dos dois: cancelled quando a visita é cancelada (pela empresa, ou pelo cliente a partir do link da visita) e declined quando a empresa recusa o pedido.
Campo de data | Descrição |
|---|---|
id | Identificador da visita. |
status | Situação da visita. |
reason | cancelled ou declined. |
json
{
"event_id": "f6a30d7b-9c25-4e18-a4b2-0d8e1c5a7f39",
"type": "visit.cancelled",
"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/visits/4e9a1c68-d205-4b73-8f1e-b6c0a3d95e27",
"data": {
"id": "4e9a1c68-d205-4b73-8f1e-b6c0a3d95e27",
"status": "cancelled",
"reason": "cancelled"
}
}opportunity.created
Quando dispara: uma oportunidade de venda nasce no CRM: por cadastro no Festero, por uma mensagem recebida nos canais de atendimento conectados, por um pedido de orçamento feito pela vitrine ou por um agendamento de visita pela página pública.
Campo de data | Descrição |
|---|---|
id | Identificador da oportunidade. |
status | Situação da oportunidade (open ao nascer). |
stage_id | Identificador da etapa em que ela entrou. |
json
{
"event_id": "1d8c4f60-a3e9-4b27-9f05-6c2b7e0d3a84",
"type": "opportunity.created",
"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/crm/opportunities/8d3f6b1e-52a4-4c7e-9a18-0b6c2f4d7e31",
"data": {
"id": "8d3f6b1e-52a4-4c7e-9a18-0b6c2f4d7e31",
"status": "open",
"stage_id": "6b0d2f84-1c93-4e57-a8d6-3f7a9c5e1b20"
}
}opportunity.stage_changed
Quando dispara: uma oportunidade muda de etapa do funil: ao movê-la no quadro, ao fechá-la como ganha ou perdida, ao reabri-la e quando as automações do funil a movem. Se a etapa de origem e a de destino são a mesma, nada é enviado.
Campo de data | Descrição |
|---|---|
id | Identificador da oportunidade. |
from_stage_id | Etapa de origem. Pode ser null. |
to_stage_id | Etapa de destino. |
status | Situação da oportunidade depois da mudança. |
Os identificadores de etapa são os de GET /v1/crm/pipeline-stages.
json
{
"event_id": "8e2b5a73-c0d4-4f19-b6a8-3d9f1c7e0a52",
"type": "opportunity.stage_changed",
"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/crm/opportunities/8d3f6b1e-52a4-4c7e-9a18-0b6c2f4d7e31",
"data": {
"id": "8d3f6b1e-52a4-4c7e-9a18-0b6c2f4d7e31",
"from_stage_id": "6b0d2f84-1c93-4e57-a8d6-3f7a9c5e1b20",
"to_stage_id": "c41e9a77-6d02-4b58-8f3a-91d5e7b20a64",
"status": "open"
}
}receivable.paid
Quando dispara: o Festero registra um pagamento, total ou parcial, em um recebível. partial diz qual dos dois: false quando o recebível ficou pago e true quando ficou parcialmente pago.
Campo de data | Descrição |
|---|---|
id | Identificador do recebível. |
status | Situação do recebível depois do pagamento (paid ou partiallypaid). |
partial | true se o pagamento foi parcial. |
event_id | Evento a que o recebível pertence, ou null. |
due_date | Vencimento (yyyy-MM-dd). |
json
{
"event_id": "b9d0e6a1-4f72-4c38-8e15-2a7c3d5f0b96",
"type": "receivable.paid",
"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/finance/receivables/0f7c3a95-e1d8-4b26-9a40-5c2e8b6d1f73",
"data": {
"id": "0f7c3a95-e1d8-4b26-9a40-5c2e8b6d1f73",
"status": "partiallypaid",
"partial": true,
"event_id": "b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"due_date": "2026-11-10"
}
}receivable.overdue
Quando dispara: um recebível passa a vencido. Isso acontece quando a rotina diária do Festero marca como vencidos os recebíveis com vencimento anterior a hoje e quando uma edição ou reagendamento deixa o recebível vencido. O aviso sai uma vez, na passagem; um recebível que já estava vencido não dispara de novo.
Campo de data | Descrição |
|---|---|
id | Identificador do recebível. |
status | Situação do recebível (overdue). |
event_id | Evento a que o recebível pertence, ou null. |
due_date | Vencimento (yyyy-MM-dd). |
json
{
"event_id": "4a7d1c95-e320-4b68-a0f4-9c6e2b8d5f13",
"type": "receivable.overdue",
"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/finance/receivables/0f7c3a95-e1d8-4b26-9a40-5c2e8b6d1f73",
"data": {
"id": "0f7c3a95-e1d8-4b26-9a40-5c2e8b6d1f73",
"status": "overdue",
"event_id": "b7e2c4a1-95d3-4f08-a6b2-1c8d3e5f7a90",
"due_date": "2026-10-10"
}
}O evento ping
O ping não se assina: ele é o teste que o Festero envia ao cadastrar o endereço, ao trocar a URL e quando você clica em Enviar teste. O endereço só passa a receber os avisos reais depois de responder 2xx a um ping. O resource_url do ping é GET /v1/me.
Campo de data | Descrição |
|---|---|
endpoint_id | Identificador do endereço de webhook cadastrado. |
json
{
"event_id": "d2f8b4e6-1a70-4c93-8b05-7e3a9c1d6f28",
"type": "ping",
"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/me",
"data": {
"endpoint_id": "6c3e9a15-b8d2-4f70-a1e4-5d0b7c2f8a39"
}
}Dicas para tratar os eventos
- Decida pelo
type(ou pelo cabeçalhoFestero-Event) e ignore o que não reconhece. Você só recebe os tipos que assinou. - Use
datapara rotear eresource_urlpara ler. O payload serve para saber o que aconteceu e onde; o detalhe vem da API. - Não dependa da ordem. Dois avisos sobre o mesmo recurso podem chegar fora de ordem. Compare
occurred_atou, melhor, busque o estado atual. - Deduplique pelo
event_id. O mesmo aviso pode chegar mais de uma vez.