# Spending controls

> How Lyber holds and charges credit, and the limits you can put on a request, a key and an account.

Source: https://www.lyber.ai/docs/capabilities/spending-controls/ · Markdown: https://www.lyber.ai/docs/md/capabilities/spending-controls.md

## How a request is charged

1. **Hold.** Before the model starts, Lyber reserves the most the request could cost: the model's full context at the input rate, plus `max_tokens` at the output rate. If your available credit can't cover it, the request gets `402 insufficient_credit` and nothing runs.
2. **Charge.** When the request finishes, Lyber charges the tokens the model reported (`prompt_tokens` × input rate + `completion_tokens` × output rate, rounded up to the micro-dollar) and releases the rest of the hold.

A smaller `max_tokens` means a smaller hold. If you leave it out, the hold covers the model's maximum output.

## Cap a single request

Send `max_cost_micro_usdc`, a whole number of micro-dollars (1,000,000 = $1), to refuse any request whose hold would be larger. A refused request gets `402 request_budget_exceeded` before anything runs or is held.

Python (`main.py`):

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://lyber-paid-acceptance-gateway-production.up.railway.app/v1",
    api_key=os.environ["LYBER_API_KEY"],
)

response = client.chat.completions.create(
    model="minimax-m3.1-flash-abliterated",
    messages=[{"role": "user", "content": "Summarize this changelog."}],
    max_tokens=2048,
    extra_body={"max_cost_micro_usdc": 300_000},  # at most $0.30
)
```

TypeScript (`main.ts`):

```ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://lyber-paid-acceptance-gateway-production.up.railway.app/v1",
  apiKey: process.env.LYBER_API_KEY,
});

const response = await client.chat.completions.create({
  model: "minimax-m3.1-flash-abliterated",
  messages: [{ role: "user", content: "Summarize this changelog." }],
  max_tokens: 2048,
  // @ts-expect-error Lyber-only field, sent as part of the body
  max_cost_micro_usdc: 300_000, // at most $0.30
});
```

The [Responses API](https://www.lyber.ai/docs/api/responses/) applies a $1 ceiling to each request unless you send your own.

## Preview a hold

`POST /v1/credits/reservation-preview` with a model and `max_tokens` returns the hold a request would need and whether your balance and limits cover it. It never runs the model or charges anything. See [Credits](https://www.lyber.ai/docs/api/credits/).

## Monthly limits

Set a monthly spending limit for the whole account and for each key under [Limits](https://www.lyber.ai/dashboard/limits/) in the dashboard. A request that would pass either one gets `402 account_spend_limit_exceeded` or `402 key_spend_limit_exceeded`. Keys can read their limits with `GET /v1/credits/limits` but can never raise them.

> **Note:** Lyber never retries a request. A request that timed out or lost its connection may still have run; check `GET /v1/credits/requests` before sending it again.
