# Webhooks

Receba um POST assinado no seu servidor sempre que uma ordem ou um reembolso mudar. Assim você não precisa consultar a API a cada poucos segundos.

- [Gerenciar webhooks no painel](https://bytemax.exchange/pt-BR/webhooks)
- [Baixar OpenAPI 3.1](https://bytemax.exchange/api-v1.openapi.json)
- [Página da documentação](https://bytemax.exchange/pt-BR/docs/webhooks)

## Como funciona

1. **Cadastre o webhook**
   No [painel de webhooks](https://bytemax.exchange/pt-BR/webhooks) ou por `POST /webhooks`, com a URL HTTPS do seu servidor e os eventos que quer receber.

2. **Guarde o segredo de assinatura**
   Ele vem na resposta da criação, no formato `whsec_…`, e pode ser consultado de novo com `GET /webhooks/{id}?include_signing_secret=true`. Não há como gerar outro: se vazar, exclua o webhook e crie um novo. Não confunda com a chave de API.

3. **Receba o POST**
   Cada evento chega com os cabeçalhos `svix-id`, `svix-timestamp` e `svix-signature` e o evento em JSON no corpo.

4. **Valide, grave e responda 2xx**
   Confira a assinatura, grave o evento e só então responda. Qualquer resposta fora de 2xx gera novas tentativas.

## Eventos

| Evento | Quando é enviado |
| --- | --- |
| `order.created` | Ordem criada, com valores definitivos e link de pagamento. |
| `order.updated` | A ordem mudou: estado, valor reembolsado ou valor retido. |
| `refund.created` | Reembolso registrado. |
| `refund.updated` | O reembolso mudou de estado. |
| `webhook.test` | Evento de teste, enviado só para o webhook que você testou. |

`data` traz a ordem ou o reembolso completo, no mesmo formato das consultas. `version` aumenta a cada mudança.

**Exemplo: order.created**

```json
{
  "id": "evt_example",
  "type": "order.created",
  "api_version": "v1",
  "occurred_at": "2026-09-10T13:05:00.000Z",
  "data": {
    "id": "ord_example",
    "version": "1",
    "status": "pending_payment",
    "source_currency": "BRL",
    "source_amount_atomic": "10000",
    "target_currency": "CNY",
    "target_amount_atomic": "12500000000",
    "refunded_source_amount_atomic": "0",
    "blocked_source_amount_atomic": "0",
    "payment": {
      "url": "https://bytemax.exchange/pay/example",
      "pix_copy_paste": null
    },
    "created_at": "2026-09-10T13:05:00.000Z"
  }
}
```

## Receber e verificar

Valide com o segredo e o corpo bruto da requisição, antes de interpretar o JSON. Use a biblioteca oficial do Svix na sua linguagem: ela confere a assinatura e a tolerância de tempo do `svix-timestamp`. Não implemente a verificação à mão.

[Como verificar assinaturas com a biblioteca oficial (docs.svix.com)](https://docs.svix.com/receiving/verifying-payloads/how)

**O que chega no seu servidor**

```http
POST /webhooks/bytemax HTTP/1.1
Content-Type: application/json
svix-id: msg_2gkQ7Wc9cD6yYq1xkKz7GJb3wQm
svix-timestamp: 1757509500
svix-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhUjM8G3xRk2w1vNq4T0=

{ "id": "evt_example", "type": "order.updated", ... }
```

## Processar sem duplicar

Eventos podem chegar mais de uma vez e fora de ordem. Cinco regras evitam efeitos duplicados:

- Use o `id` do evento como chave única: grave antes de responder e ignore repetidos.
- Compare `version` da ordem ou do reembolso: um evento com versão menor que a já gravada não substitui o estado mais novo.
- Grave o efeito do evento e a marca de processado na mesma transação.
- Responda 2xx só depois de gravar. Se a gravação falhar, responda 5xx para receber de novo.
- Trabalho demorado fica fora da resposta: enfileire e responda rápido.

## Testar e reenviar

`POST /webhooks/{id}/test-events`, sem corpo, envia um `webhook.test` para esse webhook. Acompanhe a publicação em `GET /events/{id}` e confira no seu servidor se o evento chegou e a assinatura foi aceita. O teste comprova a entrega e a assinatura; para testar o tratamento de ordens e reembolsos, acompanhe uma ordem real.

Entregas que falham recebem novas tentativas automáticas. O histórico de cada tentativa fica no painel e em `GET /webhooks/{id}/deliveries`. Para reenviar eventos específicos, use `POST /webhooks/{id}/redeliveries` com até 20 ids: a resposta diz, evento por evento, se o reenvio foi aceito.

## Limites

- Até 200 webhooks por conta, um por URL.
- Eventos ficam consultáveis por 30 dias.
- Listas usam `items` e `next_cursor`: 30 por página, no máximo 100.
- Exportação de entregas até 1.000 tentativas; `truncated` avisa quando há mais.
- Estatísticas de entregas por até 28 dias.

## Referência

Doze operações, todas com `Authorization: Bearer <API_KEY>`. As três mais usadas aparecem completas; as demais seguem o mesmo formato.

### Criar webhook

`POST /webhooks`

Cria o webhook e devolve o segredo de assinatura.

**Requisição**

```bash
curl --request POST "https://bytemax.exchange/api/v1/webhooks" \
  --header "Authorization: Bearer <API_KEY>" \
  --header "Content-Type: application/json" \
  --data '{"url":"https://merchant.example/webhooks/bytemax","events":["order.created","order.updated","refund.created","refund.updated"],"enabled":true}'
```

**Resposta 201**

```json
{
  "id": "ep_example",
  "url": "https://merchant.example/webhooks/bytemax",
  "events": [
    "order.created",
    "order.updated",
    "refund.created",
    "refund.updated"
  ],
  "enabled": true,
  "api_version": "v1",
  "signing_secret": "<WEBHOOK_SIGNING_SECRET>"
}
```

### Enviar teste

`POST /webhooks/{id}/test-events`

Envia um `webhook.test` para este webhook. Sem corpo.

| Parâmetro | Onde | Obrigatório |
| --- | --- | --- |
| `id` | caminho | Sim |

**Requisição**

```bash
curl --request POST "https://bytemax.exchange/api/v1/webhooks/ep_example/test-events" \
  --header "Authorization: Bearer <API_KEY>"
```

**Resposta 202**

```json
{
  "id": "evt_test_example",
  "type": "webhook.test",
  "api_version": "v1",
  "occurred_at": "2026-09-10T13:05:00.000Z",
  "data": {
    "message": "ByteMax webhook test."
  },
  "publication_status": "pending"
}
```

### Reenviar eventos

`POST /webhooks/{id}/redeliveries`

Reenvia até 20 eventos para este webhook. A resposta traz o resultado de cada um.

| Parâmetro | Onde | Obrigatório |
| --- | --- | --- |
| `id` | caminho | Sim |

**Requisição**

```bash
curl --request POST "https://bytemax.exchange/api/v1/webhooks/ep_example/redeliveries" \
  --header "Authorization: Bearer <API_KEY>" \
  --header "Content-Type: application/json" \
  --data '{"event_ids":["evt_example"]}'
```

**Resposta 200**

```json
{
  "items": [
    {
      "event_id": "evt_example",
      "status": "queued"
    }
  ]
}
```

### Outras operações

| Operação | Nome | O que faz |
| --- | --- | --- |
| `GET /webhooks` | Listar webhooks | Todos os webhooks da conta. |
| `GET /webhooks/{id}` | Consultar webhook | Um webhook. Com `include_signing_secret=true`, inclui o segredo de assinatura. |
| `PATCH /webhooks/{id}` | Alterar webhook | URL, eventos ou ativação. |
| `DELETE /webhooks/{id}` | Excluir webhook | Exclui o webhook. |
| `GET /events` | Listar eventos | Eventos dos últimos 30 dias e seu estado de publicação. |
| `GET /events/{id}` | Consultar evento | Um evento e seu estado de publicação. |
| `GET /webhooks/{id}/deliveries` | Listar entregas | Tentativas de entrega de um webhook, com filtros por estado e tipo. |
| `GET /webhooks/{id}/deliveries/export` | Exportar entregas | Até 1.000 tentativas; `truncated` avisa quando há mais. |
| `GET /webhooks/statistics` | Estatísticas | Sucessos e falhas por até 28 dias. |
