Error Reference¶
All API errors return a consistent JSON format.
Error Response Format¶
| Field | Type | Description |
|---|---|---|
error |
string | Machine-readable error type (e.g. "invalid_token", "insufficient_credits") |
message |
string | Human-readable description of what went wrong |
status_code |
integer | HTTP status code (matches the response status) |
details |
object or null | Additional context — validation errors, reason codes, etc. |
Error Codes¶
400 Bad Request¶
Invalid input or failed validation.
{
"error": "bad_request",
"message": "Registration failed",
"status_code": 400,
"details": { "reason": "email_exists" }
}
Common causes:
| Detail / Reason | Source | Description |
|---|---|---|
privacy_policy_not_accepted |
/auth/register |
Privacy policy must be accepted |
username_exists |
/auth/register |
Username already taken |
email_exists |
/auth/register |
Email already registered |
missing_token |
/auth/confirm |
Confirmation token not provided |
invalid_token |
/auth/confirm, /auth/reset-password |
Token is expired or malformed |
missing_fields |
/auth/reset-password |
Required fields not provided |
file_type must be either 'image' or 'audio' |
/media |
Invalid media file type parameter |
Minimum credit purchase amount is $10 |
/stripe/checkout |
Credit purchase below minimum |
401 Unauthorized¶
Authentication failed or credentials missing.
Common causes:
| Detail | Description |
|---|---|
Not authenticated |
No credentials provided |
Invalid API key |
API key does not exist or is malformed |
Token has been revoked |
Access token was explicitly revoked |
Token has expired. Please log in again. |
JWT access token past expiry |
Invalid token: {error} |
Token decode failure |
Token issued for {env} environment... |
Token/environment mismatch |
Invalid token - missing user ID |
Malformed token payload |
Invalid token type - expected access token... |
Refresh token used where access token required |
User not found |
Token references a deleted user |
Invalid admin API key |
Admin endpoint called with wrong key |
Not authenticated. Access token missing. |
Protected endpoint called without token |
402 Payment Required¶
Insufficient credits to complete the request.
{
"error": "payment_required",
"message": "Insufficient credits for this request",
"status_code": 402,
"details": null
}
Top up credits at indoxhub.com or use BYOK (Bring Your Own Key) to bypass credit billing.
403 Forbidden¶
Authenticated but not authorized for this action.
{
"error": "forbidden",
"message": "Insufficient privileges. Admin access required.",
"status_code": 403,
"details": null
}
Common causes:
| Detail | Description |
|---|---|
User account is disabled |
Account suspended or deactivated |
Insufficient privileges. Admin access required. |
Non-admin calling an admin endpoint |
404 Not Found¶
Requested resource does not exist.
Common causes:
| Detail | Description |
|---|---|
Unknown provider: {provider} |
Provider name not recognized |
JSON file not found for {provider} |
Provider config missing |
Alias '{alias_name}' not found |
Model alias does not exist |
Media file not found |
File ID not in database |
Media file has been deleted |
File was soft-deleted |
Stream not found |
Streaming session expired or invalid |
409 Conflict¶
Resource already exists or state conflict.
{
"error": "conflict",
"message": "Registration failed",
"status_code": 409,
"details": { "reason": "email_already_linked" }
}
Returned when an email is already linked to an OAuth provider during registration.
500 Internal Server Error¶
Unexpected server-side failure.
{
"error": "internal_server_error",
"message": "Registration failed",
"status_code": 500,
"details": { "reason": "server_error" }
}
Common causes:
| Detail / Reason | Source | Description |
|---|---|---|
user_creation_failed |
/auth/register |
Database write failed during signup |
activation_failed |
/auth/confirm |
Account activation failed |
update_failed |
/auth/reset-password |
Password update failed |
server_error |
Various auth endpoints | Generic catch-all |
Pricing calculation failed: {error} |
/stripe/checkout |
Stripe pricing API error |
Checkout session creation failed: {error} |
/stripe/checkout |
Stripe session error |
Failed to retrieve media files: {error} |
/media |
Storage backend error |
503 Service Unavailable¶
A required external service is down or misconfigured.
{
"error": "service_unavailable",
"message": "Payment processing is currently unavailable",
"status_code": 503,
"details": null
}
Returned when Stripe or another critical integration is unreachable. Retry after a short delay.
Custom Exception Classes¶
The backend uses these internal exceptions (defined in app/exceptions.py) which are converted to HTTP errors at the router layer:
| Exception | Typical HTTP Code | Description |
|---|---|---|
ProviderNotFoundError |
404 | AI provider not configured |
ModelNotFoundError |
404 | Model ID not recognized |
ModelNotAvailableError |
400 | Model exists but is currently unavailable |
InvalidParametersError |
400 | Request parameters failed validation |
RequestError |
500 | Upstream provider request failed |
InsufficientCreditsError |
402 | User balance too low |
RateLimitError |
429 | Too many requests |
Troubleshooting¶
"Not authenticated" (401)¶
Cause: Missing or malformed Authorization header.
Fix: Include a valid bearer token or API key:
"Token has expired" (401)¶
Cause: JWT access token has passed its expiry time.
Fix: Refresh your token using the refresh endpoint, or generate a new API key from the dashboard.
"Insufficient credits" (402)¶
Cause: Your account balance is too low for the requested operation.
Fix: Add credits at indoxhub.com, or switch to BYOK mode to use your own provider API keys. See BYOK Support.
"Insufficient privileges" (403)¶
Cause: Your account does not have admin role.
Fix: Admin endpoints are restricted. Use standard user endpoints, or contact your organization admin.
"User account is disabled" (403)¶
Cause: Account has been suspended.
Fix: Contact support to resolve account status.
"Stream not found" (404)¶
Cause: The streaming session ID is expired or was never created.
Fix: Start a new streaming request. Streaming sessions are ephemeral and expire shortly after completion.
"Payment processing unavailable" (503)¶
Cause: Stripe integration is temporarily unreachable.
Fix: Wait 30-60 seconds and retry. If the issue persists, check IndoxHub status or contact support.