# Introdução aos webhooks

A cobrança acontece do lado da Quyta: a régua dispara mensagens, o devedor negocia, fecha
um acordo, paga uma parcela. Nada disso parte de uma chamada do seu sistema — e por isso
seu sistema não teria como saber que aconteceu.

Os webhooks resolvem isso. Você registra uma URL, e a Quyta faz um `POST` nela sempre que
um evento relevante ocorre.

<Mermaid chart={`
sequenceDiagram
  participant D as Devedor
  participant Q as Quyta
  participant S as Seu sistema
  D->>Q: Negocia e fecha acordo
  Q-->>S: POST /webhook — contract.created
  S-->>Q: 200 OK
  D->>Q: Paga a 1ª parcela
  Q-->>S: POST /webhook — contract.installment.paid
  S-->>Q: 200 OK
  Note over S: Baixa no ERP
`} />

## Por que não consultar em laço

A alternativa seria varrer `GET /debts` de tempos em tempos procurando mudanças. Isso
funciona mal por três motivos: consome o limite de requisições, atrasa a informação em até
um ciclo inteiro de consulta, e piora conforme a carteira cresce.

Com webhook a informação chega em segundos e o custo não cresce com o tamanho da carteira,
e sim com o número de eventos — que é exatamente o que você precisa processar de qualquer
forma.

## Configurando um endpoint

As assinaturas de webhook são gerenciadas **no painel da Quyta**. Ao criar uma, você
define:

1. **A URL** que vai receber os `POST`. Precisa ser HTTPS e acessível publicamente.
2. **Os tipos de evento** que quer receber — veja o [catálogo completo](/webhooks/eventos).
3. **Um segredo**, usado para assinar cada entrega. É opcional, mas
   [recomendado](/webhooks/seguranca).

O painel também mostra o histórico de entregas de cada assinatura, com o código de
resposta que o seu endpoint devolveu — o primeiro lugar a olhar quando algo não chega.

## O que o seu endpoint precisa fazer

Quatro requisitos, em ordem de importância:

**Responder 2xx rapidamente.** Qualquer status entre 200 e 299 marca a entrega como
bem-sucedida. Qualquer outra coisa — ou um timeout — é tratada como falha e entra em
retentativa.

**Não processar de forma síncrona.** Valide a assinatura, grave o evento numa fila e
responda. Se você processar tudo antes de responder, uma lentidão no seu banco vira
timeout de webhook.

**Verificar a assinatura** antes de confiar no conteúdo. Veja
[Segurança](/webhooks/seguranca).

**Tolerar repetições.** Uma retentativa pode entregar duas vezes o mesmo evento. Use o
campo `id` do payload para descartar duplicatas.

## O formato do evento

Todo webhook chega com o mesmo payload:

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "debt.created",
  "version": "1",
  "created_at": "2026-08-27T10:30:00Z",
  "data": { }
}
```

| Campo | Descrição |
| --- | --- |
| `id` | UUID único do evento. Use-o para deduplicação. |
| `type` | O tipo do evento — determina o formato de `data`. |
| `version` | Versão do formato do evento. Hoje sempre `"1"`. |
| `created_at` | Quando o evento ocorreu, em ISO 8601. |
| `data` | O conteúdo, específico de cada tipo de evento. |

Ramifique o seu processamento por `type` e leia `data` conforme o
[catálogo de eventos](/webhooks/eventos).

## Um receptor mínimo

```javascript
import express from "express";

const app = express();

// Guarde o corpo bruto: a assinatura é calculada sobre ele.
app.post(
  "/webhooks/quyta",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    if (!assinaturaValida(req.body, req.get("Quyta-Webhook-Signature"))) {
      return res.sendStatus(401);
    }

    const evento = JSON.parse(req.body.toString("utf8"));

    // Responda primeiro; processe depois.
    res.sendStatus(200);

    await fila.publicar(evento);
  },
);

app.listen(3000);
```

A implementação de `assinaturaValida` está em [Segurança](/webhooks/seguranca).

## Próximos passos

- [Catálogo de eventos](/webhooks/eventos) — os dez eventos e o que cada um significa.
- [Entrega e retentativas](/webhooks/entrega) — headers, timeout e política de reenvio.
- [Segurança](/webhooks/seguranca) — validação da assinatura HMAC.
