Skip to main content
This guide shows how to create a complete billing flow programmatically: define pricing, create a plan, embed checkout, and route billable traffic per customer.
Prerequisites: Start with Authenticate an Agent, then follow Route Traffic for the gateway path you chose.

MCP flow

The Lava MCP server handles gateway traffic routing. Billing setup (meters, plans, checkout) requires the SDK. A typical billing workflow:
  1. SDK: Create a meter, plan, and checkout session (Steps 1–3 below)
  2. MCP: login to authenticate the gateway session
  3. MCP: prompt or call to route billable traffic through the gateway

SDK flow

Overview

The billing flow has four parts:
  1. Meter - Defines how usage is priced (e.g., $3 per million tokens)
  2. Plan - A subscription that includes an optional monthly fee, credit allowance, and linked meters
  3. Checkout - An embedded flow where your customer subscribes and pays
  4. Forward tokens - Per-customer auth tokens that route traffic through the gateway with billing

Step 1: Create a Meter

A meter defines the pricing rules for a type of usage. For example, charging per token for AI model calls:
import { Lava } from '@lavapayments/nodejs';

const lava = new Lava(); // reads LAVA_SECRET_KEY from env

const meter = await lava.meters.create({
  name: 'AI Chat Tokens',
  rate_type: 'fixed',
  tier_type: 'tokens_1m',
  tiers: [
    { start: '0', rate: '3.00' }  // $3.00 per million tokens
  ]
});

console.log('Meter ID:', meter.meter_id);
console.log('Meter slug:', meter.meter_slug);

Meter options

ParameterOptionsDescription
rate_typefixed, percentageFixed price per unit, or percentage markup on base cost
tier_typetokens_1m, characters_1m, minutes, requestsWhat unit is being measured
You can also add volume-based tiers for graduated pricing:
const meter = await lava.meters.create({
  name: 'API Requests',
  rate_type: 'fixed',
  tier_type: 'requests',
  tiers: [
    { start: '0', rate: '0.01' },       // $0.01/request for first 10k
    { start: '10000', rate: '0.005' }    // $0.005/request after 10k
  ]
});

Step 2: Create a Plan

A plan ties together an optional recurring price, included credits, and one or more meters (product features included in your plan):
const plan = await lava.subscriptions.createPlan({
  name: 'Pro Plan',
  period_amount: '49.00',
  billing_interval: 'month',
  included_credit: '25.00',
  meter_ids: [meter.meter_id]  // Link meters to this plan
});

console.log('Plan ID:', plan.plan_id);
The meter_ids field links meters to the plan. You can link multiple meters to a single plan.

Plan options

ParameterOptionsDescription
billing_intervalday, week, month, yearHow often the subscription renews
rollover_typefull, noneWhether unused included credit carries over
included_creditAny decimal stringCredit included with each billing cycle
credit_bundlesArray of bundlesOptional add-on credit packs customers can purchase
Example with credit bundles:
const plan = await lava.subscriptions.createPlan({
  name: 'Pro Plan',
  period_amount: '99.00',
  billing_interval: 'month',
  included_credit: '50.00',
  rollover_type: 'full',
  meter_ids: [meterA.meter_id, meterB.meter_id],
  credit_bundles: [
    { name: '$25 Top-up', cost: '25.00', credit_amount: '25.00' },
    { name: '$100 Top-up', cost: '100.00', credit_amount: '100.00' }
  ]
});

Step 3: Embed Checkout

Checkout is a two-step flow: your backend creates a session, your frontend opens it with the @lavapayments/checkout SDK.
npm install @lavapayments/checkout

Backend: Create a session

const session = await lava.checkoutSessions.create({
  checkout_mode: 'subscription',
  origin_url: 'https://yourapp.com',
  plan_id: plan.plan_id
});

// Return session.checkout_session_token to your frontend

Frontend: Open checkout

import { useLavaCheckout } from '@lavapayments/checkout';

const { open } = useLavaCheckout({
  onSuccess: ({ customerId }) => {
    // Save customerId — this is the billing relationship with your customer
  }
});

// Call with the token from your backend
open(checkoutSessionToken);
The checkout overlay handles phone verification, payment method collection, and subscription creation. When complete, onSuccess fires with the customerId.
Checkout sessions expire after 60 minutes. Create a new session for each checkout attempt.
The checkout_session_token is an opaque token — do not try to construct URLs from it. Always use the SDK to open checkout.

Step 4: Route Billable Traffic

Once a customer has completed checkout, generate forward tokens scoped to their customer ID and meter. Every request made with this token is tracked and billed against their subscription:
// Get the customer (from your database, or list them)
const { data: customers } = await lava.customers.list();
const customer = customers[0];

// Generate a forward token for this customer
const forwardToken = lava.generateForwardToken({
  customer_id: customer.customer_id,
  meter_slug: meter.meter_slug,
});

// Use it exactly like in the Route Traffic guide
const response = await fetch(lava.providers.openai + '/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${forwardToken}`
  },
  body: JSON.stringify({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: 'Hello!' }]
  })
});

Step 5: Monitor Customer Usage

Track usage and costs per customer:
// Get usage for a specific customer
const usage = await lava.usage.retrieve({
  start: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
  customer_id: customer.customer_id,
});

console.log('Customer requests:', usage.totals.total_requests);
console.log('Customer cost:', usage.totals.total_cost);

// Check their subscription status
const sub = await lava.customers.getSubscription(customer.customer_id);
if (sub.subscription) {
  console.log('Plan:', sub.subscription.plan.name);
  console.log('Credits remaining:', sub.subscription.credits.total_remaining);
}

What’s Next?

Meters

Advanced meter configuration and pricing strategies

Checkout Guide

Checkout modes, completion handling, and webhooks

Webhooks

Get notified when customers subscribe, run low on balance, or cancel

SDK Reference

Full API for customers, subscriptions, and usage