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

# Error Handling

> Handle API errors gracefully

# Error Handling

All Descripio API errors return a JSON response with an `error` field.

## Error Response Format

```json theme={null}
{
  "error": "Human-readable error message",
  "limit": 10,
  "used": 10
}
```

Additional fields may be included depending on the error type.

## Common Errors

### 401 Unauthorized

**Cause**: Invalid or revoked API key

```json theme={null}
{
  "error": "Invalid API key"
}
```

**Solution**:

1. Verify your API key is correct (starts with `dscr_`)
2. Check if key was revoked in the [dashboard](https://app.descripio.com/developer/api-keys)
3. Create a new key if needed

### 402 Payment Required

**Cause**: Monthly quota exceeded

```json theme={null}
{
  "error": "Monthly quota exceeded",
  "used": 10,
  "limit": 10
}
```

**Solution**:

1. Wait for quota reset (1st of each month)
2. Upgrade to a higher plan

### 403 Forbidden

**Cause**: Marketplace not authorized for your account

```json theme={null}
{
  "error": "Marketplace not authorized for this store",
  "hint": "Configure marketplace access in your account settings"
}
```

**Solution**:

1. Go to Dashboard → Settings → Marketplaces
2. Add the marketplace you're trying to access
3. Retry the request

### 429 Rate Limit Exceeded

**Cause**: Too many requests or concurrent jobs

```json theme={null}
{
  "error": "Rate limit exceeded",
  "limit": 1
}
```

**Solution**: Implement retry with backoff:

```python theme={null}
import time
import requests

def api_call_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)
        
        if response.status_code == 429:
            wait_time = (2 ** attempt) * 10  # 10s, 20s, 40s
            print(f"Rate limited. Waiting {wait_time}s...")
            time.sleep(wait_time)
            continue
        
        return response
    
    raise Exception("Max retries exceeded")
```

### 429 ASIN Cooldown

**Cause**: ASIN was refreshed recently

```json theme={null}
{
  "error": "ASIN cooldown active",
  "cooldownHours": 24
}
```

**Solution**: Wait for cooldown period to expire, or use cached data via `GET /reviews`.

## Best Practices

### 1. Always check status codes

```python theme={null}
response = requests.post(url, headers=headers, json=data)

if response.status_code == 202:
    job = response.json()
    # Success - process job
elif response.status_code == 429:
    # Rate limited - wait and retry
elif response.status_code == 402:
    # Quota exceeded - alert user
else:
    # Log unexpected error
    print(f"Error {response.status_code}: {response.json()}")
```

### 2. Implement exponential backoff

```javascript theme={null}
async function fetchWithBackoff(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);
    
    if (response.status === 429) {
      const waitTime = Math.pow(2, attempt) * 10000; // 10s, 20s, 40s
      await new Promise(r => setTimeout(r, waitTime));
      continue;
    }
    
    return response;
  }
  
  throw new Error('Max retries exceeded');
}
```

### 3. Set polling timeout

Never poll forever. Always set a maximum timeout:

```python theme={null}
max_attempts = 24  # 2 minutes at 5s intervals
timeout_seconds = 120

for attempt in range(max_attempts):
    # ... poll job status
    time.sleep(5)
else:
    raise TimeoutError("Job did not complete in time")
```

### 4. Log errors for debugging

Include relevant context when logging errors:

```python theme={null}
import logging

logging.error(
    "API Error",
    extra={
        "status_code": response.status_code,
        "error": response.json().get("error"),
        "asin": asin,
        "timestamp": datetime.now().isoformat()
    }
)
```

### 5. Handle network errors

```python theme={null}
import requests
from requests.exceptions import Timeout, ConnectionError

try:
    response = requests.post(url, headers=headers, json=data, timeout=30)
except Timeout:
    print("Request timed out - check your connection")
except ConnectionError:
    print("Connection failed - check if service is available")
```

## Support

If you encounter persistent errors:

* **Email**: [support@descripio.com](mailto:support@descripio.com)
* **Include**: Job ID, timestamp, error message, request details
