Skip to main content
There are two ways to use Lava for billing: Path 1: Gateway + Billing (Build + Monetize) Route your AI requests through Lava’s proxy. We track usage and bill customers automatically. Path 2: Post-Request + Billing (Monetize only) Track any usage yourself and report it to Lava. Works for AI calls, API requests, compute time, or any cost you want to bill for. We recommend Path 1 for AI usage. It’s faster to set up and unlocks features that aren’t possible with post-request billing. Learn why →

Key concepts

Meter: Pricing rules for usage. Defines how you calculate cost: per token, per request, percentage markup, tiered pricing, etc. You wrap your billable operations with a meter to track usage. You might use one meter for all usage, or different meters for different features. Plan: A monthly subscription. Defines how much customers pay each month (e.g., $25/month) and whether unused credits roll over. The subscription amount becomes their usage budget. Plans link to one or more meters that determine how usage depletes the balance. Overage: When a customer uses more than their plan covers. If someone on a 25/monthplanuses25/month plan uses 30 worth of usage, they go $5 over. Lava auto-charges their card for overages so service isn’t interrupted. Checkout: A hosted payment flow where customers subscribe to your plan. They verify their phone, add a payment method, and fund their wallet. You can embed checkout in your app with a button, or send customers an email with a checkout link. Connection: A link between your app and a customer’s wallet. Created when a customer completes checkout. You use the connection to identify who to charge for each request. Forward token: A credential for each request. Combines your API key + connection + meter. Tells Lava who to charge and how to price it.
Terminology note: In the SDK and API, plans are called “subscription configs” (subscription_config_id) and meters are called “products” (product_secret). The dashboard uses “plan” and “meter.”

How meters and plans work together

Meters define pricing. Plans set the monthly budget and link to meters. Example:
  • You create a meter set to $0.02 per 1K tokens
  • You wrap your AI calls (OpenAI, Claude, Gemini, etc.) with that meter
  • You create a $25/month plan and attach the meter
  • Customer subscribes to the plan
  • Each request costs tokens × 0.02,deductedfromtheir0.02, deducted from their 25 balance
  • If they exceed $25, Lava auto-charges for the overage at the same meter rate
A plan can have multiple meters. For example, you might have one meter for chat completions and another for image generation, both attached to the same plan.

Path 1: Gateway + Billing

Your app calls AI providers (OpenAI, Claude, Gemini, Mistral, etc.) through Lava instead of directly. We see every request, track usage, and charge the customer in real time.

Step 1: Create a meter

Go to Dashboard → Meters → Create Meter. A meter defines how you price usage:
  • Fixed fee: e.g., $0.02 per 1K tokens
  • Percentage markup: e.g., 20% on top of provider costs
  • Tiered pricing: Volume discounts at higher usage
  • Billing basis: Charge for input+output tokens, output only, characters, etc.
This pricing applies to all usage, whether within the plan or overage. Save the meter. You’ll get a meter secret (called product_secret in code).

Step 2: Route your AI calls through Lava

If you’re building something new, make your AI calls through Lava from the start. If you’re already calling AI providers, swap out those calls to route through Lava instead.
import { Lava } from '@lavapayments/nodejs';

const lava = new Lava(process.env.LAVA_SECRET_KEY!, {
  apiVersion: '2025-04-28.v1'
});

// Generate a forward token with your meter and customer's connection
function makeAIRequest(connectionSecret: string, messages: any[]) {
  const forwardToken = lava.generateForwardToken({
    connection_secret: connectionSecret,
    product_secret: 'prod_...' // Your meter secret from Step 1
  });

  // Route through Lava
  // Works with OpenAI, Claude, Gemini, Mistral, and 20+ other providers
  return fetch('https://api.lavapayments.com/v1/forward?u=https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${forwardToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'gpt-4o-mini',
      messages
    })
  });
}
Same pattern for Claude, Gemini, Mistral, etc., just change the provider URL in the ?u= parameter. You can organize meters however makes sense:
  • One meter for all AI calls
  • One meter per feature (e.g., “chat” vs “summarization”)
  • One meter per provider
  • One meter per product tier
The connectionSecret comes from checkout (next steps). For now, you can test with your self-forward token from the dashboard.

Step 3: Create a plan

Go to Dashboard → Plans → Create Plan. A plan defines the monthly subscription:
  • Name: What customers see (e.g., “Pro Plan”)
  • Amount: Monthly charge (e.g., $25.00), this becomes their usage credit
  • Rollover: Whether unused credits carry to next month
  • Meters: Select which meters track usage against this plan
Save the plan. You’ll get a subscription config ID.

Step 4: Add checkout to your app

There are two ways to get customers through checkout: Option A: Embed checkout in your app (most common) Install the checkout library:
npm install @lavapayments/checkout
Create a backend endpoint that generates a checkout session:
// Backend: /api/create-checkout-session
app.post('/api/create-checkout-session', async (req, res) => {
  const session = await lava.checkoutSessions.create({
    checkout_mode: 'subscription',
    origin_url: 'https://yourapp.com',
    subscription_config_id: 'subconf_your_plan_id', // Your plan from Step 3
    reference_id: req.user.id
  });

  res.json({ checkout_session_token: session.checkout_session_token });
});
Add a button that opens checkout:
// Frontend
import { useLavaCheckout } from '@lavapayments/checkout';

function SubscribeButton() {
  const { open } = useLavaCheckout({
    onSuccess: async ({ connectionId, checkoutSessionId }) => {
      // Save connection to your database
      await saveToDatabase(userId, connectionId);

      // Retrieve the connection secret for making metered requests
      const connection = await fetch(`/api/connections/${connectionId}`);
      const { connectionSecret } = await connection.json();

      // Now you can make metered AI requests for this customer
      // using the connectionSecret from Step 2
    }
  });

  return (
    <button onClick={() => {
      fetch('/api/create-checkout-session')
        .then(res => res.json())
        .then(data => open(data.checkout_session_token));
    }}>
      Subscribe to Pro Plan
    </button>
  );
}
Option B: Send a checkout link via email Generate a checkout session and email the link to your customer:
const session = await lava.checkoutSessions.create({
  checkout_mode: 'subscription',
  origin_url: 'https://yourapp.com',
  subscription_config_id: 'subconf_your_plan_id',
  reference_id: customerId
});

// Send email with checkout link
await sendEmail({
  to: customer.email,
  subject: 'Complete your subscription',
  body: `Click here to subscribe: https://checkout.lavapayments.com/${session.checkout_session_token}`
});
When the customer clicks the link, they complete checkout in their browser. Use webhooks to get notified when checkout completes.
When a customer completes checkout, they’ll:
  1. Verify their phone number
  2. Add a payment method (for overages and renewal)
  3. Subscribe to your plan
You get a connection ID. Save it and retrieve the connection secret:
const connection = await lava.connections.retrieve(connectionId);
const connectionSecret = connection.connection_secret;
Now use that connectionSecret in your metered AI requests from Step 2.

Step 5: Verify it worked

Go to Dashboard → Requests to see requests with cost breakdown. Go to Dashboard → Connections to see customer balances. Lava:
  1. Forwards requests to the provider
  2. Tracks token usage
  3. Calculates cost using your meter pricing
  4. Deducts from the customer’s plan balance
  5. If balance hits zero, auto-charges their card for overages

Path 2: Post-Request + Billing

You track usage yourself and report it to Lava. This works for AI calls, but also for any billable operation: API requests, database queries, compute time, file storage, or any cost you want to pass through. This path is common when you bring your own API keys (BYOK) and want Lava to handle billing while you call providers directly.

Step 1: Create a meter

Dashboard → Meters → Create Meter. For non-AI usage, you’ll typically use:
  • Per-request pricing: e.g., $0.001 per API call
  • Fixed fee: e.g., $0.05 per operation
  • Tiered pricing: Volume discounts
Save the meter. Get your meter secret.

Step 2: Report usage after each operation

After each billable operation, report it to Lava:
POST https://api.lavapayments.com/v1/requests
Authorization: Bearer <lava_secret_key>
Content-Type: application/json

{
  "request_id": "req_01K7QJT2YSVV0YR2NPK4Z2GRXQ",
  "connection_secret": "cons_live_Gv3Kl2uKH_4BxcFQlhDRKimWlp2dBpmne3eK_cYoATblRRADynmmY9",
  "product_secret": "cons_live_oe9egtYLNza5t6SVUdGOBmpC7VrX7c6SVDJfQbeLYBc3maNVoAu3Db",
  "input_tokens": 100,
  "output_tokens": 500,
  "input_characters": 0,
  "output_characters": 0,
  "input_seconds": 0.0,
  "output_seconds": 0.0,
  "metadata": {
    "key": "value"
  }
}
Or using the SDK:
import { Lava } from '@lavapayments/nodejs';

const lava = new Lava(process.env.LAVA_SECRET_KEY!, {
  apiVersion: '2025-04-28.v1'
});

await lava.requests.create({
  request_id: crypto.randomUUID(),
  connection_secret: connectionSecret,
  product_secret: 'prod_...', // Your meter secret
  input_tokens: 100,
  output_tokens: 500,
  metadata: { feature: 'chat' }
});
Only populate the fields relevant to your usage type. For example:
  • LLM requests → input_tokens and output_tokens
  • Text-to-speech → input_characters and output_seconds
  • Speech-to-text → input_seconds and output_characters
  • Video generation → input_seconds or output_seconds

Usage fields reference

FieldTypeUse case
request_idstring (required)Idempotency key to deduplicate requests
connection_secretstring (required)Identifies which customer wallet to charge
product_secretstring (required)Determines which meter/pricing rules apply
input_tokensintegerLLMs (GPT-4, Claude, etc.)
output_tokensintegerLLMs - typically priced higher than input
input_charactersintegerTTS, translation, embeddings
output_charactersintegerText generation APIs
input_secondsfloatSpeech-to-text, media processing
output_secondsfloatTTS, voice synthesis, video generation
metadataobjectOptional data for filtering/analytics

Examples by use case

LLM (OpenAI, Claude, etc.)
const response = await openai.chat.completions.create({ ... });

await lava.requests.create({
  request_id: crypto.randomUUID(),
  connection_secret: connectionSecret,
  product_secret: 'prod_...',
  input_tokens: response.usage.prompt_tokens,
  output_tokens: response.usage.completion_tokens
});
Text-to-speech
const audio = await elevenLabs.generate({ text: userText });

await lava.requests.create({
  request_id: crypto.randomUUID(),
  connection_secret: connectionSecret,
  product_secret: 'prod_...',
  input_characters: userText.length,
  output_seconds: audio.durationSeconds
});
Speech-to-text
const transcript = await whisper.transcribe(audioFile);

await lava.requests.create({
  request_id: crypto.randomUUID(),
  connection_secret: connectionSecret,
  product_secret: 'prod_...',
  input_seconds: audioFile.durationSeconds,
  output_characters: transcript.text.length
});
Video generation
const video = await runway.generate({ prompt });

await lava.requests.create({
  request_id: crypto.randomUUID(),
  connection_secret: connectionSecret,
  product_secret: 'prod_...',
  output_seconds: video.durationSeconds
});
Per-request (meter handles flat pricing)
await elasticSearch.query({ ... });

await lava.requests.create({
  request_id: crypto.randomUUID(),
  connection_secret: connectionSecret,
  product_secret: 'prod_...'
  // No usage fields - meter charges flat rate per request
});
The connectionSecret comes from checkout (next steps).

Step 3: Create a plan

Dashboard → Plans → Create Plan. Attach the meter(s).

Step 4: Add checkout to your app

Same as Path 1. Embed a checkout button or send a checkout link via email. When checkout completes, save the connection ID and retrieve the connection secret to use in your usage reporting from Step 2.

Step 5: Verify it worked

Same as Path 1. Check Dashboard → Requests and Dashboard → Connections.

Terminology

DashboardSDK / APIUsed for
MeterProductRequest pricing
Meter secretproduct_secretForward tokens, reporting usage
PlanSubscription ConfigCheckout (what customers subscribe to)
Plan IDsubscription_config_idCreating checkout sessions

Next steps