Skip to main content
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. 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. 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.
Cero código de backend. Onflay es el Merchant of Record, así que impuestos, reembolsos, disputas y pagos los manejamos por ti.

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.
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)

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)

Devuelve un snapshot durable de autorización con activePlans, entitlements, credits y meters. Usa ETag / version para detectar cambios baratos. Ver Customer access para el shape completo y las reglas de status de suscripción.
El Nivel 2 es el default sin webhook. La mayoría de integradores se quedan acá.

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.
Verifica la firma del webhook con el esquema HMAC de la referencia de 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

Links de pago (Nivel 0)

Cero código.

Inicio rápido (Nivel 1 + 2)

5 minutos con curl + fetch.

Customer access (Nivel 2 + 3)

El endpoint default de provisioning.

Referencia API

OpenAPI con copy-as-curl.