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

# Escalera de integración

> Los 4 niveles para integrar Onflay — desde un link de pago sin código hasta un webhook opcional. Elige el menor nivel que te sirva y sube solo cuando lo necesites.

Onflay está diseñado como una **escalera de integración progresiva**. Elige el
nivel más bajo que encaje con tu producto y sube solo cuando lo necesites.
Cada nivel es production-ready; nunca estás forzado a subir al siguiente.

| Nivel | Qué                   | Código                              | Señal de confianza                |
| ----- | --------------------- | ----------------------------------- | --------------------------------- |
| 0     | Link de pago          | 0 líneas                            | Checkout hospedado por Onflay     |
| 1     | Checkout por catálogo | backend mínimo                      | Redirect a `checkoutUrl`          |
| 2     | Confirmar pago        | + poll de receipt o customer-access | `paid` / entitlements en servidor |
| 3     | Webhook opcional      | + `customer.access_changed`         | push en vez de poll               |

La historia de provisioning por defecto es `GET /v1/customer-access/{externalCustomerId}`
(+ `customer.access_changed` opcional). Los eventos `payment.completed` y
`subscription.*` existen para integraciones existentes pero son **Avanzado** —
ver [Customer access](/developers/customer-access).

## Nivel 0 — Link de pago (0 líneas)

**Quién:** creadores, MVPs, landing pages, link-in-bio.

**Flujo:**

1. Crea una oferta en el dashboard (sandbox o live).
2. Copia el **link de pago** desde la oferta / espacio.
3. Compártelo — el checkout hospedado de Onflay maneja el pago.

Los parámetros opcionales de UTM y prefill (`customer_email`, `customer_name`,
`discount_code`, `utm_*`, `reference_id`) están documentados en
[Link de pago](/developers/link-de-pago).

<Check>
  Cero código de backend. Onflay es el Merchant of Record, así que impuestos,
  reembolsos, disputas y pagos los manejamos por ti.
</Check>

## Nivel 1 — Checkout por catálogo (backend mínimo)

**Quién:** apps SaaS, proyectos en Lovable, cualquier backend.

**Flujo:**

1. `GET /v1/catalog/listings/{catalogKey}/recipe` — descubre claves estables,
   precios y entitlements.
2. `POST /v1/checkout-sessions` con `catalog` + `externalCustomerId` +
   `successUrl` / `cancelUrl` (+ header `Idempotency-Key`).
3. Redirige al comprador a `checkoutUrl`.

```http theme={"dark"}
GET /v1/catalog/listings/main-saas/recipe
Authorization: Bearer sk_test_...
```

```http theme={"dark"}
POST /v1/checkout-sessions
Authorization: Bearer sk_test_...
Content-Type: application/json
Idempotency-Key: checkout:user_123:main-saas:pro:monthly

{
  "catalog": { "listing": "main-saas", "plan": "pro", "interval": "month" },
  "externalCustomerId": "user_123",
  "email": "buyer@example.com",
  "successUrl": "https://app.example.com/billing/success",
  "cancelUrl": "https://app.example.com/pricing"
}
```

`interval` es opcional y por defecto es `month`. Renderiza los montos desde
`recipe.plans[].prices` — nunca hardcodees montos autoritativos.

Tras el pago, Onflay redirige a `successUrl` y **siempre añade** los query
params `checkout_id` y `return_token`. También puedes incluir
`{CHECKOUT_SESSION_ID}` en `successUrl` para plantillar path/query.

## Nivel 2 — Confirmar pago (default sin webhook)

**Quién:** igual que Nivel 1; requerido para confianza server-side.

**Nunca des acceso solo desde `successUrl`** — un comprador puede llegar ahí
por error o manipulando la URL. Elige una de dos rutas de confirmación
server-side.

### A. Poll de receipt (default para integraciones nuevas)

```http theme={"dark"}
GET /v1/checkout-sessions/{checkoutId}/receipt?returnToken=...
Authorization: Bearer sk_test_...
```

Haz poll hasta que el status sea `paid` | `failed` | `expired`
(`processing` significa sigue haciendo poll). Variante headless:
`?headless=true` con la secret key, sin return token.

### B. Poll de customer-access (con `externalCustomerId` conocido)

```http theme={"dark"}
GET /v1/customer-access/user_123
Authorization: Bearer sk_test_...
```

Devuelve un snapshot durable de autorización con `activePlans`,
`entitlements`, `credits` y `meters`. Usa `ETag` / `version` para detectar
cambios baratos. Ver [Customer access](/developers/customer-access) para el
shape completo y las reglas de status de suscripción.

<Check>
  El Nivel 2 es el default sin webhook. La mayoría de integradores se quedan acá.
</Check>

## Nivel 3 — Provisioning de producción (webhook opcional)

**Quién:** apps que quieren push en vez de poll.

**Flujo:**

1. Registra un webhook endpoint en el dashboard o vía
   `POST /v1/webhook-endpoints`.
2. Escucha `customer.access_changed` — un payload thin que solo dice "la
   versión del snapshot cambió".
3. Al recibir el evento → `GET /v1/customer-access/{externalCustomerId}` →
   actualiza tu DB local.

```http theme={"dark"}
POST /v1/webhook-endpoints
Authorization: Bearer sk_test_...
Content-Type: application/json

{
  "url": "https://app.example.com/api/webhooks/onflay",
  "events": ["customer.access_changed"]
}
```

Verifica la firma del webhook con el esquema HMAC de la referencia de
[Webhooks](/sdk/sdks/webhooks) — la matemática de verificación es estable
aun con el SDK congelado. Para dev local sin ngrok usa `onflay listen`
(herramienta de dev, no runtime).

### Avanzado: eventos de suscripción

`payment.completed`, `subscription.created`, `subscription.renewed`,
`subscription.cancel_scheduled`, `subscription.canceled`,
`subscription.updated`, `subscription.expired` y `subscription.dunning` existen
y siguen soportados para integraciones existentes. **No** son la ruta
recomendada para integradores nuevos — `customer.access_changed` +
customer-access cubre lo mismo con un evento y un endpoint. Usa eventos de
suscripción solo si necesitas contabilidad/analytics a nivel de período de
facturación que el snapshot no expone.

## Elige tu nivel

<CardGroup cols={2}>
  <Card title="Links de pago (Nivel 0)" icon="link" href="/developers/link-de-pago">Cero código.</Card>
  <Card title="Inicio rápido (Nivel 1 + 2)" icon="rocket" href="/developers/inicio-rapido">5 minutos con curl + fetch.</Card>
  <Card title="Customer access (Nivel 2 + 3)" icon="key" href="/developers/customer-access">El endpoint default de provisioning.</Card>
  <Card title="Referencia API" icon="code" href="/api-reference/openapi">OpenAPI con copy-as-curl.</Card>
</CardGroup>
