Documentation Index
Fetch the complete documentation index at: https://docs.getcatalog.ai/llms.txt
Use this file to discover all available pages before exploring further.
The Catalog API uses standard HTTP status codes and returns detailed error information to help you troubleshoot issues quickly.
All error responses follow a consistent structure:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description",
"request_id": "req_truncated"
}
}
Additional fields may be included at the root level for specific error types. For example, validation errors may include additional context:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "One or more URLs have invalid format",
"request_id": "req_abc123"
},
"invalid_urls": [
"Index 0: https://invalid-url - invalid format"
]
}
All error responses include a Request-ID header that matches the request_id in the response body. Use this ID when contacting support.
HTTP status codes
| Status Code | Meaning | Description |
|---|
200 | Success | Request completed successfully |
400 | Bad Request | Invalid request parameters or malformed JSON |
401 | Unauthorized | Missing or invalid API key |
402 | Payment Required | Insufficient credits to complete the request |
403 | Forbidden | API key lacks required permissions |
404 | Not Found | Requested resource does not exist |
409 | Conflict | Resource state conflict (e.g., operation already in progress) |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server-side error occurred |
Error codes reference
Authentication errors
| Code | HTTP Status | Description | Resolution |
|---|
UNAUTHORIZED | 401 | Missing or invalid API key | Verify your API key is correct and included in the x-api-key header |
FORBIDDEN | 403 | API key access denied | Contact support to verify your API key permissions |
Request validation errors
| Code | HTTP Status | Description | Resolution |
|---|
INVALID_REQUEST | 400 | Invalid request format or missing required fields | Check the request format and ensure all required parameters are included |
VALIDATION_ERROR | 400 | Request format is valid but values are invalid | Check parameter values against endpoint requirements (e.g., URL format, array length limits) |
Resource errors
| Code | HTTP Status | Description | Resolution |
|---|
NOT_FOUND | 404 | Resource not found | Verify the endpoint URL and any resource IDs (e.g., execution IDs) |
CONFLICT | 409 | Resource state conflict | The requested operation conflicts with the current state (e.g., trying to cancel an execution that’s already stopped) |
Billing errors
| Code | HTTP Status | Description | Resolution |
|---|
INSUFFICIENT_CREDITS | 402 | Not enough credits to complete the request | Add credits to your account or enable auto top-up. The response includes credits_needed and credits_remaining fields. |
Rate limiting errors
| Code | HTTP Status | Description | Resolution |
|---|
RATE_LIMITED | 429 | Too many requests in a short window | Respect Retry-After header, pace requests using RateLimit-Remaining, and back off (exponential recommended). Contact support if you need higher limits. |
Server errors
| Code | HTTP Status | Description | Resolution |
|---|
INTERNAL_ERROR | 500 | Unexpected server error | Retry the request; if persistent, contact support with the request_id |
Handling errors
Basic error handling
const response = await fetch('https://api.getcatalog.ai/v1/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
},
body: JSON.stringify({ query: 'black dress' })
});
if (!response.ok) {
const error = await response.json();
const requestId = response.headers.get('Request-ID') || error.error?.request_id;
switch (response.status) {
case 401:
console.error('Authentication failed:', error.error.message);
break;
case 402:
console.error('Insufficient credits:', error.error.message);
if (error.credits_needed && error.credits_remaining) {
console.error(`Need ${error.credits_needed}, have ${error.credits_remaining}`);
}
break;
case 403:
console.error('Access forbidden:', error.error.message);
break;
case 404:
console.error('Resource not found:', error.error.message);
break;
case 409:
console.error('Conflict:', error.error.message);
break;
case 429:
const retryAfter = response.headers.get('Retry-After');
console.error('Rate limited. Retry after:', retryAfter);
break;
case 500:
console.error('Server error:', error.error.message);
console.error('Request ID:', requestId);
break;
default:
console.error('Request failed:', error);
}
return;
}
const data = await response.json();
Retry with exponential backoff
For transient errors (402, 429, 500), implement exponential backoff:
async function requestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.ok) {
return response.json();
}
const error = await response.json();
// Don't retry client errors (except 402 for credits)
if (response.status === 402) {
// Insufficient credits - don't retry, user needs to add credits
throw new Error(`Insufficient credits: ${error.error.message}`);
}
if (response.status === 429 || response.status >= 500) {
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter
? parseInt(retryAfter) * 1000
: Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
console.log(`Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
// Non-retryable error
throw new Error(`Request failed: ${response.status} - ${error.error.message}`);
}
throw new Error('Max retries exceeded');
}
Error response examples
Insufficient Credits (402)
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits",
"request_id": "req_01HZ..."
},
"credits_needed": 100,
"credits_remaining": 50
}
Validation Error with Additional Context (400)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "One or more URLs have invalid format",
"request_id": "req_01HZ..."
},
"invalid_urls": [
"Index 0: https://invalid-url - invalid format",
"Index 2: not-a-url - invalid format"
]
}
Not Found (404)
{
"error": {
"code": "NOT_FOUND",
"message": "Execution not found",
"request_id": "req_01HZ..."
}
}
Conflict (409)
{
"error": {
"code": "CONFLICT",
"message": "Crawl is currently stopping for example.com. Please wait.",
"request_id": "req_01HZ..."
}
}
Logical errors (200 OK responses)
Some endpoints return 200 OK even when individual items fail. Always check the response body:
Single product endpoint
{
"product": null,
"meta": {
"found": false,
"url": "https://example.com/invalid-product",
"outcome": "VENDOR_NOT_SUPPORTED"
}
}
Bulk products endpoint
{
"products": [
{
"url": "https://valid-store.com/product",
"success": true,
"product": { "_truncated": "Product object omitted for display" }
},
{
"url": "https://invalid-store.com/product",
"success": false,
"product": null,
"outcome": "VENDOR_NOT_SUPPORTED"
}
],
"meta": {
"total_requested": 2,
"total_successful": 1,
"total_failed": 1
}
}
Always check meta.found or success fields in responses, even when the HTTP status is 200.
Need help?
If you encounter persistent errors or need assistance, contact our support team with:
- The full error response (including the
error object)
- The
request_id from the response (found in both the response body and Request-ID header)
- Your request payload (with sensitive data redacted)
- Timestamp of when the error occurred