> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runledger.co/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runledger.co/_mcp/server.

# Pools

A pool is a named part of a customer's balance. Credits sit in a pool, a plan lists its pools in order, and work draws from them in that order. Use pools when credits have different rules but the same unit: included credits that reset each month, purchased credits that last a year, or credits that only some work may use.

## Before you start

* A prepaid plan with a [credit type](/concepts/billing#credit-types).
* The [burn order](/concepts/billing#credits) for credits inside one pool.

## Pools or credit types

| Use               | When                                                                                                                                                         |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **A pool**        | The credits are worth the same, and differ only in their rules: where they came from, when they expire, which allowance refills them, what they cost to burn |
| **A credit type** | The unit is different: credits and GPU-seconds, or credits in two products. Each prepaid plan has one credit type, and its balances are never added together |

Most plans that need "included first, then bought" want pools. A customer with two credit types has two separate balances.

## Define pools on a plan

`pools` lists the pools in drawdown order. An allowance feeds a pool with `pool`, `included_credits` and `top_up` take a `pool` too, and a [credit grant](/api-reference/credit-grants/create) names one.

**`Config document: plans`**

```json title="Config document: plans"
{
  "plans": [
    {
      "key": "team_monthly",
      "name": "Team",
      "billing_mode": "prepaid",
      "currency": "usd",
      "interval": "month",
      "credit_type": "ai_credits",
      "recurring_fee": { "amount": 2500, "currency": "usd" },
      "per_seat": true,
      "pools": [
        { "key": "included", "name": "Included usage" },
        { "key": "purchased", "name": "Extra usage" }
      ],
      "allowances": [
        {
          "key": "monthly",
          "kind": "refill",
          "pool": "included",
          "amount": "2000",
          "scope": "per_member",
          "window": { "type": "fixed", "duration": "P1M", "anchor": "billing_period" }
        }
      ],
      "top_up": {
        "unit_amount_decimal": "1",
        "minimum_credits": "1000",
        "maximum_credits": "1000000",
        "pool": "purchased",
        "credits_expire_in": "P1Y"
      },
      "rates": [{ "event_name": "agent.task", "credits_per_unit": "10" }]
    }
  ]
}
```

A plan with no `pools` has one, `default`. Grants made without a pool go to `default`, or to the plan's first pool when the grant comes from checkout.

## Drawdown order

Work draws from pools in the plan's order. Inside a pool, credits follow the usual [burn order](/concepts/billing#credits): `priority`, then soonest expiry, then promotional before paid, then oldest. When a pool runs out, work continues in the next pool. It is denied with `insufficient_balance` only when every pool is spent.

A [cap](/guides/usage-windows) on a pool can send work onward early, with `on_exhausted: draw_next_pool`.

## Burn multipliers

A multiplier changes how many credits a unit of work costs. Set it on a pool or on a rate, and the two multiply.

| Where                     | Example                                                          |
| ------------------------- | ---------------------------------------------------------------- |
| `pools[].burn_multiplier` | Work drawn from `premium` costs 1.6 times the credits            |
| `rates[].burn_multiplier` | A rate for a larger model costs 2 times as much as the base rate |

**`Config document: plans`**

```json title="Config document: plans"
{
  "plans": [
    {
      "key": "flex_monthly",
      "name": "Flex",
      "billing_mode": "prepaid",
      "currency": "usd",
      "interval": "month",
      "credit_type": "ai_credits",
      "pools": [
        { "key": "included", "burn_multiplier": "1" },
        { "key": "purchased", "burn_multiplier": "1.6" }
      ],
      "rates": [
        { "event_name": "agent.task", "credits_per_unit": "10" },
        { "event_name": "agent.task.large", "credits_per_unit": "10", "burn_multiplier": "2" }
      ]
    }
  ]
}
```

A charge is worked out in base credits, then drawn pool by pool. When a pool can't cover all of it, the covered share is taken at that pool's multiplier and the rest moves to the next pool at its own. With 4 credits left in `included` (multiplier 1), a 10-credit task takes 4 from `included` and the remaining 6 base credits cost 9.6 from `purchased`. `required` on a check is the charge in base credits, and the ledger entries show the credits actually drawn from each pool.

For a multiplier that depends on the model or the request, use a [price rule](/guides/price-rules-and-guardrails) on the rate instead. A rate takes either `price_rule` or `burn_multiplier`.

## Read balances

`GET /v1/customers/{id}/balances` returns each balance with a `pools` array, and the ledger records the `pool` on every entry. `GET /v1/ledger_entries` filters by `pool`.

**`Response: Balance`**

```json title="Response: Balance"
{
  "object": "balance",
  "customer": "cus_9sF2kq81LmQz",
  "credit_type": "ai_credits",
  "posted": "4870",
  "held": "40",
  "limit": "0",
  "available": "4830",
  "pools": [
    { "pool": "included", "posted": "570", "held": "40", "available": "530" },
    { "pool": "purchased", "posted": "4300", "held": "0", "available": "4300" }
  ],
  "as_of": "2026-11-04T13:12:09Z",
  "livemode": false
}
```

`posted`, `held` and `available` at the top are the sums. Holds draw from the pools in order, like work does.

## Rules

* Pool keys are unique on a plan. A grant to a pool the customer's plan doesn't list is `parameter_invalid`.
* `pools`, `allowances` and burn multipliers lock with the rest of the plan's pricing once a customer subscribes.
* Two pools never mix their expiry. A pool's soonest expiry shows as `next_expiry` in the [usage summary](/guides/usage-summary).
* A `per_member` refill adds `amount` to its pool for each member, at the member's first call of a [window](/guides/usage-windows). The members share that pool, and what is left expires with the window, so it never moves to another pool, such as `purchased`. A `per_member` cap holds each member to `amount`.
* Spend limits can name a pool, so you can cap spending on `purchased` credits alone. See [Spend limits](/guides/spend-limits).

## Next steps

* [Usage windows](/guides/usage-windows) refill and cap a pool over time.
* [Credit expiry and breakage](/guides/credit-expiry) covers how long a pool's credits last.
* [Spend limits](/guides/spend-limits) can name a pool.
* [Recipes](/guides/recipes) shows pools in complete plans.