| Plan | Requests per minute | Concurrent requests |
| Free | 15 | 1 |
| Developer | 60 | 3 |
| Growth | 300 | 10 |
POST /v1/tts/generatePOST /v1/tts/streamtext messageGET /v1/voices do not count against your limit.123X-RateLimit-Limit: 60 X-RateLimit-Remaining: 58 X-RateLimit-Reset: 1715678460
X-RateLimit-Limit — maximum requests per minute for your plan.X-RateLimit-Remaining — requests left in the current window.X-RateLimit-Reset — Unix timestamp when the window resets.429 Too Many Requests with a Retry-After header:1234567{ "error": { "status_code": 429, "code": "rate_limit_exceeded", "message": "You have exceeded 60 requests per minute. Retry after 23 seconds." } }
error message with
code rate_limit_exceeded and a retry_after_seconds field. The connection
stays open.POST /v1/tts/generate and POST /v1/tts/stream request
counts while it is running, and frees its slot when it finishes (on success or
error).config until the socket
closes — not per text message. An idle-but-open session still holds its slot
because it keeps synthesis capacity reserved.429 Too Many Requests with the code concurrency_limit_exceeded:1234567{ "error": { "status_code": 429, "code": "concurrency_limit_exceeded", "message": "This account already has 3 synthesis requests in flight, which is the maximum allowed at once. Wait for one to finish before starting another." } }
rate_limit_exceeded, this response has no Retry-After header. A
concurrency slot has no fixed reset time — it frees only when one of your
account's other in-flight requests finishes. Retry once an outstanding request
completes.error message with
code concurrency_limit_exceeded.429. Wait until the time indicated by
Retry-After (or X-RateLimit-Reset), then retry with exponential backoff and
jitter.123456789import time from vakyamai import RateLimitError try: client.tts.generate( text="...", model_id="raaga-v1", voice="Archana", language="ta-IN", ) except RateLimitError as exc: time.sleep(exc.retry_after_seconds or 5)