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

# Eventos

> Catalogo de eventos webhook recomendados para Bookable Payments, pagos, productos, customers y booking event types.

Suscribete solo a los eventos que tu integracion necesita, pero procesa cada evento de forma idempotente.

## Bookable minimo

Para una integracion Scheduled Offer minima:

| Evento                 | Cuando ocurre                    | Accion recomendada                            |
| ---------------------- | -------------------------------- | --------------------------------------------- |
| `booking.hold_created` | SimplePay creo un hold.          | Guarda hold y expiracion si tu UI lo muestra. |
| `booking.confirmed`    | El pago confirmo la reserva.     | Entrega voucher, acceso o confirmacion final. |
| `booking.expired`      | Checkout o hold expiro.          | Libera seleccion local e invita a reintentar. |
| `booking.cancelled`    | Pago fallo o se cancelo booking. | No entregues acceso.                          |

## Bookable completo

Para una plataforma madura:

```txt events theme={"theme":{"light":"github-light","dark":"github-dark"}}
booking.hold_created
booking.hold_released
booking.confirmed
booking.expired
booking.cancelled
booking.rescheduled
booking.refunded
booking.partially_refunded
booking.no_show
product.updated
customer.updated
booking_event_type.updated
```

## Contrato de estados

| Estado SimplePay      | Booking     | Hold        | Payment status | Accion merchant      |
| --------------------- | ----------- | ----------- | -------------- | -------------------- |
| Checkout completado   | `confirmed` | `converted` | `paid`         | Confirma acceso.     |
| Checkout expirado     | `expired`   | `expired`   | `unpaid`       | Libera UI local.     |
| Pago asincrono falló  | `cancelled` | `released`  | `failed`       | Requiere nuevo pago. |
| PaymentIntent fallido | `cancelled` | `released`  | `failed`       | Requiere nuevo pago. |

Tu plataforma recibe eventos SimplePay como `booking.confirmed`; usa esos eventos como contrato publico de integracion.

## Campos que conviene persistir

Para Bookable:

* `event.id`
* `event.type`
* `booking.id`
* `booking.status`
* `booking.paymentStatus`
* `booking.eventTypeId`
* `booking.productId`
* `booking.resourceId`
* `booking.tenantCustomerId`
* `booking.startsAt`
* `booking.endsAt`
* `booking.quantity`
* `booking.amountMinor`
* `booking.currency`
* `booking.simplepayCheckoutSessionId`
* `booking.simplepayCheckoutSessionId`

Para pagos simples:

* `event.id`
* `event.type`
* Checkout Session ID `spcs_...`
* Payment Link ID `splink_...`, si aplica
* PaymentIntent ID `sppi_...`, si aplica
* `client_reference_id`
* `metadata.order_id` o equivalente
* amount y currency esperados

<Danger>
  No persistas secretos ni credenciales en tus tablas de eventos. Guarda
  referencias, estados y snapshots no sensibles.
</Danger>

## Deduplicacion

Tu tabla de eventos deberia tener una llave unica por `event.id`.

```sql schema.sql theme={"theme":{"light":"github-light","dark":"github-dark"}}
create table simplepay_webhook_events (
  id text primary key,
  type text not null,
  received_at timestamptz not null default now(),
  processed_at timestamptz,
  payload jsonb not null
);
```

En el handler:

```ts dedupe.ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
async function handleEvent(event: SimplePayEvent) {
  const inserted = await insertEventIfNew(event.id, event.type, event);

  if (!inserted) {
    return { duplicate: true };
  }

  switch (event.type) {
    case "booking.confirmed":
      await confirmBooking(event.data.booking);
      break;
    case "booking.expired":
    case "booking.cancelled":
      await releaseBooking(event.data.booking);
      break;
    default:
      await recordUnhandledEvent(event);
  }
}
```

## Replays

Los replays vuelven a entregar un evento existente. Por eso tu handler debe ser idempotente antes de depender de replays como herramienta operacional.
