> Append .md to any page URL for clean Markdown. Index: https://docs.speechify.ai/llms.txt.
>
> Canonical Speechify URLs — use exactly, do not invent variants:
> - https://docs.speechify.ai — this site (API reference, SDKs, quickstarts)
> - https://speechify.ai — marketing + product site
> - https://platform.speechify.ai — customer dashboard, signup, API keys, billing
> - https://api.speechify.ai — API base URL
> - https://github.com/Speechify-AI: GitHub org for the API (cookbook, demos, CLI). `github.com/speechify` does not exist.
> - https://status.speechify.ai — status + incidents
> - https://speechify.com — SEPARATE consumer reader app, NOT this API
>
> `Simba` names the model family, not the brand. Model ids: `simba-3.2` (English, recommended) and `simba-3.0` (English, German, Spanish, French, Italian and Portuguese; the default). `simba-english` and `simba-multilingual` are retired: a new workspace that sends either gets `400 model_retired`. `SimbaVoice` / `simbavoice.ai` are retired.
>
> Ask, don't scrape. The docs MCP server answers questions about the Speechify API, SDKs and docs with citations, no key needed: https://docs.speechify.ai/_mcp/server (Streamable HTTP, tool `searchDocs`). Setup: https://docs.speechify.ai/build/guides/get-started/connect-mcp

# Spend Limits

> Set a monthly USD spend limit on any Speechify API key. Requests are refused with 402 spend_cap_exceeded once the key reaches its limit; the limit resets each calendar month.

Every API key can carry an optional **monthly spend limit** in US dollars. Once the key's billed
usage in the current calendar month reaches the limit, further requests with that key are refused
until you raise the limit, switch to another key, or the month rolls over.

Spend limits are the blast-radius control for API keys: a leaked key, a runaway script, or an
experimental integration can never spend more than the budget you gave it.

## How it works

* The limit covers **everything the key does**, every billable surface it can reach, in one
  dollar number.
* Spend is measured by the **same billing engine that produces your invoice**, at your plan's
  prices. The number the limit counts is the number you are billed.
* The window is the **calendar month (UTC)**. Limits reset automatically at 00:00 UTC on the 1st.
* Keys without a limit are unaffected. Limits are per key, independent of your workspace balance.

> **Note**
>
> Enforcement runs against billed usage, which trails live traffic by a couple of minutes. A key
> crossing its limit mid-burst can briefly overshoot before it is cut off.

## Setting a limit

Manage limits in the console under **API Keys**: set a limit when creating a key, or open
**Edit** on an existing key to add, raise, lower, or remove one at any time - the change takes
effect immediately and the key secret never changes. Each capped key shows its month-to-date
spend against the limit right in the key list.

## Workspace-wide monthly budget

Per-key limits bound one credential; the **workspace budget** bounds everything. Owners can set
a monthly USD budget in workspace settings (Settings → Workspace). Once the workspace's billed
month-to-date spend - across every API key plus console usage - reaches the budget, new requests
are refused with a `402` whose error `code` is `spend_budget_exceeded`,
until the budget is raised or the month resets (1st, UTC). The two controls compose: a key stops
at its own limit even when the workspace budget has room, and the budget stops everything even
for uncapped keys.

The budget has the same webhook alerts as per-key limits: subscribe an endpoint to
`workspace.spend_budget.warning` (80%) and `workspace.spend_budget.reached` (100%). Each fires
at most once per month for a given budget value (changing the budget re-arms them); `data.object`
is a workspace snapshot with `monthly_budget` and `monthly_spend`, and the crossing details ride
as `data.spend_budget_alert`.

## Project budgets

A project's `monthly_budget` is the ceiling in between: it bounds the work attributed to one project, and an application that models each of its customers as a project uses it as that customer's allowance.
Once the project's billed month-to-date spend reaches it, new billable work attributed to the project is refused with a `402` whose error `code` is `project_spend_limit_exceeded`, distinct from the workspace's `spend_budget_exceeded`.

Subscribe an endpoint to `project.spend_budget.warning` (80%) and `project.spend_budget.reached` (100%) to hear it coming.
They use the same thresholds and the same once-per-month-per-budget-value rule as the workspace pair, so changing the budget re-arms them.
An endpoint scoped to a project receives only that project's events; a workspace-wide endpoint receives every project's.
`data.object` is the project exactly as `GET /v1/projects/{project_id}` returns it, and the crossing details ride as `data.spend_budget_alert`:

```json
{
  "type": "project.spend_budget.warning",
  "data": {
    "object": {
      "id": "proj_...",
      "name": "Acme Corp",
      "monthly_budget": 15,
      "monthly_spend": 12.5,
      "monthly_budget_status": "warning",
      "monthly_budget_remaining": 2.5,
      "archived_at": null,
      "resource_count": 4,
      "created_at": "2026-08-18T18:03:11Z",
      "updated_at": "2026-09-01T09:00:00Z"
    },
    "spend_budget_alert": {
      "threshold_percent": 80,
      "spend": 12.5,
      "resets_at": "2026-10-01T00:00:00Z"
    }
  }
}
```

The same answer is readable without waiting for an event: every project read carries `monthly_budget_status` (`ok`, `warning` or `reached`, on the same thresholds) and `monthly_budget_remaining`, which goes negative by the overshoot once spend has passed the budget.

> **Note**
>
> A crossing is detected by the budget check the next billable request attributed to the project makes, and project alerts pause while the workspace itself is over its own budget, which the workspace events already cover.

## Get warned before a key hits its limit

Workspace webhook endpoints can subscribe to two spend-limit events, so you hear about a
key approaching its budget instead of discovering it through failing requests:

| Event                       | Fires when                                                      |
| --------------------------- | --------------------------------------------------------------- |
| `api_key.spend_cap.warning` | The key's billed spend this month crosses **80%** of its limit  |
| `api_key.spend_cap.reached` | The key's billed spend this month reaches **100%** of its limit |

Each event fires at most once per key per calendar month for a given limit value; changing
the limit re-arms both thresholds against the new value. `data.object` is the API key
exactly as a GET returns it (including `spend_cap` and `spend_cap_remaining`), and the
crossing details ride alongside it as `data.spend_cap_alert`:

```json
{
  "type": "api_key.spend_cap.warning",
  "data": {
    "object": {
      "id": "key_...",
      "name": "prod-mobile",
      "api_key": "sk_...cdef",
      "scopes": ["audio:all"],
      "spend_cap": 50,
      "spend_cap_remaining": 7.5,
      "created_at": "2026-05-14T09:12:00Z"
    },
    "spend_cap_alert": {
      "threshold_percent": 80,
      "spend": 42.5,
      "resets_at": "2026-08-01T00:00:00Z"
    }
  }
}
```

## When a key hits its limit

Requests with the key fail with **HTTP 402** and the error code `spend_cap_exceeded`:

```json
{
  "error": {
    "code": "spend_cap_exceeded",
    "message": "This API key has reached its monthly spend cap. Raise the cap or use a different key; the cap resets on Aug 1 (UTC)."
  },
  "request_id": "..."
}
```

Handle it distinctly from `payment_required`: `payment_required` means the workspace balance
needs a top-up; `spend_cap_exceeded` means this specific key hit the budget you set for it, and
raising the key's limit in the console unblocks it immediately.

> **Note**
>
> In-flight requests are never interrupted. The limit gates new requests only.