Error Handling
The MarketGeist API uses standard HTTP status codes to indicate success or failure. All error responses include a JSON body with a detail field explaining the error.
Response Format
Successful responses always include success: true and a data field:
200 OK
{
"success": true,
"data": { ... }
}Error responses include detail (and sometimes error):
4xx / 5xx Error
{
"detail": "A human-readable error message"
}Error Codes
The request was malformed or missing required parameters.
{ "detail": "Invalid report_type: unknown_type" }How to fix: Check the endpoint reference for required parameters and valid values.
Authentication failed or no credentials were provided.
{ "detail": "Authentication required. Provide Authorization: Bearer <token> or X-API-Key: <key>" }How to fix: Verify your API key is correct, active, and included in the X-API-Key header.
The API key does not have the required scope for this endpoint.
{ "detail": "API key missing required scope: reports" }How to fix: Update your API key scopes in the dashboard or create a new key with the needed scopes.
The requested resource does not exist or does not belong to the authenticated user.
{ "detail": "Report not found" }How to fix: Verify the resource ID and that it belongs to your account.
Rate limit exceeded for your subscription tier.
{
"error": "Rate limit exceeded",
"detail": "Maximum 60 requests per minute for starter tier",
"retry_after": 12
}How to fix: Wait for the time specified in the Retry-After header. Consider upgrading your plan for higher limits.
An unexpected error occurred on the server.
{ "detail": "Internal server error" }How to fix: Retry after a brief delay. If persistent, contact support.
A required external service (e.g., AI provider) is temporarily unavailable.
{ "detail": "AI service temporarily unavailable" }How to fix: Retry with exponential backoff. This is usually a transient issue.
Retry Strategy
For transient errors (429, 500, 503), implement exponential backoff:
Python
import time
import requests
def safe_request(method, url, **kwargs):
max_retries = 3
headers = kwargs.pop("headers", {})
headers["X-API-Key"] = "mg_live_your_key_here"
for attempt in range(max_retries):
resp = requests.request(method, url, headers=headers, **kwargs)
if resp.status_code == 429:
wait = int(resp.headers.get("Retry-After", 5))
time.sleep(wait * (2 ** attempt))
continue
if resp.status_code >= 500:
time.sleep(2 ** attempt)
continue
return resp
return resp # Return last response after all retriesJavaScript
async function safeRequest(url, options = {}) {
const maxRetries = 3;
const headers = {
"X-API-Key": "mg_live_your_key_here",
...options.headers,
};
for (let attempt = 0; attempt < maxRetries; attempt++) {
const resp = await fetch(url, { ...options, headers });
if (resp.status === 429) {
const wait = parseInt(resp.headers.get("Retry-After") || "5");
await new Promise(r => setTimeout(r, wait * (2 ** attempt) * 1000));
continue;
}
if (resp.status >= 500) {
await new Promise(r => setTimeout(r, (2 ** attempt) * 1000));
continue;
}
return resp;
}
}