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:
| Mode | Purpose | When to Use |
|---|
onboarding | Create new wallet + collect initial payment | First-time customers |
topup | Add funds to existing wallet | Existing customers adding credits |
subscription | Start recurring billing plan | Monthly subscription plans |
Methods
create()
Create a new checkout session.
Signature
create(params: CreateCheckoutSessionParams): Promise<RestCheckoutSession>
Parameters
| Name | Type | Required | Description |
|---|
checkout_mode | 'onboarding' | 'topup' | 'subscription' | Yes | The type of checkout flow |
origin_url | string | Yes | Your app’s origin URL for CORS (must match window.location.origin) |
reference_id | string | No | Your internal user/customer ID for tracking |
connection_id | string | No | Required for topup mode |
subscription_config_id | string | No | Required 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
| Name | Type | Required | Description |
|---|
cursor | string | No | Pagination cursor for next page |
limit | number | No | Number of results per page (default: 10, max: 100) |
reference_id | string | No | Filter 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
| Name | Type | Required | Description |
|---|
checkoutSessionId | string | Yes | The 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:
Using Webhooks (Recommended)
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 });
});