Eventos de webhook - Visão Geral
Introdução
O recurso de Webhook Events é o histórico de todas as notificações geradas para os Webhook Endpoints configurados. Ele permite monitorar a entrega de eventos, verificar o status, identificar falhas e reenviar (replay) eventos quando necessário, garantindo que os sistemas integrados permaneçam sincronizados com a plataforma.
Conceito e Funcionalidade
Cada evento registra uma ocorrência na sua conta (ex.: transaction.approved), seu tipo, o recurso afetado e o resultado da entrega. A partir do evento, a plataforma cria um ou mais dispatches — uma tentativa de entrega por endpoint elegível. A listagem de eventos já traz os dispatches aninhados em cada item.
Timeout e Retentativas
A plataforma aguarda a resposta do seu endpoint por até 30 segundos (a resposta completa — cabeçalho e corpo). Sem resposta 2xx nesse período (ou em caso de erro/timeout), a tentativa é registrada como falha e o sistema agenda uma nova tentativa com backoff (até esgotar as retentativas, ~3 dias).
Endpoint lento. A entrega da plataforma é compartilhada entre as contas, então nenhum endpoint pode segurá-la:
cada endpoint tem um número pequeno de entregas simultâneas, e um endpoint que levou 5 segundos ou mais para
responder (ou estourou o prazo) passa, por alguns minutos, a receber pela fila agendada — os eventos continuam
chegando, com alguns segundos de atraso. Responder 2xx logo e processar depois evita isso.
Ordem. A ordem de entrega não é garantida: dois eventos do mesmo recurso podem chegar fora da ordem em que
aconteceram (por exemplo, um vai pela fila agendada e o seguinte não). Use o createdAt do envelope e o estado do
recurso em payload.object — nunca a ordem de chegada — para decidir o que vale.
Fluxo de Entrega de Eventos
sequenceDiagram
autonumber
participant SW as Selectwin
participant EP as Seu Endpoint
Note over SW: Mudança de status<br/>gera um evento
SW->>EP: POST payload (X-Selectwin-Signature)
alt resposta 2xx em até 30s
EP-->>SW: 200 OK
Note over SW: dispatch = success
else timeout (>30s) ou erro
EP--xSW: erro / sem resposta
Note over SW: agenda nova tentativa (backoff)
SW->>EP: POST payload (retry)
EP-->>SW: 200 OK
endEventos podem ser reenviados manualmente via POST /v1/webhooks/events/{eventId}/resend
(veja Reenviar Evento). Valide sempre a assinatura X-Selectwin-Signature antes de
processar o payload.
Retenção
O histórico de eventos e de suas tentativas de entrega (dispatches) fica disponível por 90 dias a partir da criação do evento. Depois disso o evento e os dispatches dele saem da listagem e não podem mais ser reenviados — guarde no seu sistema o que precisar manter por mais tempo.
O mesmo evento não volta depois da janela. Um evento é único para sempre, não só enquanto está no histórico — um
por recurso, id do recurso e tipo, ou um por ocorrência nos tipos que se repetem (veja
Uma vez por recurso × uma vez por ocorrência): um segundo
transaction.approved da mesma venda tra_… não gera entrega nova, nem depois que o evento saiu da listagem (a
Selectwin guarda a chave do evento apagado). Mesmo assim, além de deduplicar pelo id, torne o processamento idempotente
pelo estado do recurso em payload.object: não libere de novo um pedido que o seu sistema já marcou como pago.
Uma vez por recurso × uma vez por ocorrência
Cada evento tem um id (wbh_…), que chega também no cabeçalho X-Selectwin-Event-Id. A Selectwin nunca entrega o
mesmo fato como dois eventos; o que conta como "o mesmo fato" depende do tipo:
| Regra | Tipos | Na prática |
|---|---|---|
| Uma vez por recurso | Os fatos que acontecem uma vez na vida do recurso: *.created, *.approved, *.paid, *.canceled, *.deleted e os demais tipos de status, inclusive as mudanças de status de assinatura (subscription.active, subscription.pastdue…) e de seller (seller.approved, seller.blocked…) | Um segundo transaction.approved da mesma venda tra_… não gera evento novo, nem quando a venda volta a approved porque você ganhou uma disputa |
| Uma vez por ocorrência | Todo *.updated (customer.updated, customer.address.updated, card.updated, subscription.updated, seller.updated…) | Cada alteração do recurso é um evento novo, com id próprio — no máximo um por recurso a cada 60 s: alterações do mesmo recurso no mesmo minuto chegam como UM evento, com o estado da primeira (veja Janela e orçamento dos *.updated, abaixo) |
| Uma vez por ocorrência | coupon.disabled | Desativar, reativar e desativar de novo o mesmo cupom entrega dois coupon.disabled, cada um com id próprio |
| Uma vez por ocorrência | transaction.refunded | Cada estorno liquidado da mesma transação é um evento novo, com id próprio. Pela API a venda aceita um pedido de reembolso, mas pode receber outro estorno por fora dele (uma devolução de Pix, por exemplo) — e esse também gera evento |
| Uma vez por ocorrência | transaction.dispute, transaction.chargeback, receivable.dispute, receivable.chargeback | Disputa e chargeback podem reabrir: a disputa encerrada a seu favor volta, o chargeback revertido é cobrado de novo. Cada reabertura na mesma venda (ou no mesmo recebível) é um evento novo, com id próprio. A primeira disputa e o primeiro chargeback chegam com o mesmo id de sempre |
Janela e orçamento dos *.updated. Cada *.updated sai no máximo uma vez por recurso a cada 60 s: a ocorrência
é o updatedAt do recurso truncado ao minuto (UTC), então dez alterações do mesmo cliente no mesmo minuto chegam como UM
customer.updated, com o estado da primeira — o evento é um snapshot congelado e assinado, nunca reescrito (a exceção
é subscription.updated, cuja ocorrência é a versão do conteúdo: cada mudança da assinatura é um evento). E cada conta
tem um orçamento de *.updated por hora, por ambiente: 5 000 no live e 300 no sandbox. Acima dele, os
*.updated restantes daquela hora não são emitidos — a sua request continua respondendo normalmente (2xx); só o
webhook fica de fora. Os eventos de dinheiro e de estado (*.created, *.approved, *.paid, *.canceled, *.deleted,
transaction.refunded, disputa e chargeback…) não têm janela nem orçamento: saem sempre. Por isso trate um *.updated
como o sinal de que o recurso mudou e, quando precisar do estado atual, leia-o pela API (GET) — o que vale para todo
evento, porque a ordem de entrega não é garantida.
Retentativas, reentregas e reenvios da mesma ocorrência chegam sempre com o mesmo id: deduplique por ele.
Duas ocorrências do mesmo tipo no mesmo recurso chegam com ids diferentes — não descarte um customer.updated
porque já recebeu outro do mesmo cliente, nem um transaction.refunded porque a venda já tinha um estorno, nem um
transaction.dispute porque a venda já esteve em disputa. Como a ordem de entrega não é garantida, use o estado do
recurso em payload.object (no estorno, os valores estornados da transação) para decidir o que vale.
Os eventos de catálogo saem um por recurso afetado: uma operação que mexe em várias variantes de um produto (criar o
produto com variantes, excluí-lo, a retirada do ar pela moderação) entrega o evento do produto e um variant.* para cada
variante, cada um com id próprio. Veja o Catálogo.
Estrutura do Objeto Evento (respostas da API)
Itens de listagem de events (com dispatches aninhados; envelope paginado com merchant/_links no root):
{
"id": "wbh_01hqzvabc",
"type": "transaction.approved",
"resource": "transaction",
"resourceId": "tra_987654321",
"source": "automatic",
"delivered": true,
"attempts": 1,
"data": { "id": "tra_987654321", "status": "approved", "amount": 1500 },
"createdAt": "2026-06-20T17:56:32.000Z",
"dispatches": [ { "id": "wdi_01hqzvabc", "status": "success", "...": "..." } ]
}| Atributo | Tipo | Descrição |
|---|---|---|
id | string | ID do evento (wbh_*) |
type | string | Tipo do evento (ver Catálogo) |
resource | string | Recurso afetado (ex.: transaction) |
resourceId | string | null | ID público do recurso |
source | string | Origem do evento (automatic, api) |
account | string | Só para plataformas de marketplace, nos eventos repassados de uma sub-conta: o id (bus_…) da sub-conta a que o evento pertence. Ausente nos eventos da própria conta. Presente também no envelope entregue à sua URL — veja Marketplace |
delivered | boolean | Se a entrega foi concluída com sucesso |
attempts | integer | Total de tentativas de entrega |
data | objeto | O objeto do recurso (mesma forma da leitura do recurso) |
createdAt | string (ISO) | Data de criação do evento |
dispatches | array | Tentativas de entrega aninhadas (ver Dispatches) |
merchant / _links | object | Presentes na leitura individual e no envelope da lista |
Recursos Disponíveis
| Recurso | Método | Caminho | Descrição |
|---|---|---|---|
| Listar Eventos | GET | /v1/webhooks/events | Lista eventos com paginação e filtros (dispatches aninhados) |
| Recuperar Evento | GET | /v1/webhooks/events/{eventId} | Recupera um evento e seus dispatches |
| Reenviar Evento | POST | /v1/webhooks/events/{eventId}/resend | Reentrega o evento a todos os endpoints elegíveis |
Tipos de Eventos
A lista completa e autoritativa está no Catálogo de Eventos de Webhook. Alguns dos principais tipos:
| Categoria | Tipo de Evento | Descrição |
|---|---|---|
| Transações | transaction.created | Quando uma nova transação é criada |
| Transações | transaction.approved | Quando uma transação é aprovada |
| Transações | transaction.failed | Quando uma tentativa de transação falha |
| Transações | transaction.canceled | Quando uma transação é cancelada |
| Transações | transaction.refunded | Quando uma transação é estornada |
| Clientes | customer.created | Quando um novo cliente é criado |
| Clientes | customer.updated | Quando um cliente é atualizado |
| Clientes | customer.deleted | Quando um cliente é excluído |
| Endereços | customer.address.created | Quando um endereço de cliente é criado |
| Cartões | card.created | Quando um novo cartão é registrado |
| Cartões | card.deleted | Quando um cartão é removido |
| Carteiras | wallet.created | Quando uma nova carteira é criada |
| Carteiras | wallet.enabled | Quando uma carteira é ativada |
| Recebíveis | receivable.paid | Quando um recebível é pago/liberado |
| Webhooks | webhook.created | Quando um novo webhook endpoint é configurado |
Casos de Uso Comuns
- Monitoramento de Integrações: acompanhamento da saúde das integrações via webhook
- Recuperação de Eventos: identificação e reenvio de eventos não entregues
- Auditoria: histórico completo das notificações geradas
- Depuração: análise de falhas de entrega via Dispatches
Melhores Práticas
- Monitoramento Regular: verifique o status de entrega dos eventos.
- Reenvio Seletivo: use o reenvio apenas para eventos que não foram entregues com sucesso.
- Filtragem: ao listar, use os filtros (
type,status,resource,endpoint, datas). - Deduplicação: processe cada
idde evento (wbh_...) apenas uma vez — e trate o estado do recurso empayload.objectcomo a verdade (veja Retenção). Deduplique peloid, nunca por recurso e tipo: os tipos por ocorrência trazem umidnovo a cada alteração ou estorno. Num*.updated, releia o recurso (GET) se precisar do estado atual: ele chega no máximo uma vez por minuto por recurso, com o estado da primeira alteração do minuto, e tem orçamento por hora (veja Uma vez por recurso × uma vez por ocorrência). - Filas: processe os eventos de forma assíncrona e resiliente.
Integração com Outros Recursos
- Webhook Endpoints: os eventos são entregues aos endpoints configurados.
- Webhook Dispatches: cada tentativa de entrega é um dispatch auditável.
- Transactions / Customers / Cards / Wallets / Finance / Checkout: geram eventos em mudanças de estado (ver Catálogo).
Atualizado em 21 de outubro de 2026