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
All Descripio API errors return a JSON response with an error field.
{
"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
{
"error": "Invalid API key"
}
Solution:
- Verify your API key is correct (starts with
dscr_)
- Check if key was revoked in the dashboard
- Create a new key if needed
402 Payment Required
Cause: Monthly quota exceeded
{
"error": "Monthly quota exceeded",
"used": 10,
"limit": 10
}
Solution:
- Wait for quota reset (1st of each month)
- Upgrade to a higher plan
403 Forbidden
Cause: Marketplace not authorized for your account
{
"error": "Marketplace not authorized for this store",
"hint": "Configure marketplace access in your account settings"
}
Solution:
- Go to Dashboard → Settings → Marketplaces
- Add the marketplace you’re trying to access
- Retry the request
429 Rate Limit Exceeded
Cause: Too many requests or concurrent jobs
{
"error": "Rate limit exceeded",
"limit": 1
}
Solution: Implement retry with backoff:
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
{
"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
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
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:
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:
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
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: