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

# Update a plan

PATCH https://api.runledger.co/v1/plans/{plan}
Content-Type: application/json

`name`, `description` and `metadata` can always change. Pricing and limits can change only while the plan has no subscriptions, and otherwise the request fails with `plan_locked`.

Reference: https://docs.runledger.co/api-reference/plans/update

## Authentication

- `Authorization` header (bearer token, required) — A secret key (`rl_sk_test_...`, `rl_sk_live_...`) or a restricted key with limited scopes (`rl_rk_test_...`, `rl_rk_live_...`). A restricted key can carry `agent: true` and an `expires_at`, and is what a coding agent should hold. Keys end in a checksum so secret scanners can recognize them. People create, roll and revoke keys in the dashboard; `GET /v1/api_keys` lists them, masked.

## Request

### Path parameters

- `plan` (string, required) — The plan ID (`plan_...`) or key.

### Body (application/json)

This endpoint expects an UpdatePlanRequest.

- `name` (string, optional)
- `description` (string, optional, nullable)
- `recurring_fee` (Money, optional, nullable) — An amount of money in the currency's minor unit.
- `included_credits` (IncludedCredits, optional, nullable) — Prepaid. Credits granted at the start of each period.
- `top_up` (TopUpSettings, optional, nullable) — Prepaid. Lets customers buy more credits through checkout.
- `allowances` (list of Allowance, optional) — Refills and caps on the plan's balance. See [Usage windows](/guides/usage-windows).
- `pools` (list of PoolDefinition, optional) — Named balance pools, in drawdown order. See [Pools](/guides/pools).
- `per_seat` (boolean, optional) — `recurring_fee` and `included_credits` are per seat, multiplied by the subscription's `quantity`. Default false.
- `default_spend_limit` (PlanDefaultSpendLimit, optional, nullable) — The spend limit each new subscription on the plan starts with. A customer-set limit may replace it, up to `ceiling`.
- `overdraft_limit` (string, optional, nullable)
- `credit_limit` (Money, optional, nullable) — An amount of money in the currency's minor unit.
- `minimum_commitment` (Money, optional, nullable) — An amount of money in the currency's minor unit.
- `invoice_grace_period` (string, optional, nullable)
- `rates` (list of PlanRate, optional) — Replaces the whole list.
- `metadata` (map from string to string, optional) — Up to 50 keys of your own, with keys up to 40 characters and values up to 500 characters.

## Response

### 200

The updated plan.

- `id` (string, required)
- `object` ("plan", required)
- `key` (string, required)
- `name` (string, required)
- `status` (enum, required)
  - Allowed values: `active`, `archived`
- `billing_mode` (enum, required) — `prepaid`: a credit balance that must cover charges, topped up or granted in advance. `postpaid`: charges accrue in money and are invoiced at period end.
  - Allowed values: `prepaid`, `postpaid`
- `currency` (string, required)
- `interval` (enum, required)
  - Allowed values: `month`, `year`
- `rates` (list of PlanRate, required)
- `has_subscriptions` (boolean, required) — Once true, pricing can't change.
- `metadata` (map from string to string, required) — Up to 50 keys of your own, with keys up to 40 characters and values up to 500 characters.
- `livemode` (boolean, required)
- `created_at` (datetime, required)
- `description` (string, optional)
- `credit_type` (string, optional)
- `recurring_fee` (Money, optional) — An amount of money in the currency's minor unit.
- `included_credits` (IncludedCredits, optional) — Prepaid. Credits granted at the start of each period.
- `top_up` (TopUpSettings, optional) — Prepaid. Lets customers buy more credits through checkout.
- `allowances` (list of Allowance, optional) — Refills and caps on the plan's balance. See [Usage windows](/guides/usage-windows).
- `pools` (list of PoolDefinition, optional) — Named balance pools, in drawdown order. See [Pools](/guides/pools).
- `per_seat` (boolean, optional) — `recurring_fee` and `included_credits` are per seat, multiplied by the subscription's `quantity`. Default false.
- `default_spend_limit` (PlanDefaultSpendLimit, optional) — The spend limit each new subscription on the plan starts with. A customer-set limit may replace it, up to `ceiling`.
- `overdraft_limit` (string, optional)
- `credit_limit` (Money, optional) — An amount of money in the currency's minor unit.
- `minimum_commitment` (Money, optional) — An amount of money in the currency's minor unit.
- `invoice_grace_period` (string, optional)
- `actor` (Actor, optional) — Who last changed the plan.

## Errors

### 400 Bad Request Error

The request was malformed or a parameter was invalid. A configuration that fails validation, such as two equally specific overrides with overlapping dates, returns `config_invalid`.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 401 Unauthorized Error

The API key is missing, invalid or revoked.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 403 Forbidden Error

The key can't do this. A restricted or agent key lacks the scope (`insufficient_scope`, with `required_scope`), a live key called a sandbox-only endpoint, an agent tried a live config write that needs a proposal (`proposal_required`), or something only a signed-in person can do.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 404 Not Found Error

No object with that ID exists in this environment.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 409 Conflict Error

The object is in a state that doesn't allow this (`invalid_state`, for example approving a stale config proposal or deleting a price rule a plan rate still uses), or a request with the same idempotency key is still in progress.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 429 Too Many Requests Error

Too many requests. Wait for the number of seconds in `Retry-After`.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 500 Internal Server Error

Something went wrong on Runledger's side. Safe to retry with the same idempotency key.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

## Types

### Money

An amount of money in the currency's minor unit.

- `amount` (integer, required) — Minor units. 1500 is US$15.00; 1500 is ¥1,500.
- `currency` (string, required) — Lowercase ISO 4217 code.

### IncludedCredits

Prepaid. Credits granted at the start of each period.

- `amount` (string, required)
- `pool` (string, optional) — The pool (key) the credits join. Defaults to the plan's first pool.
- `rollover` (enum, optional, default: none) — What happens to unused included credits at period end.
  - Allowed values: `none`, `all`, `capped`
- `rollover_cap` (string, optional) — `capped` only: the most that carries over.

### TopUpSettings

Prepaid. Lets customers buy more credits through checkout.

- `unit_amount_decimal` (string, required) — Price per credit, in minor units of the plan currency.
- `minimum_credits` (string, optional)
- `maximum_credits` (string, optional)
- `pool` (string, optional) — The pool (key) purchased credits join. Defaults to the plan's last pool.
- `credits_expire_in` (string, optional) — How long purchased credits last, as an ISO 8601 duration from `P1D` to `P10Y`. The grant gets that `expires_at` when payment completes. Leave it out and top-up credits expire after one year (`P1Y`). A checkout session can override it. Setting an expiry that is lawful where your customers are is your responsibility.
- `low_balance_at` (string, optional) — Send `balance.low` when the pool's available balance falls to this or below, as a decimal string.
- `auto` (TopUpAutoSettings, optional) — Whether customers on the plan may have an auto top-up, and the most they can set.

### Allowance

A refill or a cap on a plan's prepaid balance. A `refill` grants `amount` into `pool` at the start of each window, as a credit grant with `source: allowance` that expires at the window's end unless `rollover` keeps some. A `cap` grants nothing and limits how much of the pool can be consumed in the window. A plan can hold several, and consumption counts against every window that applies: `check()` allows work only if each has room.

- `key` (string, required) — Unique on the plan. Webhooks and the usage summary name the allowance by it.
- `kind` (enum, required)
  - Allowed values: `refill`, `cap`
- `amount` (string, required) — Credits granted per window (`refill`) or the most that may be consumed per window (`cap`), as a decimal string.
- `window` (AllowanceWindow, required) — When an allowance refills, or the range a cap counts consumption over. `fixed` windows reset on a boundary. A `session` window opens at the first consumption after the previous one closed and lasts `duration`, like a five-hour session. A `sliding` window counts consumption over the trailing `duration`, and only a `cap` can use it.
- `pool` (string, optional) — The pool (by key) the allowance feeds or limits. A `refill` defaults to the plan's first pool, or `default` when the plan has none. A `cap` with no `pool` counts consumption from every pool.
- `scope` (enum, optional, default: customer) — `customer`: one window for the customer, shared by everyone in the organization. `per_member`: each distinct `member_id` gets its own window, and a refill grants `amount` for each member at the member's first `check()` or `track()` of the window. The members' refills land in the allowance's pool, which every member draws on, and a refill's window reports what its member used without capping them; a `per_member` cap holds each member to `amount`.
  - Allowed values: `customer`, `per_member`
- `rollover` (enum, optional, default: none) — `refill` allowances on `fixed` windows. What happens to unspent credits when the window ends. `all` and `capped` move them to a new grant with `source: rollover`.
  - Allowed values: `none`, `all`, `capped`
- `rollover_cap` (string, optional) — `capped` only: the most that carries over.
- `rollover_expires_after` (string, optional) — How long a rollover grant lasts, as an ISO 8601 duration. Default: until the end of the next window.
- `priority` (integer, optional, default: 50) — `refill` only. The priority of the grants the allowance creates. Lower numbers are drawn first inside a pool.
- `on_exhausted` (enum, optional, default: block) — `cap` only. What happens when the window is full. `block` (the default): `check()` denies the work with `allowance_exhausted`. `draw_next_pool`: skip the capped pool and draw from the pools after it in the plan's order, so a cap on `included` sends work to `purchased`. It needs `pool` to be set.
  - Allowed values: `block`, `draw_next_pool`
- `alert_at` (list of string, optional) — Decimals from 0 to 1. A webhook `usage.threshold_reached` is sent the first time `percent_used` reaches each one in a window. `["0.8", "1"]` is 80% and 100%.

### PoolDefinition

A named balance pool on a plan. The order of `pools` on the plan is the drawdown order. A pool is a balance pool and has nothing to do with the provider names in the price catalog.

- `key` (string, required)
- `name` (string, optional) — A label for dashboards and the customer view.
- `burn_multiplier` (string, optional) — Multiplies the credits charged when work is drawn from this pool. At `"1.6"`, a unit that costs 10 credits from another pool costs 16 here. Default `"1"`.

### PlanDefaultSpendLimit

The spend limit each new subscription on the plan starts with. A customer-set limit may replace it, up to `ceiling`.

- `amount` (Money, required) — An amount of money in the currency's minor unit.
- `ceiling` (Money, optional) — An amount of money in the currency's minor unit.
- `period` (SpendLimitPeriod, optional)
- `counts` (enum, optional, default: paid_usage) — What counts toward the limit. `paid_usage`: the money value of consumption drawn from paid credits and overage, so included and promotional usage keeps working. `all_usage`: the money value of everything. Buying credits never counts.
  - Allowed values: `paid_usage`, `all_usage`
- `action` (enum, optional, default: warn) — `warn` adds warnings and a webhook. `block` also denies in `check()`.
  - Allowed values: `warn`, `block`
- `alert_at` (list of string, optional)

### PlanRate

The price of one usage event or one outcome. Set exactly one of `event_name` or `outcome_definition`. Prepaid plans use `credits_per_unit`; postpaid plans use `unit_amount_decimal`, and may give each period a free `included_quantity`. A rate for an `event_name` can use `price_rule` instead of a fixed amount.

- `event_name` (string, optional) — A usage event, charged per unit of `quantity`.
- `outcome_definition` (string, optional) — An outcome definition (ID or key), charged per confirmed outcome.
- `credits_per_unit` (string, optional) — Prepaid. Credits per unit, as a decimal string.
- `unit_amount_decimal` (string, optional) — Postpaid. Minor units of the plan currency per unit, as a decimal string.
- `price_rule` (string, optional) — A price rule (ID or key) that works out the price from the event's quantity and properties. Use it instead of `credits_per_unit` or `unit_amount_decimal`, on an `event_name` rate. The rule's currency must be the plan's. The plan follows the rule's version in force when each event happens.
- `included_quantity` (string, optional) — Postpaid. Units per period charged at no cost before `unit_amount_decimal` applies, as a decimal string.
- `overage_unit_amount_decimal` (string, optional) — Postpaid. Minor units per unit past `included_quantity`. Defaults to `unit_amount_decimal`. Those units invoice as `overage` lines.
- `burn_multiplier` (string, optional) — Prepaid. Multiplies this rate's credits, on top of the pool's `burn_multiplier`. At `"2"`, a rate of 10 credits costs 20. Default `"1"`. Use it for a model that costs more than others.
- `description` (string, optional) — The label on invoices.

### Actor

Who made a change. Runledger fills it in from the credential, so a client can't claim to be someone else: an API key always acts as itself, the dashboard calls the API as the signed-in person, and the MCP server passes the client's name and the person it acts for. A request that sends a `Runledger-Actor` header is refused with `400 parameter_unknown`.

- `type` (enum, required) — `user`: a signed-in person, including a person at Runledger support acting in your account, whose `name` reads `Runledger support`. `agent`: an agent connected through an OAuth session or an agent key. `key`: any other API key. `rule`: a reversal rule. `system`: Runledger itself, such as a clock.
  - Allowed values: `user`, `agent`, `key`, `rule`, `system`
- `id` (string, optional) — The user, key or agent session ID. Left out for `rule` and `system`, except a change a customer makes on the customer view, which carries the customer session's ID.
- `name` (string, optional) — A display name, such as a person's name, a key's name or the MCP client.
- `on_behalf_of` (string, optional) — The person an agent acts for, when known.
- `client` (string, optional) — The software that made the call, such as an MCP client or SDK.

### ConfigIssue

A problem or warning about a part of a configuration document.

- `code` (string, required) — A stable code. New codes may be added.
- `message` (string, required)
- `path` (string, optional) — Where in the document, as a dotted path.

### ErrorResponseBlockedByItems

- `object` (enum, required) — The kind of object in the way: a routing rule, or a customer with a `payment_provider` override.
  - Allowed values: `routing_rule`, `customer`
- `id` (string, required) — The object's ID, `rr_...` for a routing rule and `cus_...` for a customer.

### TopUpAutoSettings

Whether customers on the plan may have an auto top-up, and the most they can set.

- `allowed` (boolean, optional, default: false)
- `maximum_monthly_limit` (Money, optional) — The highest `monthly_limit` a customer's auto top-up can have.

### AllowanceWindow

When an allowance refills, or the range a cap counts consumption over. `fixed` windows reset on a boundary. A `session` window opens at the first consumption after the previous one closed and lasts `duration`, like a five-hour session. A `sliding` window counts consumption over the trailing `duration`, and only a `cap` can use it.

- `type` (enum, required)
  - Allowed values: `fixed`, `session`, `sliding`
- `duration` (string, required) — An ISO 8601 duration from `PT1H` to `P1Y`, such as `PT5H`, `P1D`, `P1W` or `P1M`.
- `anchor` (enum, optional, default: billing_period) — `fixed` windows only. `billing_period`: the subscription's period start. `subscription_start`: the day the subscription started. `calendar`: UTC midnight, Monday for a week, the first for a month. `customer`: a stable reset instant chosen per customer when the subscription starts, so customers' windows don't all reset together. Default `billing_period`.
  - Allowed values: `billing_period`, `subscription_start`, `calendar`, `customer`

### SpendLimitPeriod

- `duration` (enum, optional, default: P1M)
  - Allowed values: `P1D`, `P1W`, `P1M`
- `anchor` (enum, optional, default: calendar) — `calendar`: UTC midnight, Monday for a week, the first for a month. `billing_period`: the customer's subscription period. `customer`: a stable reset instant per customer.
  - Allowed values: `calendar`, `billing_period`, `customer`

## Examples

**Request**

```json
{}
```

**Response**

```json
{
  "id": "plan_8hJ2kL5zXc",
  "object": "string",
  "key": "enterprise_monthly",
  "name": "string",
  "status": "active",
  "billing_mode": "prepaid",
  "currency": "string",
  "interval": "month",
  "rates": [
    {
      "event_name": "agent.task",
      "outcome_definition": "chat_resolution",
      "credits_per_unit": "10",
      "unit_amount_decimal": "95",
      "price_rule": "video_cost_plus",
      "included_quantity": "1000",
      "overage_unit_amount_decimal": "120",
      "burn_multiplier": "1",
      "description": "Chat resolutions"
    }
  ],
  "has_subscriptions": true,
  "metadata": {},
  "livemode": true,
  "created_at": "2024-01-15T09:30:00Z",
  "description": "string",
  "credit_type": "string",
  "recurring_fee": {
    "amount": 1500,
    "currency": "usd"
  },
  "included_credits": {
    "amount": "5000",
    "pool": "included",
    "rollover": "none",
    "rollover_cap": "2000"
  },
  "top_up": {
    "unit_amount_decimal": "1",
    "minimum_credits": "1000",
    "maximum_credits": "1000000",
    "pool": "purchased",
    "credits_expire_in": "P1Y",
    "low_balance_at": "1000",
    "auto": {
      "allowed": false,
      "maximum_monthly_limit": {
        "amount": 1500,
        "currency": "usd"
      }
    }
  },
  "allowances": [
    {
      "key": "weekly",
      "kind": "refill",
      "amount": "1500",
      "window": {
        "type": "fixed",
        "duration": "P1W",
        "anchor": "billing_period"
      },
      "pool": "included",
      "scope": "customer",
      "rollover": "none",
      "rollover_cap": "500",
      "rollover_expires_after": "P1M",
      "priority": 50,
      "on_exhausted": "block",
      "alert_at": [
        "0.8",
        "1"
      ]
    }
  ],
  "pools": [
    {
      "key": "included",
      "name": "Included usage",
      "burn_multiplier": "1"
    }
  ],
  "per_seat": true,
  "default_spend_limit": {
    "amount": {
      "amount": 1500,
      "currency": "usd"
    },
    "ceiling": {
      "amount": 1500,
      "currency": "usd"
    },
    "period": {
      "duration": "P1M",
      "anchor": "calendar"
    },
    "counts": "paid_usage",
    "action": "warn",
    "alert_at": [
      "0.75",
      "0.9",
      "1"
    ]
  },
  "overdraft_limit": "string",
  "credit_limit": {
    "amount": 1500,
    "currency": "usd"
  },
  "minimum_commitment": {
    "amount": 1500,
    "currency": "usd"
  },
  "invoice_grace_period": "string",
  "actor": {
    "type": "user",
    "id": "usr_4tN8vB2cXk",
    "name": "Claude Code",
    "on_behalf_of": "usr_4tN8vB2cXk",
    "client": "claude-code"
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.runledger.co/v1/plans/enterprise_monthly"

payload = {}
headers = {
    "Authorization": "Bearer <api_key>",
    "Content-Type": "application/json"
}

response = requests.patch(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.runledger.co/v1/plans/enterprise_monthly';
const options = {
  method: 'PATCH',
  headers: {Authorization: 'Bearer <api_key>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.runledger.co/v1/plans/enterprise_monthly"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("PATCH", url, payload)

	req.Header.Add("Authorization", "Bearer <api_key>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.runledger.co/v1/plans/enterprise_monthly")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <api_key>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.patch("https://api.runledger.co/v1/plans/enterprise_monthly")
  .header("Authorization", "Bearer <api_key>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://api.runledger.co/v1/plans/enterprise_monthly', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Bearer <api_key>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.runledger.co/v1/plans/enterprise_monthly");
var request = new RestRequest(Method.PATCH);
request.AddHeader("Authorization", "Bearer <api_key>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <api_key>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.runledger.co/v1/plans/enterprise_monthly")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```