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

# Billing and subscriptions

> List plans and create payment-aware checkout or direct subscriptions from a trusted backend.

Billing methods run on your server with a secret key. Derive the Nozle customer from the authenticated application user or workspace.

## List plans

```ts theme={null}
const plans = await nozle.plans()

for (const plan of plans) {
  console.log(plan.code, plan.amount_cents, plan.amount_currency, plan.interval)
}
```

Each `Plan` contains `code`, `name`, `amount_cents`, `amount_currency`, and `interval`.

## Create checkout

```ts theme={null}
const result = await nozle.checkout(
  'workspace_123',
  'pro_monthly',
  'https://app.example.com/settings/billing',
)
```

`checkout()` requires an `sk_` key and may return:

```ts theme={null}
type CheckoutResult =
  | {
      type: 'stripe'
      url?: string
      client_secret?: string
      clientSecret?: string
      invoice_id?: string
      amount_cents?: number
      currency?: string
    }
  | {
      type: 'completed' | 'scheduled'
      status: string
      subscription_id?: string
      plan_code?: string
    }
```

Handle every result shape explicitly:

```ts theme={null}
if (result.type === 'stripe') {
  if (result.url) return redirect(result.url)
  if (result.client_secret || result.clientSecret) {
    return { clientSecret: result.client_secret ?? result.clientSecret }
  }
  throw new Error('Stripe checkout returned no URL or client secret')
}

if (result.type === 'completed') {
  return { status: result.status, refreshBilling: true }
}

return { status: result.status, scheduled: true }
```

Validate the exact HTTPS return origin on your server before passing it to Nozle.

<Warning>
  Stripe webhook processing is authoritative. A checkout result, browser redirect, or client callback does not by itself prove that a paid subscription is active.
</Warning>

## Direct subscription

```ts theme={null}
const subscription = await nozle.subscribe('workspace_123', 'free')

console.log(subscription.subscription_id)
console.log(subscription.status)
```

`subscribe()` requires an `sk_` key and returns `SubscribeResult`. Use checkout for payment-gated plan changes; use direct subscription only where your configured product flow does not require an interactive payment.

## Cancellation

```ts theme={null}
const result = await nozle.cancelSubscription(
  'workspace_123',
  'subscription_123',
  'end_of_period',
)
```

The policy defaults to `end_of_period` and also accepts `immediate`.

## Entity subscriptions

Use Entity subscriptions when users, agents, projects, or workspaces under one paying customer can have different plans.

```ts theme={null}
await nozle.entitySubscriptions.ensure('workspace_123', 'user_42')

const checkout = await nozle.entitySubscriptions.checkout(
  'workspace_123',
  'user_42',
  {
    planCode: 'pro_monthly',
    billingTime: 'anniversary',
    returnUrl: 'https://app.example.com/settings/billing',
    idempotencyKey: 'checkout-user-42-pro-v1',
  },
)
```

Change or cancel only that Entity:

```ts theme={null}
await nozle.entitySubscriptions.changePlan('workspace_123', 'user_42', {
  planCode: 'max_annual',
  returnUrl: 'https://app.example.com/settings/billing',
  idempotencyKey: 'change-user-42-max-v1',
})

await nozle.entitySubscriptions.cancel('workspace_123', 'user_42', {
  timing: 'end_of_period',
  idempotencyKey: 'cancel-user-42-v1',
})
```

Every method requires an `sk_` key. See [Entity Subscriptions](/api/entity-subscriptions) for lifecycle and payment behavior.

The Node.js SDK currently exposes single-Entity checkout and plan changes. For a mixed seat-pool purchase, call the bulk Entity checkout endpoint from the same trusted backend and return only the Stripe result to your browser. Do not loop over `entitySubscriptions.checkout()`: that would create separate invoices and payments.

## Settlement transitions

Preview and apply merchant-configurable cancellation, downgrade, and uncancel operations:

```ts theme={null}
const params = {
  customerId: 'workspace_123',
  subscriptionId: 'subscription_123',
  operation: 'downgrade' as const,
  timing: 'end_of_period' as const,
  targetPlanCode: 'growth_monthly',
  creditAction: 'none' as const,
}

const preview = await nozle.previewSubscriptionTransition(params)

const transition = await nozle.applySubscriptionTransition(
  params,
  'transition-subscription-123-growth-v1',
)
```

Apply requires an idempotency key up to 255 bytes. See [Subscriptions](/guides/billing/subscriptions) for settlement options and validation rules.

## Customer creation

Create or update the customer before subscribing when needed:

```ts theme={null}
const customer = await nozle.customers.upsert({
  externalId: 'workspace_123',
  name: 'Acme Workspace',
  email: 'billing@example.com',
})
```

See [Customers and Entities](/sdks/node/customers-entities) for lifecycle methods.
