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

# Setup

> Install the SDK and CLI, publish your catalog to Sandbox, and start your first customer on a plan.

This page sets up credit billing for a chat app. Each chat message costs 1 credit, a **Free** plan grants 50 credits a month, and **Pro** grants 1,000 credits for \$20 a month. Everything runs in **Sandbox**, with Stripe test cards, so no real money moves.

You keep your catalog in a file in your repo and publish it with the `ledger` CLI. Your backend talks to Ledger through the SDK.

> [!TIP]
>
> **Using a coding agent?** Paste this into Claude Code, Codex, Cursor or any other agent in your app's repository:
>
> ```text Prompt wrap theme={"system"}
> Add Ledger billing to my app: docs.integrateledger.com/skill.md
> ```
>
> The setup skill does every step on this page: it reads your pricing, asks about the edge cases, writes `ledger.catalog.json`, publishes it to Sandbox once you approve the diff, and wires up check and track. Along the way `ledger skills` writes its two companion skills, `ledger-catalog` and `ledger-integrate`, into your repository's `.agents/skills/`. [Build with AI](https://docs.integrateledger.com/ai.md#ledger-skills) has the details.

**1. Create a Sandbox API key**

Sign in to the [dashboard](https://dashboard.integrateledger.com), check that the sidebar switch is on **Sandbox**, then open **Settings › API keys** and choose **Create key**. The key starts with `ledger_test_` and is shown once.

Put it in your server's environment, for example in a gitignored `.env`:

```bash .env theme={"system"}
LEDGER_API_KEY=ledger_test_...
```

Keep it on your server: it can spend any customer's credits. [API keys](https://docs.integrateledger.com/api-keys.md) covers permissions.

**2. Install the SDK and the CLI**

The SDK runs in your backend. The CLI manages the catalog and needs Node 22.18 or later, or Bun, whatever your app is written in.

```bash TypeScript theme={"system"}
npm install integrateledger
npm install --save-dev integrateledger-cli
```

```bash Python theme={"system"}
pip install integrateledger
# Run the CLI with npx integrateledger-cli; nothing to install.
```

**3. Define your catalog**

`npx integrateledger-cli init` writes a starter config: `ledger.config.ts` in a JavaScript project, `ledger.catalog.json` anywhere else. Edit it to describe what you sell:

```ts ledger.config.ts theme={"system"}
import { defineCatalog, feature, plan } from "integrateledger-cli";

export default defineCatalog({
	features: [
		feature({ id: "chat_message", name: "Chat message", creditCost: 1 }),
	],
	plans: [
		plan({ id: "free", name: "Free", monthlyCredits: 50, monthlyPriceCents: 0 }),
		plan({ id: "pro", name: "Pro", monthlyCredits: 1000, monthlyPriceCents: 2000 }),
	],
	creditPacks: [],
});
```

```json ledger.catalog.json theme={"system"}
{
  "schemaVersion": 1,
  "features": [
    { "id": "chat_message", "name": "Chat message", "creditCost": 1 }
  ],
  "plans": [
    { "id": "free", "name": "Free", "monthlyCredits": 50, "monthlyPriceCents": 0 },
    { "id": "pro", "name": "Pro", "monthlyCredits": 1000, "monthlyPriceCents": 2000 }
  ],
  "addOns": []
}
```

A **feature** is an action and what one use costs. A **plan** grants credits every month; a price of `0` makes it free. [Catalog](https://docs.integrateledger.com/concepts/catalog.md) explains each item.

**4. Publish it to Sandbox**

```bash theme={"system"}
npx integrateledger-cli diff   # what would change
npx integrateledger-cli push   # publish it
```

`push` syncs each paid plan to Stripe. Sandbox comes with a Stripe test account that Ledger creates for your workspace, so there's nothing to set up in Stripe yet. From now on, change pricing the same way: edit the file, review the diff in a pull request, push. The [CLI reference](https://docs.integrateledger.com/cli.md) has every command.

**5. Create the customer on signup**

Use your app's own user or organization ID as the `customerId`, and attach the free plan when they sign up. Creating a customer grants nothing; attaching a plan does. A free plan starts at once, without Checkout.

```typescript TypeScript theme={"system"}
import ledger from "integrateledger";

export const billing = new ledger({ apiKey: process.env.LEDGER_API_KEY ?? "" });

// In your signup handler:
await billing.createOrGetCustomer({ customerId: user.id });
await billing.attach({ customerId: user.id, planId: "free" });
```

```python Python theme={"system"}
import os
from integrateledger import ledger

billing = ledger(api_key=os.environ["LEDGER_API_KEY"])

# In your signup handler:
billing.create_or_get_customer(customer_id=user.id)
billing.attach(customer_id=user.id, plan_id="free")
```

The customer now has 50 credits. [Creating customers](https://docs.integrateledger.com/customers/creating-customers.md) covers the details.

> [!NOTE]
>
> **Other ways.** You can build the catalog in the dashboard (**Plans**, **Features**, **Add-ons**) and bring it into your file with `npx integrateledger-cli pull`, or call the [API](https://docs.integrateledger.com/api-reference/introduction.md) directly. Keep one source of truth: `ledger push` archives anything that isn't in the file.

## Next steps

> [card] [Gate features](https://docs.integrateledger.com/getting-started/gating.md)
>
> Check the balance before an action and track it after.

> [card] [Display billing](https://docs.integrateledger.com/getting-started/display-billing.md)
>
> Show the balance and sell plans with Stripe Checkout.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.