# Limits, capacity and busy

> The limits on sessions, audio and API calls, and what to do when Kheelona is busy.

Source: https://docs.voice.kheelona.com/concepts/limits/

Some limits are fixed. Some are set for your account by Kheelona: ask the Kheelona team if one gets in your way.

## Sessions

| Limit | Default | Notes |
|---|---|---|
| Session length | 1,800 s | Set per partner by Kheelona, 60 to 3,600 s. A session can ask for less with `max_duration_s`, never more. |
| Idle timeout | 120 s | The longest a session stays open with nobody speaking and nothing playing. Set per partner, 30 to 600 s. Muting pauses the check-in and goodbye counts, not this timeout. A quiet session usually ends sooner: see [Quiet sessions](https://docs.voice.kheelona.com/concepts/sessions.md#quiet-sessions). |
| Client secret | 60 s, single use | See [Sessions](https://docs.voice.kheelona.com/concepts/sessions.md). |
| Reservation | 60 s | A session created but not connected. |
| Concurrent sessions | set per partner | Reserved and live sessions both count. |
| Monthly minutes | set per partner, optional | When it is used up, new sessions are refused with `forbidden`. |
| Languages | 1 to 11 | See [Languages](https://docs.voice.kheelona.com/concepts/languages.md). |
| `instructions` | 4,000 characters | |
| `metadata` | 10 keys, 200 characters per value, 2 KB in all | Stored: no personal data. |
| `end_user_ref` | 128 characters | Letters, digits and `. _ : -` only. |

## Audio and events

| Limit | Value |
|---|---|
| Input audio speed | at most 2 times real time, and at most 1 s ahead of real time |
| Input frame | 10 to 500 ms |
| One WebSocket message | 64 KB; a larger one closes the connection |
| One client event | 8 KB |
| One typed turn (`input.text`) | 2,000 characters |
| Typed turns per session | 5 at once, then 1 per second. A turn beyond that is dropped and the session gets a non-fatal `error` with `rate_limited` (`retryable: true`). Send it again after a second. |
| One spoken turn | 60 s of speech; a longer turn is cut and processed |

## API calls

Limits are per API key.

| Calls | Rate | Burst |
|---|---|---|
| `POST /v1/sessions` | 10 per second | 20 |
| Every other `/v1` call | 20 per second | 40 |

Responses carry `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, so you can slow down before you are
refused. Over the limit you get `429` with `rate_limited` and a `Retry-After`. More than 20 failed authentications a minute from one IP
address are refused for 10 minutes.

A relay normally creates one session per conversation, far below these rates. If a launch will create many sessions at
once, tell us beforehand.

## Capacity and "busy"

Kheelona runs a fixed amount of speaking capacity: people talking and getting replies at the same moment. Kheelona sets it for
the whole service, and sets how many sessions your account may run together.

A new session is checked when you create it, in this order: your account status, your monthly minutes, your concurrent
sessions, then the capacity of the service. You get one of these answers:

- `201`: go ahead.
- `429` `partner_limit_reached`: your account is at its concurrent-session limit. Wait for a session to end, then try
  again. If you need more, ask the Kheelona team.
- `503` `capacity_exhausted`: the service is full right now. The answer has a `Retry-After` of 5 to 30 seconds. Wait that
  long and try again. For a toy, say something like "I'm busy, try again in a moment" from the device itself.
- `503` `capacity_exhausted` with `details.reason` set: the voice service is not running right now.
  `voice_service_starting` means it is waking up: retry after 60 seconds (the answer's `Retry-After`).
  `voice_service_asleep` means it is switched off to save cost: retry after 300 seconds, and tell the Kheelona team if
  it stays asleep when you need it.
- `403` `forbidden`: the account is suspended or the monthly minutes are used up. Retrying will not help.

`GET /v1/health` needs no key and says `capacity: available` or `busy`. It is cached for 5 seconds, so use it to
choose between two messages for the user, not to decide whether a session will succeed: only the create call decides.

See [Errors and retries](https://docs.voice.kheelona.com/guides/errors-and-retries.md) for how to retry.
