La facturación por uso te permite cobrar al final de un período de facturación en lugar de a un precio fijo.
Onflay soporta dos modelos complementarios que puedes usar por separado o en conjunto.
Modelos disponibles
| Modelo | Cómo funciona | Ideal para |
|---|
| Push del desarrollador (Modelo A) | Tu plataforma calcula el consumo y el importe total. Llamas a onflay.invoices.create() y Onflay cobra la tarjeta automáticamente. | APIs de IA, cómputo, métricas propias |
| Medición de Onflay (Modelo B) | Defines un Meter y un precio USAGE_BASED o TIERED. Reportas eventos con onflay.usage.report(). Onflay agrega y factura al cierre del período. | Llamadas a API, almacenamiento en GB, billing por asientos |
Requisito previo: colectar un método de pago
Para poder cobrar automáticamente, el cliente final debe tener una tarjeta guardada.
Crea el cliente
import { Onflay } from '@onflay/node';
const onflay = new Onflay(process.env.ONFLAY_API_KEY!);
const customer = await onflay.customers.create({
email: 'alice@ejemplo.com',
displayName: 'Alice Smith',
});
Genera la página de tarjeta
const session = await onflay.invoices.createSetupIntent(customer.id, {
returnUrl: 'https://tu-app.com/billing/listo',
});
// Redirige al cliente — ingresará su tarjeta en la página hospedada
redirect(session.hostedUrl);
Una vez que el cliente completa el formulario, Onflay registra la tarjeta como método de pago predeterminado para cobros futuros.Si prefieres insertar Stripe Elements en tu propia UI, usa session.clientSecret directamente con stripe.confirmSetup().
Modelo A — Push del desarrollador
Tu plataforma calcula el importe. Cuando quieras cobrar, envías las líneas a Onflay.
const invoice = await onflay.invoices.create(
{
customerId: customer.id,
currency: 'usd',
lineItems: [
{
description: 'Tokens GPT-4o — junio 2026',
amountInCents: 3250, // $32.50
},
{
description: 'Generaciones de imagen — junio 2026',
amountInCents: 1700, // $17.00
},
],
// Informativo — queda guardado en la factura para auditoría
periodStart: '2026-06-01',
periodEnd: '2026-07-01',
},
{ idempotencyKey: `billing-junio-2026-${customer.id}` },
);
console.log(invoice.status); // 'paid' | 'open' | 'failed'
Onflay crea un ítem de factura por cada línea, finaliza la factura en Stripe y cobra la tarjeta guardada con collection_method: 'charge_automatically'.
Recibirás los webhooks invoice.created, invoice.finalized, invoice.paid (o invoice.payment_failed) en tu endpoint registrado.
Si el cliente no tiene una tarjeta guardada, la API devuelve 400 con el mensaje “Customer does not have a saved payment method”. Completa el flujo de SetupIntent primero.
Modelo B — Medición de Onflay
1. Crea un metro
const meter = await onflay.usage.createMeter({
name: 'Llamadas a la API',
eventName: 'api_call',
aggregation: 'SUM', // o MAX, LAST
});
2. Crea un precio por uso en un producto
const producto = await onflay.products.create({
name: 'API para Desarrolladores',
type: 'SERVICE',
});
const precio = await onflay.prices.create({
productId: producto.id,
billingScheme: 'usage_based',
currency: 'usd',
tiersMode: 'graduated',
tiers: [
{ upTo: 100_000, unitAmountInCents: 0 }, // primeras 100k llamadas gratis
{ upTo: null, unitAmountInCents: 1 }, // $0.01 por llamada adicional
],
recurring: { interval: 'month' },
});
3. Adjunta un plan de facturación a la suscripción
Después de que el cliente se suscriba vía checkout, adjunta un UsageBillingPlan para que el scheduler sepa cuándo y cómo facturar:
// POST /v1/usage/billing-plans
await fetch(`${baseUrl}/v1/usage/billing-plans`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
subscriptionId: suscripcion.id,
meterId: meter.id,
priceId: precio.id,
billingInterval: 'month',
}),
});
4. Reporta consumo
// Llama esto cada vez que ocurre un evento en tu plataforma
await onflay.usage.report({
subscriptionId: suscripcion.id,
meter: 'api_call',
quantity: 1,
idempotencyKey: crypto.randomUUID(),
});
Los eventos se almacenan en Redis y se persisten en la base de datos cada minuto. Al cierre de cada período, Onflay agrega los registros de uso, aplica el precio escalonado y crea la factura en Stripe automáticamente.
Webhooks de facturación
Suscríbete a los eventos de facturación desde el dashboard de webhooks o vía SDK:
await onflay.webhookEndpoints.create({
url: 'https://tu-app.com/webhooks/onflay',
events: ['invoice.*'],
// o explícito: ['invoice.paid', 'invoice.payment_failed']
});
Manejo de eventos
import { createNextWebhookHandler } from '@onflay/webhooks/next';
export const POST = createNextWebhookHandler({
secret: process.env.ONFLAY_WEBHOOK_SECRET!,
onEvent: async (event) => {
switch (event.type) {
case 'invoice.paid': {
const { customerId, totalInCents, currency, periodStart, periodEnd } = event.data;
// Activa acceso, registra el cobro en tu base de datos, etc.
break;
}
case 'invoice.payment_failed': {
const { customerId } = event.data;
// Notifica al cliente o activa lógica de reintento.
break;
}
}
},
});
Pruebas en sandbox
Agrega una tarjeta de prueba
En sandbox, cuando el cliente accede a la página de hostedUrl, usa la tarjeta de prueba de Stripe 4242 4242 4242 4242 con cualquier fecha futura y CVC.
Envía una factura de prueba
const onflay = new Onflay('sk_test_...');
const invoice = await onflay.invoices.create({
customerId: idClienteSandbox,
currency: 'usd',
lineItems: [{ description: 'Cargo de prueba por uso', amountInCents: 100 }],
});
console.log(invoice.status); // 'paid'
Prueba los webhooks localmente
npx onflay listen --forward-to http://localhost:3000/api/webhooks/onflay
Para simular un evento específico:npx onflay trigger invoice.paid
npx onflay trigger invoice.payment_failed
Referencia de errores
| Error | Causa | Solución |
|---|
400 — sin método de pago | El cliente no tiene tarjeta guardada | Completa el flujo de SetupIntent primero |
404 — cliente no encontrado | El customerId no pertenece a tu cuenta | Verifica el ID o crea el cliente con onflay.customers.create() |
409 — idempotencia | Ya existe una factura con esa key | Seguro ignorar — devuelve la factura original |
402 — pago fallido | Stripe rechazó el cobro | Notifica al cliente y espera invoice.payment_failed |