> ## Documentation Index
> Fetch the complete documentation index at: https://docs.weve.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook genérico

> O envelope para plataformas sem integração nativa: gateways, áreas de membros, Zapier, Make, n8n.

Hotmart, Kiwify, Eduzz e Digital Manager Guru têm integração nativa. Qualquer outra ferramenta que saiba mandar um
`POST` HTTP entra pelo **webhook genérico**: o gestor liga a plataforma no club com
`platform: "webhook"`, recebe a URL e cadastra um segredo; a ferramenta manda o envelope
abaixo com esse segredo no cabeçalho.

```http theme={null}
POST https://api.weve.cx/webhooks/webhook/{token}
Content-Type: application/json
Authorization: Bearer {segredo}
```

A resposta é `202` assim que o evento é gravado — o processamento acontece depois, e é por
isso que reenviar é sempre seguro. `401` é segredo errado; `404` é URL desconhecida ou
conexão desligada. Em `5xx`, reenvie.

## Eventos

| `event`                 | O que acontece                                                                        |
| ----------------------- | ------------------------------------------------------------------------------------- |
| `purchase.completed`    | Concede acesso ao que o produto abre                                                  |
| `subscription.renewed`  | Estende o acesso até `subscription.expires_at`                                        |
| `purchase.refunded`     | Revoga o acesso daquela transação                                                     |
| `purchase.chargeback`   | Revoga, registrando como contestação                                                  |
| `subscription.canceled` | Mantém o acesso até `subscription.expires_at` e encerra ali; sem a data, revoga agora |

Qualquer outro valor é gravado e ignorado.

## Envelope

```json theme={null}
{
  "event": "purchase.completed",
  "transaction_id": "abc-123",
  "amount": 19700,
  "currency": "BRL",
  "paid_at": "2026-09-10T12:00:00Z",
  "customer": {
    "id": "cus_9",
    "name": "Maria Silva",
    "email": "maria@example.com",
    "phone": "11999999999",
    "document": "12345678900"
  },
  "product": {
    "external_id": "PROD-001",
    "offer_id": "anual",
    "name": "Curso de Marketing"
  },
  "subscription": {
    "id": "sub_42",
    "expires_at": "2026-12-01T00:00:00Z"
  }
}
```

| Campo                     | Obrigatório    | Notas                                                                                                                                                 |
| ------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event`                   | sim            | Um dos valores da tabela acima                                                                                                                        |
| `transaction_id`          | sim            | Identifica a **venda**. É a chave de idempotência: o mesmo id nunca concede duas vezes, e é por ele que um reembolso encontra a compra                |
| `customer.email`          | sim            | Encontra ou cria o aluno no club. A conta nasce sem senha e recebe o link de acesso por e-mail                                                        |
| `customer.id`             | recomendado    | Seu id do comprador. Usado para achar a compra num reembolso que não cite a transação                                                                 |
| `customer.name`           | recomendado    | Usado ao criar a conta                                                                                                                                |
| `product.external_id`     | sim            | Seu id do produto. O gestor o mapeia para um produto do club; compra que chegar antes do mapeamento fica registrada e ganha acesso quando ele existir |
| `product.offer_id`        | opcional       | Distingue ofertas do mesmo produto (prazos diferentes)                                                                                                |
| `amount`                  | opcional       | **Centavos inteiros** (`19700` é R\$ 197,00)                                                                                                          |
| `currency`                | opcional       | ISO 4217; padrão `BRL`                                                                                                                                |
| `paid_at`                 | opcional       | RFC 3339; sem ele, vale o momento em que o evento chegou                                                                                              |
| `subscription.id`         | em recorrência | Presente, a venda é assinatura: renovações chegam como `subscription.renewed` com este mesmo id                                                       |
| `subscription.expires_at` | em recorrência | Até quando o período pago vale. É daqui que sai o prazo do acesso                                                                                     |

<Warning>
  O `amount` é em **centavos inteiros**, diferente da versão anterior da API, que aceitava
  decimal em reais. Um valor com casa decimal é gravado como "sem valor" — a venda entra, o
  número não.
</Warning>

## Idempotência e ordem

Reenvie à vontade. O mesmo corpo é reconhecido e respondido com `202` sem gravar de novo;
um corpo diferente com a mesma `transaction_id` é gravado e não concede nada a mais. Um
reembolso que chegue antes da compra fica à espera e é aplicado quando ela chegar.


## Related topics

- [Receber evento de plataforma](/api-reference/webhooks/receive.md)
- [Ligar plataforma](/api-reference/webhooks/connections-create.md)
- [Mapear id de plataforma](/api-reference/catalog/products-external-id.md)
- [Criar produto](/api-reference/catalog/products-create.md)
- [Listar conexões](/api-reference/webhooks/connections-list.md)
