Limits, capacity and metering

Base URL https://api.suisse-speech.ch/v1 · X-API-Key

Request 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 reports granted_credits, used_credits, remaining_credits and used_percent. When the credit is used up, new requests are refused with 429 *.entitlement_exhausted until 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.