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

# Webhooks

> Assine eventos da VMArea e receba notificações HTTP POST em tempo real no seu próprio endpoint HTTPS.

Webhooks permitem que você assine eventos da VMArea e receba notificações HTTP POST em tempo real no seu próprio endpoint HTTPS. Requer o escopo `webhooks:write` para gerenciar assinaturas e `webhooks:read` para listá-las.

## Criando uma assinatura

Crie uma assinatura de webhook com `POST /webhooks`:

```bash theme={null}
curl -X POST https://api.vmarea.com/api/public/v1/webhooks \
  -H "x-api-key: $VMAREA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.example.com/hooks/vmarea",
    "events": ["vm.created", "vm.started", "billing.payment_received"],
    "description": "Production listener"
  }'
```

A resposta inclui um campo `secret` — **copie-o imediatamente**, ele é exibido apenas uma vez. Você usará esse segredo para verificar as requisições recebidas.

Os URLs de endpoint devem usar HTTPS. Cada conta pode ter até 10 assinaturas de webhook ativas.

## Tipos de evento

| Evento                     | Descrição                                                                                |
| -------------------------- | ---------------------------------------------------------------------------------------- |
| `vm.created`               | Uma VM concluiu o provisionamento.                                                       |
| `vm.started`               | Uma VM foi iniciada.                                                                     |
| `vm.stopped`               | Uma VM foi parada.                                                                       |
| `vm.restarted`             | Uma VM foi reiniciada.                                                                   |
| `vm.suspended`             | Uma VM foi suspensa (ex.: por inadimplência).                                            |
| `vm.terminated`            | Uma VM foi excluída permanentemente.                                                     |
| `vm.renewed`               | O ciclo de faturamento de uma VM foi renovado.                                           |
| `billing.payment_received` | Uma recarga da carteira foi processada com sucesso.                                      |
| `billing.low_balance`      | O saldo da carteira caiu abaixo do mínimo necessário para cobrir as próximas renovações. |
| `ticket.reply`             | Um ticket de suporte recebeu uma nova resposta.                                          |

## Verificação de assinatura

Toda entrega inclui uma assinatura HMAC-SHA256 para que você possa confirmar que a requisição veio da VMArea.

**Cabeçalhos enviados em cada entrega:**

| Cabeçalho              | Valor                                                                             |
| ---------------------- | --------------------------------------------------------------------------------- |
| `X-VMArea-Event`       | O tipo de evento (ex.: `vm.started`).                                             |
| `X-VMArea-Signature`   | `sha256=<hex-digest>` do corpo JSON bruto, assinado com o segredo do seu webhook. |
| `X-VMArea-Delivery-Id` | Um ID único para esta tentativa de entrega.                                       |

**Exemplo de verificação:**

```js theme={null}
import crypto from "node:crypto";

function verifySignature(rawBody, signatureHeader, secret) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

// Exemplo com Express
app.post("/hooks/vmarea", express.raw({ type: "application/json" }), (req, res) => {
  const sig = req.headers["x-vmarea-signature"];
  if (!verifySignature(req.body, sig, process.env.VMAREA_WEBHOOK_SECRET)) {
    return res.status(401).send("Invalid signature");
  }
  const event = req.headers["x-vmarea-event"];
  const payload = JSON.parse(req.body);
  // trate o evento ...
  res.status(200).send("ok");
});
```

<Warning>
  Sempre use `crypto.timingSafeEqual` (ou equivalente) para evitar ataques de timing.
</Warning>

## Semântica de retentativa

Se seu endpoint não retornar uma resposta `2xx` em 15 segundos, a VMArea tenta a entrega novamente até **3 tentativas no total** com backoff exponencial (atraso inicial de 10 segundos, dobrando a cada tentativa).

Após **50 falhas consecutivas de entrega** em todos os eventos, a assinatura de webhook é desativada automaticamente. Você pode reativá-la pelo painel ou via `PATCH /webhooks/:id` com `{ "isActive": true }`.

O histórico de entregas (código de status, flag de sucesso, contagem de tentativas) está disponível em `GET /webhooks/:id/deliveries`.

## Boas práticas

* **Responda rapidamente.** Retorne `2xx` antes de qualquer processamento pesado — delegue o trabalho a uma fila para não atingir o timeout de 15 segundos.
* **Torne os handlers idempotentes.** O mesmo evento pode ser entregue mais de uma vez (ex.: após uma retentativa). Use `X-VMArea-Delivery-Id` para deduplicar.
* **Sempre verifique a assinatura.** Não confie no payload sem validar o HMAC.
* **Use um endpoint dedicado** por ambiente (produção, staging) para inspecionar e reproduzir eventos de forma independente.
