Rate Limits
Understand per-project request rate limits and concurrency limits across tiers.
Nineninesix enforces two limits, both per project: a request rate (requests per minute) and a concurrency cap (simultaneous streams). They scale by the project's tier.
Tiers
| Tier | Requests / min | Concurrent streams | How to reach it |
|---|---|---|---|
tier1 | 60 | 5 | Default for every new project |
tier2 | 600 | 25 | Automatic once your org's cumulative purchases reach $50 |
tier3 | 6,000 | 100 | High volume — contact us |
A long-lived WebSocket connection spends a single request token at handshake; what bounds its work is the concurrency cap.
Handling 429 Responses
When you exceed a limit you'll receive 429 Too Many Requests with a Retry-After header:
{ "error": "rate_limited", "message": "requests/min limit exceeded for your tier" }Concurrency rejections look like:
{ "error": "concurrent_limit", "message": "concurrent stream limit reached for your tier" }import time
from cartesia import Cartesia
client = Cartesia(api_key="sk_996_your_api_key", base_url="https://api.nineninesix.ai")
def generate(transcript: str, attempt: int = 0):
try:
return client.tts.bytes(
model_id="gepard-1.0",
transcript=transcript,
voice={"mode": "id", "id": "<voice-id>"},
output_format={"container": "wav", "encoding": "pcm_s16le", "sample_rate": 22050},
)
except Exception:
if attempt >= 3:
raise
time.sleep(2 ** attempt)
return generate(transcript, attempt + 1)Credits
Billing is separate from rate limits. Each character of transcript costs 1 credit; $5 buys 1,000,000 characters and credits never expire. When you run out you'll get a 402 payment_required — top up on the Billing page.
Best Practices
- Cache generated audio — don't regenerate the same text repeatedly
- Respect concurrency — pool and reuse streams rather than opening unbounded connections
- Back off on 429 — use the
Retry-Afterheader - Monitor your dashboard — watch usage and balance before hitting limits