> ## 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.

# Plans

> Configure recurring billing with included credits, rollovers, linked meters, and credit bundles

A **plan** governs a customer's access and billing. Plans specify:

* **Recurring charge** — how much and how often (e.g., \$25/month)
* **Included credits** — usage allowance per billing cycle
* **Rollover rules** — whether unused credits carry to the next cycle
* **Linked meters** — which meters can draw from plan credits
* **Credit bundles** — one-time credit packs customers can purchase

<Info>
  Plans and subscriptions are used interchangeably — in the SDK and API, plan templates are called **plans** (`plan_id`), and a customer's enrollment is an **active subscription**. Despite the name, a plan doesn't require a recurring charge — set the period amount to \$0 for pure pay-as-you-go pricing where customers only pay for what they use.
</Info>

## Default free plan

Every merchant account starts with a **Free** plan (\$0/month, no included credit). Customers are automatically placed on this plan until they complete checkout for a paid plan.

You can customize the free plan from **Monetize > Plans** in the dashboard, for example to include a small credit allowance for free-tier users. The free plan works like any other plan: you can rename it, add included credit, link meters, and attach credit bundles.

<Tip>
  Use the free plan to offer a trial experience. For example, set included credit to \$1.00 so free-tier users can try your product before upgrading.
</Tip>

## Plan configuration

<Accordion title="Full create example with all parameters">
  <Tabs>
    <Tab title="Node.js SDK">
      ```typescript theme={null}
      const plan = await lava.subscriptions.createPlan({
        // Required
        name: 'Pro Plan',
        period_amount: '25.00',
        billing_interval: 'month', // 'day' | 'week' | 'month' | 'year'

        // Optional — defaults to period_amount
        included_credit: '20.00',

        // Optional — 'full' | 'none' (default: 'none')
        rollover_type: 'full',

        // Optional — 'full' | 'none' (default: 'full')
        bundle_rollover_type: 'full',

        // Optional — restrict which meters can draw from plan credits
        meter_ids: ['meter_abc123', 'meter_def456'],

        // Optional — one-time credit packs customers can purchase
        credit_bundles: [
          { name: 'Small Pack', cost: '5.00', credit_amount: '5.00' },
          { name: 'Large Pack', cost: '20.00', credit_amount: '25.00' },
        ],

        // Optional — auto top-up bundle (by index into credit_bundles array above)
        default_auto_top_up_bundle_index: 0,
      });
      ```
    </Tab>

    <Tab title="cURL">
      ```bash theme={null}
      curl -X POST 'https://api.lava.so/v1/plans' \
        -H 'Authorization: Bearer sk_your_secret_key' \
        -H 'Content-Type: application/json' \
        -d '{
          "name": "Pro Plan",
          "period_amount": "25.00",
          "billing_interval": "month",
          "included_credit": "20.00",
          "rollover_type": "full",
          "bundle_rollover_type": "full",
          "meter_ids": ["meter_abc123", "meter_def456"],
          "credit_bundles": [
            { "name": "Small Pack", "cost": "5.00", "credit_amount": "5.00" },
            { "name": "Large Pack", "cost": "20.00", "credit_amount": "25.00" }
          ],
          "default_auto_top_up_bundle_index": 0
        }'
      ```
    </Tab>
  </Tabs>
</Accordion>

### Recurring charge

The **period amount** is what the customer pays each billing cycle. This becomes their usage credit by default.

* **Billing interval:** `day`, `week`, `month`, or `year`
* **Maximum:** \$10,000 per cycle
* Period amount and billing interval are **immutable** after creation

### Included credit

The dollar amount of usage allowance included each cycle. Three modes:

| Mode                      | Included credit               | Use case                                                         |
| ------------------------- | ----------------------------- | ---------------------------------------------------------------- |
| **Full credit** (default) | Equals period amount          | Standard plan — \$25/month plan gives \$25 in credits            |
| **Partial credit**        | Custom amount ≤ period amount | Platform fee model — \$25/month but only \$20 in credits         |
| **No credit**             | \$0                           | Access fee — subscription grants access, usage billed separately |

### Rollover

Control whether unused credits carry to the next cycle:

| Rollover type | Behavior                                   |
| ------------- | ------------------------------------------ |
| `none`        | Unused credits expire at cycle end         |
| `full`        | All unused credits carry to the next cycle |

**Example with `full` rollover:**

```
Month 1: $25 credit, $15 used → $10 remaining
Month 2: $25 new + $10 rollover = $35 available
```

**Example with `none` rollover:**

```
Month 1: $25 credit, $15 used → $10 forfeited
Month 2: $25 credit (fresh start)
```

<Note>
  Cycle credits and bundle credits have **independent rollover settings**. See [Credit bundles](#credit-bundles) below.
</Note>

### Linked meters

Select which [meters](/monetize/meters) can draw from this plan's included credits. Only linked meters consume plan credits — unlinked meters bill separately.

A plan can link multiple meters (e.g., one for chat, one for image generation), all drawing from the same credit balance.

### Credit bundles

When a customer's cycle credits are depleted, the next request returns a `402` error (`forward_token_customer_limit_reached`). To keep service running, customers can upgrade to a new plan or make a one time credit purchase with credit bundles.
Each credit bundle specifies:

* **Cost** — what the customer pays (e.g., \$10)
* **Credit amount** — credits received (e.g., \$15 for a 50% bonus)

Credit bundles are scoped to each plan. Bundle credits always rollover by default and can be configured independently of cycle credit rollover.

**Checkout flow:**

1. Customer is on a plan with credit bundles
2. Your app shows available packs
3. Customer picks a pack → create a checkout session with `checkout_mode: 'credit_bundle'`
4. Customer pays → credits added to their current cycle

```typescript theme={null}
const session = await lava.checkoutSessions.create({
  checkout_mode: 'credit_bundle',
  origin_url: 'https://yourapp.com',
  customer_id: 'conn_existing_subscriber_id',
  credit_bundle_id: 'cb_pack_id'
});
```

<Note>
  The customer must have an active subscription for the plan that owns the bundle.
</Note>

## Auto top-up

You can specify a credit bundle to be automatically purchased when a customer's cycle credits are depleted. Auto top-up has two levels:

**Plan default** — set `default_auto_top_up_bundle_id` on the plan. New subscriptions inherit this setting automatically.

```typescript theme={null}
const plan = await lava.subscriptions.createPlan({
  name: 'Pro Plan',
  period_amount: '25.00',
  billing_interval: 'month',
  credit_bundles: [
    { name: 'Top-up Pack', cost: '10.00', credit_amount: '10.00' }
  ],
  default_auto_top_up_bundle_index: 0 // index into credit_bundles array
});
```

**Per-subscription override** — once a customer subscribes, you can change or disable auto top-up on their individual subscription. Use the customer's active subscription ID (`as_...`):

```typescript theme={null}
// Enable or change auto top-up bundle
await lava.subscriptions.update('as_abc123', {
  auto_top_up_bundle_id: 'cb_pack_id'
});

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

<Tip>
  Set a plan default so customers get uninterrupted service out of the box. Customers who prefer manual control can disable auto top-up on their subscription.
</Tip>

## Subscription lifecycle

### Renewal

Subscriptions renew **automatically** at the end of each billing cycle. On renewal:

* The customer is charged the period amount
* A new cycle begins with fresh included credits
* Rolled-over credits (if rollover is `full`) are added to the new cycle's balance

### Upgrades

When a customer upgrades to a higher-priced plan:

* The new plan takes effect **immediately**
* Customer is charged the full new plan amount
* Current cycle updates with the new plan's included credit
* Unused credits (both cycle and bundle) carry over

### Downgrades

When a customer switches to a lower-priced plan:

* The current plan continues until the **end of the billing cycle**
* The new plan takes effect at the **next cycle boundary**
* Shows as `pending_change.type: 'downgrade'` in the API

### Cancellation

**Scheduled cancellation** (customer-initiated):

* Subscription stays active until the current cycle ends
* Customer retains access to remaining credits
* Shows as `pending_change.type: 'cancellation'` in the API
* No further charges after the cycle ends

**Immediate cancellation** (merchant-initiated via Lava dashboard):

* Subscription terminates immediately
* Customer is blocked from further requests
* Use for fraud, disputes, or refund scenarios

### Querying subscription status

The [customer subscription](/api-reference/customers/get-customer-subscription) endpoint returns a customer's plan details and remaining credits:

```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 }
}
```

Credit breakdown:

* `credits.total_remaining` — total available credits
* `credits.cycle_remaining` — from included credit + cycle rollover
* `credits.bundle_remaining` — from bundle purchases + bundle rollover

## Next steps

<CardGroup cols={2}>
  <Card title="Meters" icon="gauge" href="/monetize/meters">
    Configure pricing rules that attach to your plans
  </Card>

  <Card title="Checkout" icon="credit-card" href="/monetize/checkout">
    Embed checkout to onboard paying customers
  </Card>
</CardGroup>
