## Objetivo

Garantizar que los eventos Stripe llegan a Beacon con validación criptográfica, deduplicación y replay seguro.

## Procedimiento recomendado

<Steps>
  <Step title="1) Definir endpoint estable">Usa el endpoint canónico de Beacon sin redirects y con el `org` correcto en la query.</Step>
  <Step title="2) Guardar el signing secret">Guarda el secreto en el gestor de secretos, nunca en código.</Step>
  <Step title="3) Validar eventos obligatorios">Confirma que Stripe envía los eventos mínimos de checkout y suscripción que Beacon espera.</Step>
  <Step title="4) Configurar replay seguro">Mantén replay manual por `webhookEventId` y trazabilidad por evento.</Step>
</Steps>

<Tip title="Buena práctica">Activa alertas para backlog de eventos por organización y errores de firma consecutivos.</Tip>

## Endpoints canónicos por entorno

- General `test`: `https://test.beacon.pt/api/webhooks/stripe?org=<organization_slug>&mode=test`
- General `live`: `https://app.beacon.pt/api/webhooks/stripe?org=<organization_slug>&mode=live`
- Endpoint dedicado de billing: misma convención en `/api/webhooks/stripe/billing`

## Ejemplo mínimo de validación

<Tabs>
  <Tab label="curl">
    ```bash
curl -X POST "https://test.beacon.pt/api/webhooks/stripe?org=acme&mode=test" \
  -H "Content-Type: application/json" \
  -H "Stripe-Signature: t=1710492000,v1=<firma_real>" \
  -d '{"id":"evt_123","type":"checkout.session.completed"}'
```
  </Tab>
  <Tab label="node">
    ```ts
const signature = request.headers.get("stripe-signature");
const payload = await request.text();
const event = stripe.webhooks.constructEvent(payload, signature ?? "", process.env.STRIPE_WEBHOOK_SECRET!);
await processEvent(event);
```
  </Tab>
</Tabs>

## Criterios de listo

- Tasa de error por debajo de 1% cada 15 minutos.
- Reprocesamiento disponible por `webhookEventId`.
- Logs con correlación entre evento, organización y pipeline fiscal.
