---
title: "Error Codes"
description: "API error codes, causes, and solutions"
canonical: "https://docs.ainative.studio/docs/api/errors"
last-updated: "2026-10-03T21:47:10.764Z"
---

# Error Codes

Source: https://docs.ainative.studio/docs/api/errors

> API error codes, causes, and solutions

# Error Codes

All errors return JSON with an `error` object:

```json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Retry after 30 seconds.",
    "retry_after": 30
  }
}
```

## HTTP Status Codes

| Code | Meaning | Common Cause |
|------|---------|-------------|
| 400 | Bad Request | Invalid JSON, missing required fields |
| 401 | Unauthorized | Missing or invalid API key / JWT token |
| 403 | Forbidden | Insufficient permissions — response includes workspace name and suggested API key |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate resource (entity already exists) |
| 422 | Validation Error | Invalid parameter values |
| 429 | Rate Limited | Too many requests — check `Retry-After` header |
| 500 | Server Error | Internal error — contact support |
| 502 | Bad Gateway | Service temporarily unavailable |
| 503 | Service Unavailable | Maintenance or overload |

## Error Codes

| Code | Status | Description | Fix |
|------|--------|-------------|-----|
| `INVALID_API_KEY` | 401 | API key is invalid or expired | Generate a new key at /dashboard/api-keys |
| `TOKEN_EXPIRED` | 401 | JWT token has expired | Refresh the token |
| `RATE_LIMITED` | 429 | Request rate exceeded | Wait for `retry_after` seconds |
| `CREDIT_EXHAUSTED` | 402 | No API credits remaining | Upgrade plan or purchase credits |
| `INSUFFICIENT_CREDITS` | 402 | API key has no chat credits | Top up balance or use a key with credits |
| `PROJECT_NOT_FOUND` | 404 | Project ID doesn't exist | Check project ID |
| `VECTOR_LIMIT_EXCEEDED` | 403 | Vector storage limit reached | Upgrade plan |
| `FILE_TOO_LARGE` | 413 | File exceeds size limit | Check tier limits |
| `VALIDATION_ERROR` | 422 | Request body validation failed | Check parameter types and ranges |
| `upstream_provider_error` | 503 | Upstream AI provider returned an error | Check provider status or retry |

A response carrying a `Deprecation` header means the endpoint you called still works, but is scheduled for removal — see the [API Deprecation Policy](/docs/api/deprecations) for the header contract and notice period.

## Enhanced 403 Responses

Project-scoped 403 errors include actionable context to help you recover:

```json
{
  "error": {
    "code": "PROJECT_NOT_FOUND",
    "message": "Project not found in workspace 'My Startup'",
    "workspace_name": "My Startup",
    "suggested_api_key": "sk_abc1..."
  }
}
```

| Field | Description |
|-------|-------------|
| `workspace_name` | The workspace the authenticated user belongs to |
| `suggested_api_key` | A valid API key prefix for the user's workspace — use this key instead |

:::tip
If you receive a 403 with `suggested_api_key`, switch to that key. This commonly happens when using a `tmp_` key after signing up — your project-scoped `sk_` or `zdb_live_` key is the correct one.
:::

## Rate Limit Headers

Every response includes rate limit headers:

```
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 55
X-RateLimit-Reset: 1700000060
Retry-After: 30
```

## Retry Strategy

```python
import time
import requests

def api_call_with_retry(url, data, max_retries=3):
    for attempt in range(max_retries):
        response = requests.post(url, json=data, headers=HEADERS)
        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 30))
            time.sleep(retry_after)
            continue
        return response
    raise Exception("Max retries exceeded")
```
