Errors & rate limits
Errors are always JSON, always shaped the same way, regardless of which endpoint produced them.
{
"detail": "Invalid API key"
}
IP-level responses
Before an endpoint's own logic runs, every request is checked against a per-IP request limit shared across /download, /stream, and /health.
| Status | detail | Meaning |
|---|---|---|
| 429 | Too many requests | You've sent too many requests from this IP in a short window. Back off and retry after a short pause. |
| 403 | Your IP has been blocked | This IP was temporarily blocked after repeated abusive traffic. It clears on its own after a cooldown period. |
| 404 | Not found | The path doesn't correspond to a public endpoint. |
Sustained abusive traffic — for example hammering the API without a valid key — can lead to longer or repeated IP blocks. Normal client behavior with reasonable retry/backoff won't come close to these limits.
Key & request errors
| Status | detail |
|---|---|
| 400 | Type must be audio or video |
| 400 | Invalid video URL or ID |
| 400 | Invalid JSON |
| 401 | API key required |
| 401 | Invalid API key |
| 403 | API key is inactive or expired |
| 403 | API key has expired |
| 403 | API key is temporarily blocked |
| 403 | Access denied |
| 429 | Daily quota exhausted |
| 500 | Download failed |
422 validation errors
If a required query parameter is left out entirely — for example calling /download with no type at all, rather than an empty one — the framework rejects the request before it reaches the API logic, returning a standard 422 Unprocessable Entity with a list of what's missing, rather than the { "detail": "…" } shape above.