Rate limits & errors
Soft limits, response shapes, and common failure modes.
Limits are intentional but not aggressive — enough to keep the platform healthy while staying friendly for automation.
Limits (per minute)
| Scope | Limit |
|---|---|
| Per API key | ~120 requests |
| Upload init / part signing per key | ~60 |
| Per IP (all API keys) | ~240 |
Responses include X-RateLimit-Remaining when Redis-backed limiting is enabled.
When limited:
{
"ok": false,
"error": {
"message": "Rate limit exceeded — try again shortly",
"code": "rate_limited"
}
}Backoff gently (a second or two) and retry.
Envelope
Success:
{ "ok": true, "data": { } }Error:
{
"ok": false,
"error": {
"message": "Human readable message",
"code": "machine_code",
"details": {}
}
}Common codes
| Status | Code | When |
|---|---|---|
400 | validation_error | Body failed schema checks |
400 | size_mismatch | Uploaded object size ≠ declared size |
400 | object_missing | Complete called before bytes landed |
400 | invalid_state | File is not pending |
401 | unauthorized | Bad or missing API key |
403 | quota_exceeded | Not enough storage |
404 | not_found | File or folder missing |
429 | rate_limited | Soft limit hit |
Retention
Uploaded files follow the same product rules as the dashboard: 30-day retention, plan quotas, and MIME denylists still apply.