Error Handling
Comprehensive guide to API error codes and handling strategies.
Overview
The Inspira API uses standard HTTP status codes and detailed error responses to help you handle errors gracefully. All error responses follow a consistent format for easy parsing and handling.
Error Response Format
Standard Error Response
json
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked",
"field": "authorization",
"details": {
"keyFormat": "invalid",
"suggestion": "Check your API key format and ensure it starts with 'inspira_'"
}
},
"timestamp": "2025-01-06T12:00:00.000Z",
"requestId": "req_123456789"
}
Error Response Fields
Field | Type | Description |
---|---|---|
success | boolean | Always false for errors |
error.code | string | Machine-readable error code |
error.message | string | Human-readable error description |
error.field | string | Field that caused the error (if applicable) |
error.details | object | Additional error context |
timestamp | string | ISO 8601 timestamp |
requestId | string | Unique request identifier for support |
HTTP Status Codes
Success Codes (2xx)
Code | Name | Description |
---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource created successfully |
202 | Accepted | Request accepted for processing |
204 | No Content | Request succeeded with no response body |
Client Error Codes (4xx)
Code | Name | Common Causes |
---|---|---|
400 | Bad Request | Invalid request format, missing parameters |
401 | Unauthorized | Missing or invalid API key |
402 | Payment Required | Insufficient credits |
403 | Forbidden | Access denied to resource |
404 | Not Found | Endpoint or resource doesn't exist |
405 | Method Not Allowed | Wrong HTTP method |
409 | Conflict | Resource conflict (duplicate) |
413 | Payload Too Large | Request body exceeds limits |
422 | Unprocessable Entity | Valid format but semantic errors |
429 | Too Many Requests | Rate limit exceeded |
Server Error Codes (5xx)
Code | Name | Description |
---|---|---|
500 | Internal Server Error | Unexpected server error |
502 | Bad Gateway | Upstream service error |
503 | Service Unavailable | Temporary maintenance/overload |
504 | Gateway Timeout | Request processing timeout |
Common Error Codes
Authentication Errors
INVALID_API_KEY
json
{
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked",
"details": {
"keyFormat": "invalid"
}
}
}
MISSING_API_KEY
json
{
"error": {
"code": "MISSING_API_KEY",
"message": "API key is required for this endpoint",
"details": {
"header": "Authorization",
"format": "Bearer inspira_your_api_key"
}
}
}
EXPIRED_API_KEY
json
{
"error": {
"code": "EXPIRED_API_KEY",
"message": "This API key has expired",
"details": {
"expiredAt": "2024-12-31T23:59:59.000Z"
}
}
}
Credit Errors
INSUFFICIENT_CREDITS
json
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits for this operation",
"details": {
"required": 10,
"available": 5.5,
"shortfall": 4.5,
"purchaseUrl": "https://app.inspirahub.net/developer?tab=credits"
}
}
}
CREDIT_LIMIT_EXCEEDED
json
{
"error": {
"code": "CREDIT_LIMIT_EXCEEDED",
"message": "Monthly credit limit exceeded",
"details": {
"limit": 10000,
"used": 10050,
"resetDate": "2025-02-01T00:00:00.000Z"
}
}
}
Validation Errors
INVALID_PARAMETER
json
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Invalid parameter value",
"field": "size",
"details": {
"provided": "2048x2048",
"allowed": ["512x512", "1024x1024"],
"reason": "Size not supported"
}
}
}
MISSING_PARAMETER
json
{
"error": {
"code": "MISSING_PARAMETER",
"message": "Required parameter is missing",
"field": "prompt",
"details": {
"type": "string",
"required": true
}
}
}
VALIDATION_ERROR
json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"errors": [
{
"field": "temperature",
"message": "Must be between 0 and 1",
"provided": 2.5
},
{
"field": "maxTokens",
"message": "Must be a positive integer",
"provided": -100
}
]
}
}
}
Rate Limit Errors
RATE_LIMIT_EXCEEDED
json
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"details": {
"limit": 60,
"window": "1 minute",
"retryAfter": 45,
"resetAt": "2025-01-06T12:01:00.000Z"
}
}
}
Service Errors
SERVICE_UNAVAILABLE
json
{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "The AI service is temporarily unavailable",
"details": {
"service": "image-generation",
"reason": "High load",
"estimatedRecovery": "2025-01-06T12:30:00.000Z"
}
}
}
UPSTREAM_ERROR
json
{
"error": {
"code": "UPSTREAM_ERROR",
"message": "Error from AI provider",
"details": {
"provider": "openai",
"originalError": "Model overloaded"
}
}
}
Error Handling Best Practices
1. Comprehensive Error Handling
javascript
async function makeApiRequest(endpoint, data) {
try {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (!response.ok) {
// Handle different error types
switch (result.error?.code) {
case 'INSUFFICIENT_CREDITS':
throw new InsufficientCreditsError(result.error);
case 'RATE_LIMIT_EXCEEDED':
throw new RateLimitError(result.error);
case 'INVALID_PARAMETER':
throw new ValidationError(result.error);
default:
throw new ApiError(result.error);
}
}
return result;
} catch (error) {
// Handle network errors
if (error instanceof TypeError && error.message === 'Failed to fetch') {
throw new NetworkError('Unable to connect to API');
}
// Re-throw API errors
throw error;
}
}
2. Custom Error Classes
javascript
class ApiError extends Error {
constructor(error) {
super(error.message);
this.name = 'ApiError';
this.code = error.code;
this.details = error.details;
this.requestId = error.requestId;
}
}
class InsufficientCreditsError extends ApiError {
constructor(error) {
super(error);
this.name = 'InsufficientCreditsError';
this.required = error.details.required;
this.available = error.details.available;
}
}
class RateLimitError extends ApiError {
constructor(error) {
super(error);
this.name = 'RateLimitError';
this.retryAfter = error.details.retryAfter;
this.resetAt = new Date(error.details.resetAt);
}
}
class ValidationError extends ApiError {
constructor(error) {
super(error);
this.name = 'ValidationError';
this.field = error.field;
this.validationErrors = error.details.errors || [];
}
}
3. Retry Logic
javascript
async function retryableRequest(fn, options = {}) {
const {
maxRetries = 3,
retryDelay = 1000,
exponentialBackoff = true,
retryableErrors = ['RATE_LIMIT_EXCEEDED', 'SERVICE_UNAVAILABLE']
} = options;
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
// Check if error is retryable
if (!retryableErrors.includes(error.code)) {
throw error;
}
// Calculate delay
let delay = retryDelay;
if (exponentialBackoff) {
delay = retryDelay * Math.pow(2, attempt);
}
// Use retry-after header if available
if (error.retryAfter) {
delay = error.retryAfter * 1000;
}
console.log(`Retrying after ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
// Usage
const result = await retryableRequest(() =>
makeApiRequest('/api/generate-image', data)
);
4. User-Friendly Error Messages
javascript
function getUserMessage(error) {
const messages = {
'INSUFFICIENT_CREDITS': 'You need more credits to complete this action. Would you like to purchase more?',
'RATE_LIMIT_EXCEEDED': 'You\'re making requests too quickly. Please wait a moment and try again.',
'INVALID_API_KEY': 'Your API key appears to be invalid. Please check your settings.',
'SERVICE_UNAVAILABLE': 'Our service is temporarily unavailable. Please try again in a few minutes.',
'INVALID_PARAMETER': `Invalid ${error.field}: ${error.message}`,
'NETWORK_ERROR': 'Unable to connect to the server. Please check your internet connection.'
};
return messages[error.code] || 'An unexpected error occurred. Please try again.';
}
5. Error Logging
javascript
class ErrorLogger {
log(error, context = {}) {
const errorLog = {
timestamp: new Date().toISOString(),
code: error.code,
message: error.message,
details: error.details,
requestId: error.requestId,
context: {
endpoint: context.endpoint,
userId: context.userId,
...context
},
stack: error.stack
};
// Log to console in development
if (process.env.NODE_ENV === 'development') {
console.error('API Error:', errorLog);
}
// Send to error tracking service
if (window.Sentry) {
window.Sentry.captureException(error, {
extra: errorLog
});
}
return errorLog;
}
}
Error Recovery Strategies
Graceful Degradation
javascript
async function generateImageWithFallback(prompt) {
try {
// Try high quality first
return await generateImage({
prompt,
quality: 'high',
size: '1024x1024'
});
} catch (error) {
if (error.code === 'INSUFFICIENT_CREDITS') {
// Fall back to lower quality
try {
return await generateImage({
prompt,
quality: 'standard',
size: '512x512'
});
} catch (fallbackError) {
// Show error to user
throw fallbackError;
}
}
throw error;
}
}
Circuit Breaker Pattern
javascript
class CircuitBreaker {
constructor(threshold = 5, timeout = 60000) {
this.threshold = threshold;
this.timeout = timeout;
this.failures = 0;
this.openedAt = null;
}
async execute(fn) {
if (this.isOpen()) {
throw new Error('Circuit breaker is open');
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
isOpen() {
if (!this.openedAt) return false;
return Date.now() - this.openedAt < this.timeout;
}
onSuccess() {
this.failures = 0;
this.openedAt = null;
}
onFailure() {
this.failures++;
if (this.failures >= this.threshold) {
this.openedAt = Date.now();
}
}
}
Debugging Errors
Request ID Tracking
Always include the request ID when contacting support:
javascript
try {
const result = await makeApiRequest(endpoint, data);
} catch (error) {
console.error(`Request failed: ${error.message}`);
console.error(`Request ID: ${error.requestId}`);
console.error(`Please include request ID when contacting support`);
}
Debug Mode
Enable debug mode for detailed error information:
javascript
const response = await fetch(endpoint, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'X-Debug-Mode': 'true'
}
});