> ## Documentation Index
> Fetch the complete documentation index at: https://lava.so/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js SDK

> Official Node.js SDK for integrating Lava's monetization and AI proxy APIs

The `@lavapayments/nodejs` SDK provides a typed client for all Lava API operations including checkout, customers, usage tracking, and forward token generation.

## Installation

```bash theme={null}
npm install @lavapayments/nodejs
```

**Requirements**: Node.js 18.0.0 or higher

## Initialize

```typescript theme={null}
import { Lava } from '@lavapayments/nodejs';

const lava = new Lava();
```

<Tip>
  The client reads your secret key from the `LAVA_SECRET_KEY` environment variable automatically. You can also pass it explicitly: `new Lava('aks_live_...')`. Never commit API keys to version control.
</Tip>

## Resources

| Resource           | Purpose               | Key Methods                                                                                                       |
| ------------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `checkoutSessions` | Create payment flows  | `create()`                                                                                                        |
| `customers`        | Manage customer links | `list()`, `retrieve()`, `getSubscription()`, `delete()`                                                           |
| `requests`         | Track API usage       | `list()`, `create()`, `retrieve()`                                                                                |
| `usage`            | Aggregate usage stats | `retrieve()`                                                                                                      |
| `subscriptions`    | Manage billing plans  | `listPlans()`, `retrievePlan()`, `createPlan()`, `updatePlan()`, `deletePlan()`, `list()`, `update()`, `cancel()` |
| `meters`           | Pricing configuration | `list()`, `retrieve()`, `create()`, `update()`, `delete()`                                                        |
| `creditBundles`    | Add-on credit packs   | `list()`, `retrieve()`                                                                                            |
| `webhooks`         | Event notifications   | `list()`, `retrieve()`, `create()`, `update()`, `delete()`                                                        |
| `secretKeys`       | API key management    | `list()`, `create()`, `delete()`                                                                                  |
| `spendKeys`        | Wallet spend keys     | `list()`, `retrieve()`, `create()`, `update()`, `revoke()`, `rotate()`                                            |
| `models`           | Model discovery       | `list()`                                                                                                          |

Plus utility methods:

* `gateway()` -- Make requests through the gateway in a single call
* `generateForwardToken()` -- Create authentication tokens for manual requests
* `Lava.login()` -- Browser-based CLI authentication (static)
* `Lava.exchangeAuthCode()` -- Exchange auth code for credentials (static)
* `providers.*` -- Pre-configured URLs for 27 AI providers

## Gateway Requests

The `gateway()` method makes a request through Lava's gateway in a single call. It handles forward token generation, URL construction, and body serialization automatically.

```typescript theme={null}
const data = await lava.gateway('https://api.openai.com/v1/chat/completions', {
  body: {
    model: 'gpt-4o',
    messages: [{ role: 'user', content: 'Hello!' }],
  },
});
```

### Parameters

| Parameter                 | Type                     | Required | Description                                                                                                     |
| ------------------------- | ------------------------ | -------- | --------------------------------------------------------------------------------------------------------------- |
| `url`                     | `string`                 | Yes      | The raw provider URL (e.g., `https://api.openai.com/v1/chat/completions`)                                       |
| `options.method`          | `string`                 | No       | HTTP method. Defaults to `POST`.                                                                                |
| `options.body`            | `unknown`                | No       | Request body. Objects/arrays are auto-serialized to JSON. Strings, Buffers, and streams pass through unchanged. |
| `options.headers`         | `Record<string, string>` | No       | Headers to forward to the provider. `Authorization` is set automatically.                                       |
| `options.customer_id`     | `string`                 | No       | Customer ID for billing. Must be used with `meter_slug`.                                                        |
| `options.meter_slug`      | `string`                 | No       | Meter slug for billing. Use with `customer_id` for customer billing, or alone for meter-only mode.              |
| `options.provider_key`    | `string`                 | No       | Override the provider key for this request.                                                                     |
| `options.disable_billing` | `boolean`                | No       | Disable billing for this request.                                                                               |

### With Customer Billing

```typescript theme={null}
const data = await lava.gateway('https://api.openai.com/v1/chat/completions', {
  body: { model: 'gpt-4o', messages: [{ role: 'user', content: 'Hello!' }] },
  customer_id: 'cus_123',
  meter_slug: 'ai-usage',
});
```

### Meter-Only Mode

Track usage on a meter without billing a specific customer:

```typescript theme={null}
const data = await lava.gateway('https://api.openai.com/v1/chat/completions', {
  body: { model: 'gpt-4o', messages: [{ role: 'user', content: 'Hello!' }] },
  meter_slug: 'ai-usage',
});
```

### With Format Translation (Rewrite)

Use `format` to send requests in one LLM format and have Lava translate to the provider's native format automatically. The provider format is auto-detected from the target URL.

```typescript theme={null}
// Send OpenAI-shaped requests to Anthropic — Lava translates both request and response
const data = await lava.gateway('https://api.anthropic.com/v1/messages', {
  format: 'openai',
  body: {
    model: 'claude-haiku-4-5',
    messages: [{ role: 'user', content: 'Hello!' }],
  },
});
// Response is in OpenAI format, regardless of provider
```

Supported formats: `openai`, `anthropic`, `google`, `bedrock`. See [Rewrite Proxy](/gateway/rewrite-proxy) for details on format translation.

### With Custom Headers

Some providers require additional headers. Pass them via `options.headers` -- the `Authorization` header is always set to the forward token automatically.

```typescript theme={null}
const data = await lava.gateway('https://api.anthropic.com/v1/messages', {
  body: {
    model: 'claude-haiku-4-5',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello!' }],
  },
  headers: { 'anthropic-version': '2023-06-01' },
});
```

<Info>
  Pass the **raw provider URL** to `gateway()` (e.g., `https://api.openai.com/v1/chat/completions`), not `lava.providers.*` URLs. The method constructs the forwarding URL internally.
</Info>

<Warning>
  Passing `customer_id` without `meter_slug` will throw an error. Provide both for customer billing, use `meter_slug` alone for meter-only mode, or omit both for merchant billing.
</Warning>

<Info>
  The `gateway()` method returns parsed JSON. For streaming responses, use `generateForwardToken()` with manual `fetch()` instead.
</Info>

## Authentication

### Using Your Secret Key (Simplest)

The simplest way to authenticate is to pass your secret key directly -- no forward token needed. Costs are charged to your merchant wallet:

```typescript theme={null}
const response = await fetch(lava.providers.openai + '/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${process.env.LAVA_SECRET_KEY}`
  },
  body: JSON.stringify({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: 'Hello!' }]
  })
});
```

Or use the [`gateway()` method](#gateway-method) which handles this automatically.

### Generating Forward Tokens

When you need customer billing, metering, or BYOK, generate a forward token that bundles your credentials with billing parameters.

**Meter-only authentication** -- use this when you want usage tracking on a specific meter without billing a customer:

```typescript theme={null}
const forwardToken = lava.generateForwardToken({
  meter_slug: 'my-meter'
});
```

**Customer-based authentication** -- use this when billing a specific customer's wallet with your pricing configuration:

```typescript theme={null}
const forwardToken = lava.generateForwardToken({
  customer_id: 'conn_id_from_customer',
  meter_slug: 'my-meter'
});
```

**Billing-disabled authentication** -- proxy requests through a customer's meter without charging their wallet:

```typescript theme={null}
const forwardToken = lava.generateForwardToken({
  customer_id: 'conn_id_from_customer',
  meter_slug: 'my-meter',
  disable_billing: true
});
```

**Unmanaged (bring your own key) authentication** — use your own provider API key with Lava for usage tracking only:

```typescript theme={null}
const forwardToken = lava.generateForwardToken({
  customer_id: null,
  meter_slug: null,
  provider_key: process.env.OPENAI_API_KEY!
});
```

<Info>
  **Unmanaged mode** (bring your own key) lets you use Lava's proxy for usage tracking and analytics without setting up wallet billing. You supply your own provider API key; the AI provider charges your account directly. Lava may still charge a service fee for metering.
</Info>

### CLI Authentication

Use `Lava.login()` to authenticate from a CLI or script. It opens the browser, waits for the user to authorize, and returns credentials:

```typescript theme={null}
import { Lava } from '@lavapayments/nodejs';

const credentials = await Lava.login();
// credentials: { secret_key, wallet_id, merchant_id, ... }

const lava = new Lava(credentials.secret_key);
```

`Lava.login()` loads the active secret key, creating one if needed.

If you already have an authorization code (from a custom callback flow), exchange it directly:

```typescript theme={null}
const credentials = await Lava.exchangeAuthCode({
  code: 'abc123...',
});
```

<Warning>
  `Lava.login()` requires a Node.js environment. It starts a local HTTP server and opens the system browser. It is not intended for use in production web applications.
</Warning>

## Key Management

### Spend Keys

Spend keys give scoped access to your wallet for AI requests:

```typescript theme={null}
const lava = new Lava('aks_live_...');

const spendKey = await lava.spendKeys.create({
  name: 'Agent Key',
  allowed_providers: ['openai', 'anthropic'],
  spend_limit: { amount: '50.00', cycle: 'monthly' },
  rate_limit: { rpm: 60 },
});
// spendKey.key — the raw key, only shown once

// Rotate a key's secret (preserves settings)
const rotated = await lava.spendKeys.rotate(spendKey.spend_key_id);
// rotated.key — new raw key

// Revoke a key
await lava.spendKeys.revoke(spendKey.spend_key_id);
```

### Model Discovery

List available AI models in OpenAI-compatible format. When authenticated with a spend key, results are filtered by the key's allowed models and providers:

```typescript theme={null}
const lava = new Lava();

const { data: models } = await lava.models.list();
// models[0]: { id: 'gpt-4o-mini', object: 'model', owned_by: 'openai', created: ... }
```

## Key Operations

### Create a Checkout Session

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

// Pass session.checkout_session_token to the checkout SDK
```

Checkout modes: `subscription` (recurring plan), `credit_bundle` (add-on credits).

### Retrieve a Customer

```typescript theme={null}
const customer = await lava.customers.retrieve('conn_abc123');

customer.customer_id;              // unique customer ID
customer.contact;                  // { phone, email, first_name, last_name }
customer.subscription;             // summary or null
```

### Check Subscription Status

```typescript theme={null}
const { subscription } = await lava.customers.getSubscription('conn_abc123');

if (subscription) {
  subscription.plan.name;                  // plan name
  subscription.credits.total_remaining;    // total available credits
  subscription.credits.cycle_remaining;    // from included credit + rollover
  subscription.credits.bundle_remaining;   // from bundle purchases + rollover
  subscription.cycle_end_at;               // current cycle end date
  subscription.pending_change;             // null, or { type: 'cancellation' | 'downgrade', effective_at }
}
```

### Update a Subscription

```typescript theme={null}
// Set auto top-up bundle for a customer's subscription
await lava.subscriptions.update('as_abc123', {
  auto_top_up_bundle_id: 'cb_pack_id'
});

// Disable auto top-up
await lava.subscriptions.update('as_abc123', {
  auto_top_up_bundle_id: null
});
```

### Report Usage (Post-Request Billing)

For advanced scenarios where you track usage outside of Lava's proxy:

```typescript theme={null}
const request = await lava.requests.create({
  request_id: 'req_custom_' + Date.now(),
  customer_id: 'conn_abc123',
  meter_slug: 'my-meter',
  input_tokens: 100,
  output_tokens: 50,
  metadata: {
    feature: 'code-generation',
    user_id: 'user_789'
  }
});

request.cost;                // base AI provider cost
request.charge.amount;       // merchant fee/markup charged
request.model_usage;         // { input_tokens, output_tokens, total_cost, ... }
```

### Get Usage Statistics

```typescript theme={null}
const usage = await lava.usage.retrieve({
  start: '2025-01-01T00:00:00Z',
  end: '2025-01-31T23:59:59Z',
  // Optional filters:
  // customer_id: 'conn_abc123',
  // meter_id: 'meter_abc123',
  // metadata_filters: { feature: 'chat' },
});

usage.totals.total_requests;      // aggregate request count
usage.totals.total_usage_tokens;  // aggregate token count
usage.totals.total_cost;          // aggregate AI provider cost
usage.totals.total_charge;        // aggregate merchant fees/markup
usage.items;                      // daily breakdown array
```

## Common Patterns

### Pagination

All list methods support cursor-based pagination:

```typescript theme={null}
let cursor: string | undefined;
const allCustomers = [];

do {
  const response = await lava.customers.list({ limit: 100, cursor });
  allCustomers.push(...response.data);
  cursor = response.next_cursor;
} while (cursor);
```

### Error Handling

```typescript theme={null}
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!' }]
  })
});

if (!response.ok) {
  const error = await response.json();
  // 402 — insufficient wallet balance
  // 401 — invalid forward token
  // Other — provider error (passed through)
}

const data = await response.json();
```

## Gateway Flow Example

A minimal integration for developers using Lava as an AI proxy:

```typescript theme={null}
import { Lava } from '@lavapayments/nodejs';

const lava = new Lava();

// 1. Generate a gateway-mode forward token
const forwardToken = lava.generateForwardToken({});

// 2. Make an AI request through Lava's proxy
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: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'Hello!' }
    ]
  })
});

const data = await response.json();

// 3. Check usage via the API
const usage = await lava.usage.retrieve({
  start: new Date(Date.now() - 86400000).toISOString(),
});
// usage.totals.total_requests, usage.totals.total_cost
```

<Info>
  Gateway mode charges costs to your merchant wallet. To bill customers instead, see the [Monetization Flow](#monetization-flow-example) below.
</Info>

## Monetization Flow Example

A complete integration from checkout to AI request:

```typescript theme={null}
import { Lava } from '@lavapayments/nodejs';

const lava = new Lava();

// 1. Create a checkout session for a new customer
const session = await lava.checkoutSessions.create({
  checkout_mode: 'subscription',
  origin_url: 'https://yourapp.com',
  plan_id: 'sc_plan_id'
});
// Pass session.checkout_session_token to the checkout SDK

// 2. After checkout completes, your frontend receives a customer_id
//    Store it in your database, associated with your user

// 3. Generate a forward token for AI requests
const forwardToken = lava.generateForwardToken({
  customer_id: 'conn_...', // from your database
  meter_slug: process.env.LAVA_METER_SLUG!
});

// 4. Make an AI request through Lava's proxy
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: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: 'Hello!' }
    ]
  })
});

const data = await response.json();

// 5. Check remaining credit
const { subscription } = await lava.customers.getSubscription('conn_...');
// subscription?.credits.total_remaining
```

<Info>
  The SDK automatically detects test vs production mode based on your secret key prefix:

  * `aks_test_*` routes to sandbox (`sandbox-api.lava.so`)
  * Other prefixes route to production (`api.lava.so`)
</Info>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Complete API documentation with all parameters and response types
  </Card>

  <Card title="Forward Proxy" icon="route" href="/gateway/forward-proxy">
    Route AI requests through Lava's proxy
  </Card>
</CardGroup>
