Skip to main content

Overview

Checkout sessions handle wallet creation and payment collection for your customers. The SDK creates sessions on your backend, then you pass the session token to your frontend to display Lava’s checkout UI (using @lavapayments/checkout).

Checkout Modes

Lava supports three checkout modes:
ModePurposeWhen to Use
onboardingCreate new wallet + collect initial paymentFirst-time customers
topupAdd funds to existing walletExisting customers adding credits
subscriptionStart recurring billing planMonthly subscription plans

Methods

create()

Create a new checkout session. Signature
create(params: CreateCheckoutSessionParams): Promise<RestCheckoutSession>
Parameters
NameTypeRequiredDescription
checkout_mode'onboarding' | 'topup' | 'subscription'YesThe type of checkout flow
origin_urlstringYesYour app’s origin URL for CORS (must match window.location.origin)
reference_idstringNoYour internal user/customer ID for tracking
connection_idstringNoRequired for topup mode
subscription_config_idstringNoRequired for subscription mode
Returns
{
  checkout_session_id: string;
  checkout_session_token: string; // Pass this to frontend
  checkout_mode: 'onboarding' | 'topup' | 'subscription';
  origin_url: string;
  connection_id?: string;
  reference_id?: string;
  subscription_config_id?: string;
  created_at: string;
  completed_at?: string;
}
Example: Onboarding Mode Create a wallet for a new customer:
const session = await lava.checkoutSessions.create({
  checkout_mode: 'onboarding',
  origin_url: 'https://yourapp.com',
  reference_id: 'user_123' // Your internal user ID
});

// Pass to frontend
res.json({
  checkoutToken: session.checkout_session_token
});
Example: Topup Mode Add funds to an existing wallet:
const session = await lava.checkoutSessions.create({
  checkout_mode: 'topup',
  origin_url: 'https://yourapp.com',
  connection_id: 'conn_existing_connection_id'
});

res.json({
  checkoutToken: session.checkout_session_token
});
Example: Subscription Mode Start a recurring billing plan:
const session = await lava.checkoutSessions.create({
  checkout_mode: 'subscription',
  origin_url: 'https://yourapp.com',
  subscription_config_id: 'subconf_plan_id'
});

res.json({
  checkoutToken: session.checkout_session_token
});

list()

List all checkout sessions with optional filtering. Signature
list(params?: CheckoutSessionsListParams): Promise<ListResponse<RestCheckoutSession>>
Parameters
NameTypeRequiredDescription
cursorstringNoPagination cursor for next page
limitnumberNoNumber of results per page (default: 10, max: 100)
reference_idstringNoFilter by your internal user/customer ID
Returns
{
  data: RestCheckoutSession[];
  has_more: boolean;
  next_cursor?: string;
}
Example: List All Sessions
const sessions = await lava.checkoutSessions.list({
  limit: 20
});

console.log(`Found ${sessions.data.length} sessions`);
console.log('Has more:', sessions.has_more);
Example: Filter by Reference ID
const userSessions = await lava.checkoutSessions.list({
  reference_id: 'user_123'
});

// Get all sessions for this user
for (const session of userSessions.data) {
  console.log(`Session ${session.checkout_session_id}: ${session.checkout_mode}`);
}
Example: Pagination
let cursor: string | undefined;
const allSessions: RestCheckoutSession[] = [];

do {
  const response = await lava.checkoutSessions.list({
    limit: 100,
    cursor
  });

  allSessions.push(...response.data);
  cursor = response.next_cursor;
} while (cursor);

console.log(`Total sessions: ${allSessions.length}`);

retrieve()

Get details for a specific checkout session. Signature
retrieve(checkoutSessionId: string): Promise<RestCheckoutSession>
Parameters
NameTypeRequiredDescription
checkoutSessionIdstringYesThe checkout session ID
Returns Single RestCheckoutSession object with full details. Example
const session = await lava.checkoutSessions.retrieve('cs_abc123');

if (session.completed_at) {
  console.log('Checkout completed at:', session.completed_at);
  console.log('Connection ID:', session.connection_id);
} else {
  console.log('Checkout still pending');
}

Integration with Frontend

After creating a checkout session on your backend, pass the checkout_session_token to your frontend:

Backend (Node.js)

// API route: POST /api/create-checkout
app.post('/api/create-checkout', async (req, res) => {
  const session = await lava.checkoutSessions.create({
    checkout_mode: 'onboarding',
    origin_url: 'https://yourapp.com',
    reference_id: req.user.id
  });

  res.json({
    checkoutToken: session.checkout_session_token
  });
});

Frontend (React)

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

function CheckoutButton() {
  const [checkoutToken, setCheckoutToken] = useState<string>();

  const handleCheckout = async () => {
    // Call your backend
    const response = await fetch('/api/create-checkout', {
      method: 'POST'
    });
    const { checkoutToken } = await response.json();

    setCheckoutToken(checkoutToken);
  };

  return (
    <>
      <button onClick={handleCheckout}>Add Credits</button>

      {checkoutToken && (
        <LavaCheckout
          checkoutToken={checkoutToken}
          onSuccess={() => {
            console.log('Payment successful!');
            // Refresh user balance, close modal, etc.
          }}
        />
      )}
    </>
  );
}
See the @lavapayments/checkout documentation for complete frontend integration details.

Handling Checkout Completion

You can detect when a checkout completes using webhooks or by polling the session status: Configure webhooks in your Lava dashboard to receive real-time notifications:
// Webhook handler
app.post('/webhooks/lava/checkout-complete', async (req, res) => {
  const { checkout_session_id, connection_id, reference_id } = req.body;

  // Retrieve full session details
  const session = await lava.checkoutSessions.retrieve(checkout_session_id);

  // Get connection details
  const connection = await lava.connections.retrieve(connection_id);

  // Store connection_secret for future AI requests
  await database.users.update(reference_id, {
    lavaConnectionId: connection.connection_id,
    lavaConnectionSecret: connection.connection_secret
  });

  res.json({ received: true });
});

Polling (Alternative)

async function waitForCheckoutCompletion(sessionId: string) {
  const maxAttempts = 60; // 5 minutes max
  let attempts = 0;

  while (attempts < maxAttempts) {
    const session = await lava.checkoutSessions.retrieve(sessionId);

    if (session.completed_at) {
      return session;
    }

    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
    attempts++;
  }

  throw new Error('Checkout timeout');
}

Common Use Cases

Conditional Onboarding

Only show checkout if user doesn’t have a connection:
app.post('/api/ensure-wallet', async (req, res) => {
  const userId = req.user.id;

  // Check if user already has a connection
  const connections = await lava.connections.list({
    reference_id: userId,
    limit: 1
  });

  if (connections.data.length > 0) {
    // User already has wallet
    return res.json({
      hasWallet: true,
      connectionId: connections.data[0].connection_id
    });
  }

  // Create new checkout session
  const session = await lava.checkoutSessions.create({
    checkout_mode: 'onboarding',
    origin_url: 'https://yourapp.com',
    reference_id: userId
  });

  res.json({
    hasWallet: false,
    checkoutToken: session.checkout_session_token
  });
});

Multi-Tier Subscriptions

Create different subscription tiers:
app.post('/api/subscribe/:tier', async (req, res) => {
  const tier = req.params.tier; // 'basic' or 'premium'

  const subscriptionConfigId = tier === 'premium'
    ? process.env.LAVA_PREMIUM_SUBSCRIPTION_ID!
    : process.env.LAVA_BASIC_SUBSCRIPTION_ID!;

  const session = await lava.checkoutSessions.create({
    checkout_mode: 'subscription',
    origin_url: 'https://yourapp.com',
    subscription_config_id: subscriptionConfigId,
    reference_id: req.user.id
  });

  res.json({ checkoutToken: session.checkout_session_token });
});