## Objetivo

Ingerir eventos Stripe com validação criptográfica, deduplicação por evento e capacidade de replay controlado para recuperação operacional.

## Endpoints principais

| Endpoint | Utilização | Segurança |
| --- | --- | --- |
| `POST /api/webhooks/stripe?org={slug}&mode={test\|live}` | eventos Stripe gerais e deduplicação técnica | assinatura Stripe obrigatória |
| `POST /api/webhooks/stripe/billing?org={slug}&mode={test\|live}` | eventos dedicados a billing/subscrições | assinatura Stripe obrigatória |
| `POST /api/billing/webhooks/{webhookEventId}/replay?org={slug}&mode={test\|live}` | replay manual de um webhook já persistido | Bearer token Beacon + `OWNER`/`ADMIN` |

## Modelo de processamento

<Steps>
  <Step title="1) Receber evento">Validar assinatura e formato mínimo do payload.</Step>
  <Step title="2) Deduplicar">Usar `event.id` como chave lógica de deduplicação; duplicados devolvem `duplicate: true`.</Step>
  <Step title="3) Persistir e processar">Guardar `webhookEventId` interno e executar o pipeline assíncrono.</Step>
  <Step title="4) Confirmar estado">Atualizar estado funcional e métricas de entrega; billing pode upsertar subscrições.</Step>
</Steps>

## URLs canónicas por ambiente

- `test`: `https://test.beacon.pt/api/webhooks/stripe?org=<organization_slug>&mode=test`
- `live`: `https://app.beacon.pt/api/webhooks/stripe?org=<organization_slug>&mode=live`
- Se usares o endpoint dedicado de billing, mantém a mesma convenção em `/api/webhooks/stripe/billing`.

## Política de retries e replay

- Retries automáticos devem manter contexto original do evento.
- Replay manual usa o identificador interno `webhookEventId`, não o `event.id` da Stripe.
- Nunca executar replay massivo sem priorização por impacto e sem janela de controlo.

## Exemplo de resposta do endpoint geral

```json
{
  "ok": true,
  "webhookEventId": "whevt_123",
  "eventId": "evt_123",
  "mode": "test",
  "duplicate": false
}
```

## Exemplo de replay manual

```bash
curl -X POST "https://test.beacon.pt/api/billing/webhooks/whevt_123/replay?org=acme&mode=test" \
  -H "Authorization: Bearer <beacon_session_token>"
```

```json
{
  "ok": true,
  "webhookEventId": "whevt_123",
  "queueJobId": "job_123",
  "replayScheduled": true,
  "context": {
    "mode": "test",
    "organizationSlug": "acme"
  }
}
```

## Erros e sinais operacionais

| Sinal | Significado | Ação |
| --- | --- | --- |
| aumento de `4xx` | falha de assinatura/payload | rever segredo e contrato do endpoint |
| backlog crescente | consumer lento ou bloqueado | aumentar capacidade, priorizar eventos críticos |
| duplicados processados | deduplicação incompleta | reforçar correlação por `event.id` e rever persistência do `webhookEventId` |

<Warning title="Replay">Replay deve ser auditável e reversível; evita operações amplas sem runbook de validação.</Warning>
