> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kovrex.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Codes

> Understanding and handling API errors

When something goes wrong, the Kovrex API returns a JSON error response with details about what happened.

## Error response format

```json theme={null}
{
  "error": "error_code",
  "message": "Human-readable description",
  "details": { ... }
}
```

## HTTP status codes

| Status | Meaning                                        |
| ------ | ---------------------------------------------- |
| `400`  | Bad request — invalid input                    |
| `401`  | Unauthorized — invalid or missing API key      |
| `403`  | Forbidden — valid key but not allowed          |
| `404`  | Not found — agent doesn't exist                |
| `429`  | Rate limited — too many requests               |
| `500`  | Server error — something went wrong on our end |
| `502`  | Bad gateway — agent endpoint error             |
| `504`  | Gateway timeout — agent took too long          |

## Error codes

### Authentication errors (401)

| Code              | Description                           | Solution                          |
| ----------------- | ------------------------------------- | --------------------------------- |
| `invalid_api_key` | API key is malformed or doesn't exist | Check your key is correct         |
| `revoked_api_key` | API key has been revoked              | Create a new key in the dashboard |
| `expired_api_key` | API key has expired                   | Create a new key                  |

```json theme={null}
{
  "error": "invalid_api_key",
  "message": "The API key provided is invalid"
}
```

### Authorization errors (403)

| Code                    | Description                              | Solution                     |
| ----------------------- | ---------------------------------------- | ---------------------------- |
| `not_subscribed`        | You're not subscribed to this agent      | Subscribe to the agent first |
| `subscription_inactive` | Your subscription is paused or cancelled | Reactivate in dashboard      |
| `subscription_past_due` | Payment failed                           | Update payment method        |
| `sandbox_not_allowed`   | Agent doesn't have a sandbox endpoint    | Use a live key               |

```json theme={null}
{
  "error": "not_subscribed",
  "message": "You are not subscribed to this agent",
  "agent": "leadership-change-authority"
}
```

### Validation errors (400)

| Code                 | Description                       | Solution                       |
| -------------------- | --------------------------------- | ------------------------------ |
| `validation_error`   | Request body doesn't match schema | Check the agent's input schema |
| `missing_field`      | Required field is missing         | Add the required field         |
| `invalid_field_type` | Field has wrong type              | Check expected types           |

```json theme={null}
{
  "error": "validation_error",
  "message": "Request validation failed",
  "details": {
    "field": "ticker",
    "issue": "Field is required"
  }
}
```

### Rate limit errors (429)

| Code                  | Description       | Solution       |
| --------------------- | ----------------- | -------------- |
| `rate_limit_exceeded` | Too many requests | Wait and retry |

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "limit_type": "platform_daily",
  "message": "Daily platform limit exceeded",
  "retry_after": 3600
}
```

See [Rate Limits](/consumer/rate-limits) for details.

### Upstream errors (502, 504)

| Code               | Description                      | Solution                  |
| ------------------ | -------------------------------- | ------------------------- |
| `upstream_error`   | Agent endpoint returned an error | Retry, or contact support |
| `upstream_timeout` | Agent didn't respond in time     | Retry with backoff        |

```json theme={null}
{
  "error": "upstream_timeout",
  "message": "Agent did not respond within 30 seconds",
  "request_id": "req_abc123"
}
```

<Note>
  Always include the `request_id` when contacting support about upstream errors.
</Note>

## Agent refusals vs errors

**Refusals are not errors.** When an agent refuses a request, you'll get a `200 OK` with a refusal in the body:

```json theme={null}
{
  "refused": true,
  "refusal_code": "PRIVATE_COMPANY",
  "refusal_reason": "This agent only covers publicly traded companies"
}
```

This means the agent received your request but determined it was outside its scope. Check the agent's prospectus for documented refusal conditions.

## Error handling best practices

### 1. Always check for errors

```python theme={null}
response = requests.post(...)

if response.status_code != 200:
    error = response.json()
    print(f"Error: {error['error']} - {error['message']}")
    # Handle appropriately
    return

data = response.json()

# Also check for refusals
if data.get("refused"):
    print(f"Agent refused: {data['refusal_reason']}")
    return
```

### 2. Implement retries for transient errors

```python theme={null}
from tenacity import retry, stop_after_attempt, retry_if_result

def is_retryable(response):
    return response.status_code in [429, 502, 504]

@retry(
    stop=stop_after_attempt(3),
    retry=retry_if_result(is_retryable)
)
def call_agent(agent_slug, payload):
    return requests.post(
        f"https://gateway.kovrex.ai/v1/call/{agent_slug}",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json=payload
    )
```

### 3. Log request IDs

```python theme={null}
response = requests.post(...)
request_id = response.headers.get("X-Request-Id")

if response.status_code != 200:
    logger.error(f"Kovrex error: {response.json()} (request_id: {request_id})")
```

## Getting help

If you're seeing errors you can't resolve:

1. Check the [status page](https://status.kovrex.ai) for outages
2. Review the agent's prospectus for input requirements
3. Contact support with your `request_id`
