---
title: "Webhooks — BeeFood API"
description: "Como receber eventos de pedido da BeeFood em tempo real: assinatura, formato do evento, segurança e política de reentrega."
url: "https://developer.beefood.com.br/docs/webhooks"
group: "Webhooks"
lang: "pt"
---
# Webhooks

O webhook avisa a sua aplicação, em tempo real, que **alguma coisa mudou em um pedido**: ele nasceu, foi alterado, mudou de status de entrega ou recebeu um pagamento.

É a alternativa recomendada ao [polling](https://docs.beefood.app/docs/pedidos/polling): em vez de perguntar de tempos em tempos se mudou algo, você recebe um POST no momento em que muda.

## Cadastrando um webhook

O cadastro é feito **no painel do desenvolvedor**, em *Webhooks*. Não há rota pública para criar webhook por código.

No cadastro você informa:

| Campo | Descrição |
| --- | --- |
| **URL** | O endereço que vai receber os POSTs. Precisa ser HTTPS e estar acessível pela internet |
| **Eventos** | Quais dos eventos abaixo esse webhook recebe |
| **E-mail do responsável** | Para onde avisamos se as entregas começarem a falhar |
| **Usuário e senha** | Opcionais. Preenchidos, enviamos Basic Auth na URL de destino (os dois ou nenhum) |
| **Ativo** | Desmarque para pausar as entregas sem perder o cadastro |

Você pode ter mais de um webhook por estabelecimento, cada um assinando eventos diferentes.

O **secret** é exibido **uma única vez**, no momento da criação. Guarde-o: é com ele que você valida que a chamada veio mesmo da BeeFood. Se perder, gere um novo webhook.

## Eventos disponíveis

| `eventType` | Quando dispara |
| --- | --- |
| `order_created` | Pedido criado |
| `order_updated` | Pedido alterado (inclusive devolução de Pix) |
| `order_delivery_updated` | Mudança no status de entrega |
| `payment_created` | Pagamento registrado |
| `payment_updated` | Pagamento alterado ou excluído |

## O que você recebe

O corpo do POST é o **evento**, não o pedido:

```json
{
  "eventType": "order_delivery_updated",
  "orderId": 58449268,
  "event": "order_delivery_updated",
  "orderType": "DELIVERY",
  "salesChannel": "IFOOD",
  "orderStatusDelivery": "PREPARING",
  "createdAt": "2025-03-15T18:42:10.000Z"
}
```

| Campo | Descrição |
| --- | --- |
| `eventType` / `event` | O tipo do evento. Os dois campos trazem sempre o mesmo valor; `event` é o nome que a rota de polling usa. Escolha um |
| `orderId` | Identificador do pedido, o mesmo aceito em `GET /v1/orders/{orderId}` |
| `orderType` | `DELIVERY`, `PDV` ou `TABLE` |
| `salesChannel` | Canal de venda (`IFOOD`, `DIGITAL_MENU`, `MANUAL`, …) |
| `orderStatusDelivery` | Status de entrega no momento do evento (`WAITING`, `PREPARING`, `READY`, `DISPATCHED`, `DELIVERED`, `CANCELLED`) |
| `createdAt` | Momento do evento, em UTC |

Campos que o evento não carrega são **omitidos** do JSON — trate todos como opcionais, exceto `eventType`, `event` e `orderId`.

É exatamente o mesmo formato de um item de `GET /v1/orders/polling`. Quem já consome o polling pode reaproveitar o mesmo código de tratamento nos dois caminhos.

## Exemplos por evento

O formato é o mesmo para todos os eventos — o que varia é quais campos opcionais vêm preenchidos, porque cada evento nasce de uma operação diferente no sistema do restaurante.

### `order_created`

Pedido novo. É o evento mais completo, e o melhor momento para buscar o detalhe e guardar o que você precisa.

```json
{
  "eventType": "order_created",
  "orderId": 61398399,
  "event": "order_created",
  "orderType": "DELIVERY",
  "salesChannel": "IFOOD",
  "orderStatusDelivery": "PREPARING",
  "createdAt": "2026-10-13T12:44:25.000Z"
}
```

### `order_delivery_updated`

Mudança de status de entrega. É o evento de maior volume: um pedido de delivery costuma gerar de 3 a 6 deles até ser entregue.

```json
{
  "eventType": "order_delivery_updated",
  "orderId": 61398393,
  "event": "order_delivery_updated",
  "orderType": "DELIVERY",
  "salesChannel": "IFOOD",
  "orderStatusDelivery": "PREPARING",
  "createdAt": "2026-10-13T12:44:11.000Z"
}
```

Acompanhe o `orderStatusDelivery` para saber onde o pedido está. A sequência típica é `WAITING` → `ACCEPTED` → `PREPARING` → `READY` → `DISPATCHED` → `DELIVERED`, e qualquer etapa pode terminar em `CANCELLED`.

### `order_updated`

Pedido alterado. Dispara em situações variadas — devolução de Pix, alteração de itens, reabertura — e por isso é o evento que costuma trazer menos campos:

```json
{
  "eventType": "order_updated",
  "orderId": 61398324,
  "event": "order_updated",
  "createdAt": "2026-10-13T12:44:00.000Z"
}
```

Como o evento não diz **o que** mudou, este é o caso em que buscar o detalhe faz sentido, se o seu sistema precisa refletir alterações no conteúdo do pedido.

### `payment_created`

Pagamento registrado no pedido.

```json
{
  "eventType": "payment_created",
  "orderId": 61398383,
  "event": "payment_created",
  "orderType": "TABLE",
  "createdAt": "2026-10-13T12:44:26.000Z"
}
```

### `payment_updated`

Pagamento alterado ou excluído.

```json
{
  "eventType": "payment_updated",
  "orderId": 61398097,
  "event": "payment_updated",
  "orderType": "TABLE",
  "createdAt": "2026-10-13T12:43:10.000Z"
}
```

> **Informação**
>
> Os eventos de pagamento avisam que *houve* movimento de pagamento no pedido, mas **não trazem valor, forma de pagamento nem o identificador do pagamento**. Para esses dados, consulte `payments` em `GET /v1/orders/{orderId}`.

## Como usar o evento

O evento diz **o que mudou e em qual pedido**. Quando você precisar do conteúdo do pedido — itens, cliente, pagamentos, endereço — chame o detalhe:

```
GET /v1/orders/{orderId}
```

Na prática, a maior parte das integrações não precisa do detalhe em todo evento. Um `order_delivery_updated` que leva o pedido para `DELIVERED`, por exemplo, já traz tudo o que é preciso para dar baixa: o `orderId` e o novo status. Buscar o pedido inteiro nesse momento é trabalho jogado fora, porque nada mudou além do status que o próprio evento já informou.

A recomendação é: **leia o detalhe uma vez**, normalmente no `order_created`, guarde o que você precisa, e depois use os eventos seguintes só para atualizar o status na sua base.

> **Atenção**
>
> Buscar o detalhe do pedido a cada evento recebido é o erro mais comum de integração. Além de desnecessário, é a chamada mais cara da API, porque ela consulta o sistema do restaurante em tempo real. Consultas repetidas em excesso podem acionar a [proteção de uso indevido](https://docs.beefood.app/docs/limites).

## Segurança

Toda entrega inclui o header:

```
X-Webhook-Secret: <o secret devolvido na criação do webhook>
```

Valide esse header e rejeite o que não bater. Se a sua URL exigir Basic Auth, informe `user` e `password` no cadastro do webhook (os dois ou nenhum) e nós enviaremos o header `Authorization` junto.

## Entrega e reentrega

| Regra | Comportamento |
| --- | --- |
| Método | `POST` com `Content-Type: application/json` |
| Sucesso | Qualquer `2xx` |
| Timeout | 15 segundos |
| Tentativas | Até 5, com cerca de 2 segundos entre elas |
| Após 5 falhas | O evento é marcado como erro e o dono do webhook recebe um e-mail |

Responda `2xx` **assim que receber**, antes de processar. Se a sua aplicação demora para responder, a entrega entra em retry e os eventos seguintes do mesmo estabelecimento ficam na fila atrás dela — a ordem é preservada por estabelecimento.

Projete o seu endpoint para ser **idempotente**: uma reentrega pode repetir um evento que você já processou.

## Onde encontrar o resto do pedido

O evento é propositalmente enxuto: ele avisa **o que mudou**, não transporta o pedido. Os dados de conteúdo ficam em `GET /v1/orders/{orderId}`:

| O que você precisa | Onde buscar |
| --- | --- |
| Identificar o pedido e o que mudou | O próprio evento |
| Itens, complementos e observações | `items` do detalhe |
| Cliente, telefone e endereço | `customer` e `delivery.address` do detalhe |
| Pagamentos, valores e descontos | `payments`, `total` e `discount` do detalhe |
| Entregador e linha do tempo da entrega | `delivery.driver` e `delivery.timeline` do detalhe |

## Perguntas frequentes

**Webhook ou polling: qual usar?**  
Os dois entregam o mesmo formato de evento, então são caminhos alternativos para a mesma informação. O webhook é o recomendado, por ser imediato e não gastar requisições. O polling (`GET /v1/orders/polling`) serve a quem não tem como expor uma URL pública, e também para reconciliar.

**Perdi eventos enquanto meu servidor estava fora. E agora?**  
Use `GET /v1/orders/polling`, que mantém uma janela das últimas 8 horas, para reconciliar.

**O `createdAt` é a data do pedido ou do evento?**  
Do evento. Para a data de criação do pedido, use o `createdAt` do detalhe em `GET /v1/orders/{orderId}`.

**Preciso tratar os dois campos, `event` e `eventType`?**  
Não. Eles sempre trazem o mesmo valor; escolha um.
