Visão geral
Um Webhook Event é o registro de uma notificação que a Selectwin gerou a partir de algo que aconteceu na sua conta (uma transação aprovada, um cliente criado, um recebível pago) e tentou entregar aos
Um Webhook Event é o registro de uma notificação que a Selectwin gerou a partir de algo que aconteceu na sua conta (uma transação aprovada, um cliente criado, um recebível pago) e tentou entregar aos seus Webhook Endpoints. Este recurso é o histórico auditável dessas notificações: você o usa para ver o que foi gerado, inspecionar cada tentativa de entrega (os dispatches) e reenviar manualmente um evento que falhou.
Se você está começando: um webhook é uma forma de a Selectwin "ligar de volta" para o seu servidor via HTTP POST sempre que algo muda, em vez de você ficar perguntando à API repetidamente (polling) — prática que desencorajamos. O recurso de Webhook Events é o painel desse mecanismo: registra o que foi enviado e dá ferramentas para recuperar entregas perdidas.
O que é (e o que não é)
- Um evento (
wbh_…) é uma notificação gerada por uma mudança no seu domínio (ex.:transaction.approved). Ele é imutável: descreve um fato que ocorreu num instante. - Um dispatch (
wdi_…) é uma tentativa de entrega desse evento a um endpoint específico. Um único evento pode ter vários dispatches (várias tentativas / vários endpoints), cada um com seu próprio status e código de resposta HTTP. - Este recurso não configura para onde os eventos vão — isso é feito nos Webhook Endpoints, onde você cadastra a URL e escolhe
events[]. Aqui você apenas consulta e reenvia o que já foi gerado.
Importante
Os tipos de evento aceitos por um endpoint (events[]) e seus significados vivem no Catálogo de Eventos de Webhook. Esta página descreve o objeto evento e suas operações, não a lista completa de tipos.
Como funciona a entrega
Quando um fato ocorre (ex.: uma transação muda para approved), a Selectwin cria o evento e dispara um POST para cada endpoint inscrito naquele tipo. Cada tentativa vira um dispatch:
- A Selectwin envia o
POSTcom o envelope do evento e o cabeçalho de assinaturaX-Selectwin-Signature: sha256=<hex>(HMAC-SHA256 do corpo bruto). - O seu servidor deve responder
2xxrapidamente. A Selectwin aguarda a resposta por até 15 segundos; depois disso a tentativa é considerada falha. - Se a tentativa falhar (timeout, conexão recusada,
4xx/5xx), a Selectwin agenda novas tentativas com backoff (intervalos crescentes), registrando cada uma como um novo dispatch. - Quando uma tentativa recebe
2xx, o dispatch é marcado como entregue (status: "success", comsuccessAtpreenchido) e as retentativas param.
Eventos que esgotam as retentativas automáticas (ou que você quer reprocessar) podem ser reenviados manualmente com POST /v1/webhooks/events/{eventId} — veja Reenviar Evento.
Atenção
Antes de confiar em qualquer payload recebido, verifique a assinatura HMAC X-Selectwin-Signature. Sem isso, um terceiro poderia forjar requisições para o seu endpoint. Passo a passo e código pronto em Verificando Assinaturas de Webhook.
O payload entregue ao seu endpoint
Quando um evento ocorre, a Selectwin faz um POST para a URL do seu endpoint com um envelope JSON. Esse corpo é diferente do objeto retornado pela API de listagem (mais abaixo): a listagem é o histórico/diagnóstico que você consulta; este é o que de fato chega ao seu servidor.
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID público do evento entregue (wbh_…). |
type | string | Tipo no formato recurso.acao (ex.: transaction.approved) ou um evento de plataforma como ping. Ver Catálogo de Eventos. |
source | string | Origem do evento (ex.: webhook). |
payload.object | object | O recurso relacionado ao evento. A forma varia conforme type. |
createdAt / updatedAt | string (date-time) | Criação/atualização do evento, em UTC (ISO 8601). |
correlationId | string | Identificador para correlacionar logs e suporte (corr_…). |
Exemplo: evento de teste (ping)
Um evento ping serve para verificar a conectividade do seu endpoint — confirme que sua URL responde antes de receber eventos reais. O payload.object é mínimo:
{
"id": "wbh_758c47e09f43c6d99cfe",
"type": "ping",
"source": "webhook",
"payload": {
"object": {
"message": "pong",
"endpointId": "wbe_01hqzvabc"
}
},
"createdAt": "2026-04-12T17:56:33.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z",
"correlationId": "corr_1776016593"
}Exemplo: evento real (transaction.approved)
Em eventos de recurso, payload.object carrega o objeto correspondente — aqui, a transação aprovada:
{
"id": "wbh_1234567890",
"type": "transaction.approved",
"source": "webhook",
"payload": {
"object": {
"id": "tra_987654321",
"status": "approved",
"amount": 1500,
"currency": "BRL",
"method": "credit"
}
},
"createdAt": "2026-04-12T17:56:33.000Z",
"updatedAt": "2026-04-12T17:56:33.000Z",
"correlationId": "corr_1234567890"
}Atenção
Responda 200 ou 201 para confirmar o recebimento. Qualquer outro status — inclusive outros 2xx, 3xx, 4xx e 5xx — é tratado como falha e aciona retentativas. E, antes de confiar no conteúdo, verifique a assinatura HMAC do cabeçalho X-Selectwin-Signature — veja Verificando Assinaturas de Webhook.
Modelo do objeto evento
As listagens retornam cada evento com seus dispatches aninhados. Exemplo anotado (campos do contrato):
{
"id": "wbh_01hqzvabc", // ID do evento (opaco, prefixo wbh_)
"resource": "transaction", // tipo de recurso que originou o evento
"type": "transaction.approved", // tipo do evento (ver Catálogo de Eventos)
"attempts": 1, // nº de tentativas de entrega do evento
"lastAttempt": "2026-04-12T17:56:33.000Z", // ISO 8601 UTC da última tentativa
"description": "Transaction approved event", // descrição legível
"requestPayload": { // resumo do recurso que disparou o evento
"id": "tra_987654321",
"amount": 1500, // em centavos: R$ 15,00
"status": "approved"
},
"updatedAt": "2026-04-12T17:56:33.000Z",
"createdAt": "2026-04-12T17:56:32.000Z",
"source": "api", // origem do fato (ex.: "api")
"dispatches": [ // tentativas de entrega (ver tabela abaixo)
{
"id": "wdi_01hqzvabc", // ID do dispatch (opaco, prefixo wdi_)
"status": "success", // estado desta tentativa
"endpoint": "https://webhooks.mydomain.com/selectwin",
"attempts": 1,
"lastAttemptAt": "2026-04-12T17:56:33.100Z",
"successAt": "2026-04-12T17:56:33.150Z", // null enquanto não entregue
"responseStatusCode": 200, // status HTTP que o seu servidor devolveu
"responseTime": 120, // tempo de resposta em ms
"responseBody": "OK", // início do corpo de resposta (para diagnóstico)
"correlationId": "corr_abc123",
"updatedAt": "2026-04-12T17:56:33.150Z",
"createdAt": "2026-04-12T17:56:33.000Z"
}
]
}Campos do evento
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID público do evento (wbh_…). Trate como opaco. |
resource | string | Recurso de origem (ex.: transaction, customer, receivable). |
type | string | Tipo do evento (ex.: transaction.approved) — ver Catálogo de Eventos. |
attempts | integer | Número de tentativas de entrega já feitas para este evento. |
lastAttempt | string (date-time) | Data/hora ISO 8601 UTC da última tentativa. |
description | string | Descrição legível do evento. |
requestPayload | object | Resumo do recurso que disparou o evento (id, amount em centavos, status). |
source | string | Origem do fato que gerou o evento (ex.: api). |
createdAt / updatedAt | string (date-time) | Criação e última atualização do registro, em UTC. |
dispatches | array | Tentativas de entrega aninhadas (ver abaixo). |
Campos do dispatch (dispatches[])
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID público do dispatch (wdi_…). |
status | string | Estado da tentativa (ex.: success). |
endpoint | string | URL de destino desta tentativa. |
attempts | integer | Tentativas registradas neste dispatch. |
lastAttemptAt | string (date-time) | Data/hora da última tentativa. |
successAt | string (date-time) | Quando a entrega foi confirmada; null enquanto não entregue. |
responseStatusCode | integer | Código HTTP devolvido pelo seu servidor. |
responseTime | integer | Tempo de resposta, em milissegundos. |
responseBody | string | Trecho do corpo de resposta do seu servidor (diagnóstico). |
correlationId | string | Identificador de correlação para rastreio entre sistemas. |
createdAt / updatedAt | string (date-time) | Criação e atualização do dispatch, em UTC. |
Convenções gerais (camelCase, dinheiro em centavos, datas ISO 8601 UTC, IDs opacos) estão em Convenções da API. A listagem é paginada por
offset/limit— ver Paginação.
Operações
| Operação | Método e caminho | Descrição |
|---|---|---|
| Listar eventos | GET /v1/webhooks/events | Lista eventos com seus dispatches; suporta filtros (status, tipo, recurso, intervalo de datas) e paginação. |
| Reenviar evento | POST /v1/webhooks/events/{eventId} | Solicita uma nova entrega de um evento específico (diagnóstico ou recuperação). |
Todas as chamadas usam a base https://api.selectwin.io/v1 e o cabeçalho de autenticação SelectKey (nunca Authorization: Bearer/Basic). Em produção a chave começa com sl_live_; em sandbox, com sl_test_. Veja Autenticação.
# Listar os eventos de transação aprovados mais recentes
curl "https://api.selectwin.io/v1/webhooks/events?type=transaction.approved&status=delivered&limit=20" \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"
# Reenviar um evento específico
curl -X POST https://api.selectwin.io/v1/webhooks/events/wbh_01hqzvabc \
-H "SelectKey: sl_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ"Nota
Na listagem, o filtro status aceita os valores de entrega delivered e failed. Não confunda com o campo status de cada dispatch (ex.: success), que descreve a tentativa individual.
Erros
A resposta de erro segue o envelope padrão com error.code estável — trate pelo code, nunca pela message (veja Tratamento de Erros). Códigos específicos de webhooks e os transversais mais comuns neste recurso:
error.code | HTTP | Quando ocorre |
|---|---|---|
invalidWebhookEventId / webhookEventIdInvalid | 400 | eventId (ou filtro eventid) com formato inválido. |
webhookDispatchIdInvalid | 400 | ID de dispatch inválido em filtros/consultas que o aceitam. |
eventTypeInvalid / webhookEventInvalid | 400 | Tipo de evento inválido (ex.: filtro type fora do catálogo). |
webhookEventsValidationFailed | 400 | Falha de validação dos eventos. |
invalidParameters | 400 | Parâmetro de query/caminho malformado (veja error.params). |
unauthorized | 401 | SelectKey ausente, inválida ou revogada. |
forbidden | 403 | Autenticado, mas sem permissão para o recurso. |
notFound | 404 | Evento (eventId) inexistente — comum no reenvio. |
unprocessableEntity | 422 | Regra de negócio impede a operação. |
tooManyRequests | 429 | Limite de requisições excedido — respeite error.retryAfterMinutes. |
serverError | 500 | Erro interno — repita com backoff. |
A lista completa por recurso está no Catálogo de Códigos de Erro.
Boas práticas
- Verifique a assinatura sempre. Cheque
X-Selectwin-Signature(HMAC-SHA256, comparação constant-time) antes de processar o payload — guia. - Responda
2xxrápido e processe depois. Devolva200em poucos milissegundos e empurre o trabalho pesado para uma fila assíncrona; lembre-se do limite de 15 s antes do timeout. - Seja idempotente no consumo. Como há retentativas, o mesmo evento pode chegar mais de uma vez. Use o
id(wbh_…) para deduplicar e evitar processar duas vezes. - Diagnostique falhas pelos dispatches. Use
responseStatusCode,responseTimeeresponseBodyde cada dispatch para entender por que uma entrega falhou antes de reenviar. - Não use polling para acompanhar estado. Reaja aos eventos; use a listagem para auditoria e recuperação, não como substituta dos webhooks (por quê).
- Reenvie com critério. Corrija a causa no seu endpoint antes de reenviar; reenviar contra um endpoint ainda quebrado só repete a falha.
- Filtre na listagem. Use
type,resource,resourceid,statuse os filtros de data (daterange*) para isolar o que importa em vez de paginar tudo.
Veja também
- Listar Eventos de Webhook — consulta, filtros e paginação.
- Reenviar Evento de Webhook — reentrega manual.
- Catálogo de Eventos de Webhook — todos os
typepor recurso. - Verificando Assinaturas de Webhook — validação HMAC com exemplos.
- Webhook Endpoints — onde você cadastra URLs e escolhe
events[]. - Convenções da API · Paginação · Por que não fazer polling
How is this guide?