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

# Quickstart

> Build a metered sandbox customer from catalog setup through usage tracking.

Ledger runs your credit billing in Stripe test mode. Keep your organization API key on your server and use stable IDs from your application.

## 1. Create a workspace and key

Sign in at [the Ledger dashboard](https://dashboard.integrateledger.com), then open **Developer → API key**. Copy the key when shown and save it as `LEDGER_API_KEY` in your backend environment. See [Authentication](https://docs.integrateledger.com/authentication.md) for key handling.

## 2. Build a catalog

Create each item separately in the dashboard under **Catalog**, or call the API. Features set the cost of an action. Plans grant monthly credits. Add-ons sell one-time credit packs. Prices are integer cents.

```typescript theme={null}
import { Ledger } from "@ledger/sdk";

const ledger = new Ledger({ apiKey: process.env.LEDGER_API_KEY ?? "" });
await ledger.createFeature({ id: "api_call", name: "API call", creditCost: 1 });
await ledger.createPlan({ id: "starter", name: "Starter", monthlyCredits: 100, monthlyPriceCents: 1900 });
await ledger.createAddOn({ id: "extra_credits", name: "Extra credits", type: "credit_pack", creditAmount: 50, priceCents: 500 });
```

The [Catalog guide](https://docs.integrateledger.com/catalog.md) explains item updates, plan versions, and the older whole-catalog publish operation. The **API reference** tab shows a TypeScript SDK and cURL example for every endpoint.

## 3. Connect Stripe test mode

Open **Developer → Stripe** in the dashboard and connect a `sk_test_` key. Configure **Developer → Checkout** success and cancel URLs that point to your app. Ledger syncs paid plans to your Stripe account. Test mode is the only supported environment in this release.

## 4. Create and attach a customer

```typescript theme={null}
await ledger.createOrGetCustomer({ customerId: "user_123" });
const checkout = await ledger.attach({ customerId: "user_123", planId: "starter" });
// Send the customer to checkout.checkoutUrl.
```

Checkout completion alone does not grant plan credits. Ledger waits for Stripe's paid invoice webhook. In the dashboard, open **Customers** to see the subscription status and current balance. See [Customers](https://docs.integrateledger.com/customers.md) for the credit pack flow.

## 5. Check and record a successful action

```typescript theme={null}
const check = await ledger.checkCredits({ customerId: "user_123", featureId: "api_call" });
if (!check.allowed) throw new Error("Offer an upgrade or credit pack");

// Run your feature, then record successful use.
await ledger.trackUsage({ customerId: "user_123", featureId: "api_call", requestId: "operation_123" });
```

`checkCredits` does not reserve credits. `trackUsage` makes its own decision and can return `409 insufficient_credits` if the balance changed. Reuse the same request ID when retrying the same action so it is not charged twice. Read [Credits and usage](https://docs.integrateledger.com/credits.md) for concurrency and error behavior.


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