Limits, capacity and metering
https://api.suisse-speech.ch/v1 · X-API-KeyRequest rate
Per account, shared by all of its keys (sandbox keys included): 600
requests/minute and 25 requests/second for ordinary requests, and a
separate 600 session opens/minute for realtime sessions. Exceeding any of
them returns 429 with Retry-After; every answer carries
X-Suisse-RateLimit-Remaining.
Opening a realtime session is budgeted separately on purpose. A burst rule exists to stop a client hammering an endpoint; opening fifty streams at once is not hammering anything, it is the product working. The ceiling on simultaneous sessions is the concurrency limit below, which is the right control for that.
Frames inside an open session are not counted as requests.
Concurrency
The service admits a bounded number of simultaneous requests and refuses the
rest with 429 and Retry-After, rather than queueing them. A queue would
convert a capacity problem into a latency problem for the requests that did
get in.
Two different things can refuse you, and they need different responses, so they have different error codes:
| code | meaning | what to do |
|---|---|---|
*.plan_limit_reached |
your plan’s ceiling on simultaneous requests | reduce your parallelism, or raise the limit: error.detail states the number and where to ask |
*.capacity |
the service is momentarily full (error.detail is service_capacity or host_load) |
back off and retry; this is transient |
The first is a commercial conversation, the second is a retry.
{"error":{"code":"tts.plan_limit_reached",
"message":"This plan's limit for simultaneous requests is reached. A higher limit is available on request.",
"detail":"Limit 2 simultaneous requests. Contact your account manager to raise the concurrent-request limit.",
"request_id":"req_…"}}
On a WebSocket the handshake has no body, so the same information arrives as an
X-Suisse-Capacity-Reason header on the 429 before the socket closes.
Your own ceiling is in your_plan in GET /capabilities:
"your_plan": { "concurrent_requests": 2, "source": "plan",
"upgrade": "Contact your account manager to raise the concurrent-request limit." }
source is plan when a limit has been agreed for your account, and
service_default when you are on the standard allowance. A sandbox key has a
fixed slice of 5 simultaneous requests of its own (source: sandbox), counted
apart from the account’s live traffic: sandbox requests never take a live slot,
and live sessions never refuse the sandbox.
GET /capabilities reports the current ceilings under capacity. These are
what the deployment enforces today, not a contractual entitlement. If you
need a higher figure, it has to be agreed and provisioned, not discovered by
pushing until you see 429s. Back off properly on 429 rather than retrying
tightly: the limit is there to protect the latency of the sessions that did get
in.
Voice agents
A voice agent session counts as one simultaneous request for its whole length
(your_plan in GET /capabilities; a sandbox key has 5 of its own), and opening
one counts against the 600 session opens per minute above. Inside an open session
these limits apply:
| limit | value |
|---|---|
| audio you send | at most 1.2 times real time (burst of 2 s); the excess is dropped |
| frames | at most 100 per second, text and binary together, every frame counted (also oversized and unreadable ones); a text frame and a binary frame at most 64 KB (larger: 1009); more than 50 refused frames in 10 s end the session with 1008 |
| control messages | at most 20 per second |
reply, say and text.input together |
at most 30 per minute |
config.update and context.add |
at most 10 and 50 per session |
tool.result |
at most 16,000 characters, within 30 seconds of the tool.call |
| silence on the socket | no audio and no message for 120 seconds ends the session |
| session length | max_duration_s, 60 to 1800 seconds, default 900 |
A message over a limit is answered with an error and dropped, the session goes
on; errors that do not end the session come at most once per code per second. Prepaid credit is held per session for its length, so sessions running at the
same time share the balance and never overdraw it. Instructions, tools and the other size limits are in
Voice agents.
Metering
Both directions are metered in audio seconds, measured to the second, with
no minimum per request: the length of the recording you send for
recognition, or of the speech we produce. Voice agents
are metered per second of connected session time, from session.ready until
the session ends, at CHF 0.33 per minute (CHF 19.80 per hour); a start that never
reaches session.ready costs nothing. Requests that fail are not billed,
and sandbox traffic never is.
GET /v1/usage returns what this key has consumed, read from the billing
ledger rather than from the rate limiter’s expiring counters: the same numbers
an invoice is built from, in the same unit.
curl -H "X-API-Key: $SUISSE_SPEECH_KEY" \
'https://api.suisse-speech.ch/v1/usage?from=2026-09-01&granularity=day'
It reports the window total, a breakdown by direction and mode, an optional daily series, and any allowance in force.
Start credit and prepaid credit
- Start credit. A new account starts with free credit for 60 minutes of speech: one hour of realtime text-to-speech, to spend on any service at its own rate. It does not expire and is part of the prepaid credit below.
- Top-ups. Buy credit in the console under Credit & alerts, with TWINT or card. It is added as soon as the payment is confirmed and does not expire.
- Prepaid credit. An account with credit sees an entry of kind
credit: a balance stated in credits that all services draw on, each at its own rate per hour of audio (listed in the console under Credit & alerts). The entry reportsgranted_credits,used_credits,remaining_creditsandused_percent. When the credit is used up, new requests are refused with429 *.entitlement_exhausteduntil it is topped up; requests in progress are completed. Every user of the account is notified by e-mail when 80 % and when 95 % of the credit is used.
A daily audio budget also applies, per account and per direction (synthesis and
recognition), counted in UTC days; a sandbox key has a budget of its own.
usage_today in GET /capabilities and today in GET /usage show where you
stand in both directions, and limits shows your own daily figures. Exhausting
it returns 429 *.rate_limited with a detail saying so and Retry-After set
to the seconds until 00:00 UTC.
Latency
Expected figures on a warm service:
| p50 | p95 | |
|---|---|---|
| TTS first audio (realtime) | 0.48 s | 0.58 s |
TTS batch, whole request (short text), swift |
1.44 s | 1.87 s |
TTS batch, whole request, studio |
about 1.3 to 1.5 × the length of the audio; a short sentence takes 3 to 6 s | |
| STT partial lag | 0.07 s | 0.13 s |
STT final after finalize or audio.end, on the service |
0.03 s | 0.07 s |
| STT batch, whole request | ≈ 0.87 × the length of the audio |
Measured on 3 September 2026 on production; the STT final on 10 October 2026 on
2,400 telephone turns, from the finalize or audio.end arriving to the last
final leaving, without the network between you and us. Counted from the end of
speech, add the silence your voice activity detection waits for before it sends
finalize, or with endpointing the time the recogniser takes to hold the turn
to be over (speech-to-text).
Realtime Swiss German dialect synthesis starts slightly later, typically 0.6 to
0.7 s to first audio. Measure on your own traffic before you commit to a latency
budget.