# Pricing and billing

A fixed price per generation, held at create and charged only on success. Prepaid balance topped up with USDT.

You pay a **fixed price per generation**, set per effect and variant. There is no subscription, no per-second metering and no charge for failures.

## Prices

Every variant in `GET /effects` carries its `price_micros`, and `GET /prices` returns the whole list at once:

```json
{
  "object": "price_list",
  "version": 3,
  "effective_at": "2026-10-01T00:00:00Z",
  "currency": "USD",
  "next": null,
  "data": [
    { "effect": "EFFECT_SLUG", "variant_key": "5s_640p", "price_micros": 100000 }
  ]
}
```

Amounts are integer **micro-USD**: `100000` is $0.10 and `1000000` is $1.00. Use integers end to end; never convert through floating point.

The price is fixed when you create a generation (`price_micros` and `price_list_version` on the generation), so a price change never affects work already queued.

### Price changes

New prices are announced at least 7 days ahead. `GET /prices` shows the upcoming version in `next`, and a [`price.changed`](/docs/webhooks/#pricechanged) webhook lists every affected variant.

## Holds and charges

Your balance has two parts: `balance_micros` (money in the account) and `held_micros` (reserved for generations in flight). What you can spend is `available_micros = balance - held`.

| Moment | What happens |
|---|---|
| Create | The price is **held**. If `available_micros` is lower than the price, the create answers `402 insufficient_balance` |
| Success | The hold becomes a **charge** |
| Failure on our side | The hold is **released**. You pay nothing |
| `input_rejected` | Released. You pay nothing |
| Cancel while `queued` | Released. You pay nothing |
| Cancel while `processing` | Charged, because the GPU time was spent |

`charged_micros` on each generation shows the final amount: 0 until charged, then the price.

## Top-ups

The balance is prepaid. Top up in the dashboard under **Billing** with **USDT**: you get an invoice with an address and amount, and the balance is credited **1:1 in USD** once the payment is confirmed on chain. A [`balance.topped_up`](/docs/webhooks/#balancelow-and-balancetopped_up) webhook fires when the credit lands.

Set a low-balance threshold in the dashboard to get a `balance.low` webhook and an email before you run dry.

## Usage and reporting

`GET /usage?start=...&end=...` returns daily or hourly buckets of spend, counts of succeeded, failed and canceled generations, and p50 and p95 time to result. Group by `type`, `effect` or `api_key` to split costs across your own products or customers. The dashboard shows the same data with invoices and the full ledger.

Test-mode generations never touch your balance.
