Rate limits & quotas
Per-minute and per-day limits by plan, the headers that report them, and how to back off.
Limits are enforced per ACCOUNT, not per key — minting more keys does not buy more throughput, and one noisy key will rate-limit the others. Every response carries the current state, so a well-behaved client never has to guess. The numbers, by plan (the summary above promised them, and for a while this page published none — a developer sizing an integration had to hit the wall to find out where it was): | Plan | Requests/min | Requests/day | Concurrent generations | Account keys | | --- | --- | --- | --- | --- | | Free · Starter | sandbox key only | sandbox key only | 2 (Free) · 3 (Starter) | 1 sandbox | | Creator | 20 | 2,000 | 5 | 2 | | Standard | 60 | 10,000 | 10 | 3 | | Professional | 100 | 10,000 | 15 | 5 | | Business | 500 | 100,000 | 20 | 20 | | Enterprise | 2,000 | unlimited | 50 | 100 | The Concurrent column is a different kind of ceiling from the other two: not a request RATE but how many of your generations may be RUNNING at once, counted per account, not per key (audio generations; video jobs are counted separately against the same number). Submitting past it is not queued server-side — the request answers 429 concurrency_limit_exceeded with a Retry-After header, and the slot frees when one of your in-flight jobs finishes, not when time passes. On Free and Starter the cap governs in-app generations; API keys on those plans are sandbox-only. These are the platform defaults; an account-level override (higher OR lower) can be granted by support without a plan change, and GET /api/v1/account/api-limits always returns the numbers that actually apply to YOUR key.
Authentication
Limits come from the plan of the account that owns the key. Read your own with GET /api/v1/account/api-limits; an admin can raise them per-account without changing your plan.
Create a key in Settings → API Keys. It is shown once, so copy it then. Every example below reads it from $SONICVOX_API_KEY.
Endpoints
Your quotas and recent consumption. Every response from every endpoint also carries the live headers below, so you rarely need to poll this.
- Scope
- analytics:read
- Credits
- 0
curl https://staging.sonicvox.ai/api/v1/usage \
-H "sv-api-key: $SONICVOX_API_KEY"# Headers on EVERY response
x-ratelimit-limit: 100 # requests/minute on this plan
x-ratelimit-remaining: 98 # left in the current window
x-ratelimit-reset: 1786172295 # unix seconds when it resets
x-daily-requests-limit: 10000
x-daily-requests-used: 1
x-credits-remaining: 500000
x-plan: SCALEWhen it fails
Every error carries type, code, message, request_id and a doc_url. Branch on type for retry policy.
| rate_limit_exceeded | Over the per-minute limit. Retry-After tells you how long to wait; the 60-second window starts at your first request and clears all at once, so waiting it out hands back the full allowance. |
| daily_limit_exceeded | Over the daily request allowance. It resets at 00:00 UTC — retrying sooner will not help. |
| insufficient_credits | Not a rate limit: the balance will not cover this request. Nothing was charged. |
| concurrency_limit_exceeded | Your plan's CONCURRENT generation limit (the table's Concurrent column), not the per-minute one. The slot frees when one of your in-flight jobs finishes — fewer requests in flight, not slower ones. |