Error Handling
Understanding error responses helps you debug issues and build robust integrations.
HTTP Status Codes
Success Codes (2xx)
| Code | Meaning | When You Get It |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource was created |
| 202 | Accepted | Request accepted for processing |
Client Errors (4xx)
| Code | Meaning | Common Cause | Action |
|---|---|---|---|
| 400 | Bad Request | Invalid parameters | Fix request body/params |
| 401 | Unauthorized | Missing/invalid auth | Check API key |
| 403 | Forbidden | Insufficient permissions | Use correct API key scope |
| 404 | Not Found | Resource doesn't exist | Verify resource ID |
| 429 | Rate Limited | Too many requests | Wait and retry |
Server Errors (5xx)
| Code | Meaning | Action |
|---|---|---|
| 500 | Internal Server Error | Retry with backoff |
| 503 | Service Unavailable | Check status page, wait |
Error Response Format
All errors follow a consistent format:
{
"error": {
"code": "invalid_request",
"message": "Missing required field: document_url",
"details": {
"field": "document_url",
"type": "required"
},
"request_id": "req_abc123xyz"
}
}| Field | Description |
|---|---|
| code | Machine-readable error code |
| message | Human-readable error message |
| details | Additional error context |
| request_id | Unique ID for support |
Common Error Codes
Authentication Errors
invalid_api_key
{
"error": {
"code": "invalid_api_key",
"message": "Invalid or expired API key"
}
}Solution: Generate a new API key in Settings
missing_authorization
{
"error": {
"code": "missing_authorization",
"message": "Authorization header required"
}
}Solution: Add Authorization: Bearer YOUR_API_KEY header
Permission Errors
insufficient_permissions
{
"error": {
"code": "insufficient_permissions",
"message": "API key doesn't have permission: write:documents"
}
}Solution: Use a key with the required scope or upgrade key permissions
Request Errors
invalid_request
{
"error": {
"code": "invalid_request",
"message": "Missing required field: document_url",
"details": {
"field": "document_url",
"type": "required"
}
}
}Solution: Add the missing required field
invalid_parameter
{
"error": {
"code": "invalid_parameter",
"message": "Invalid value for parameter 'language': 'spanish' (expected 'en', 'es', 'fr')",
"details": {
"parameter": "language",
"value": "spanish",
"valid_values": ["en", "es", "fr"]
}
}
}Solution: Use a valid value from the list
invalid_json
{
"error": {
"code": "invalid_json",
"message": "Request body is not valid JSON"
}
}Solution: Ensure request body is valid JSON
Resource Errors
resource_not_found
{
"error": {
"code": "resource_not_found",
"message": "Document 'doc_xyz789' not found"
}
}Solution: Verify the resource ID is correct
resource_already_exists
{
"error": {
"code": "resource_already_exists",
"message": "A document with this ID already exists"
}
}Solution: Use a different ID or update existing resource
Rate Limiting
rate_limit_exceeded
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded: 60 requests per minute"
}
}Solution: Wait before retrying (check X-RateLimit-Reset header)
Server Errors
internal_server_error
{
"error": {
"code": "internal_server_error",
"message": "An internal server error occurred",
"request_id": "req_abc123xyz"
}
}Solution: Retry with backoff, include request_id in support ticket
Error Handling Patterns
Basic Error Handling (JavaScript)
const analyzeDocument = async (documentUrl) => {
try {
const response = await fetch(
'https://api.solatis.team/v2/documents/analyze',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ document_url: documentUrl })
}
);
// Handle HTTP errors
if (!response.ok) {
const error = await response.json();
if (response.status === 401) {
console.error('Authentication failed:', error.error.message);
// Handle auth error
} else if (response.status === 429) {
console.error('Rate limited:', error.error.message);
// Implement retry
} else if (response.status >= 500) {
console.error('Server error:', error.error.message);
// Retry with backoff
} else {
console.error('Request error:', error.error.message);
}
throw new Error(error.error.message);
}
return await response.json();
} catch (error) {
console.error('Request failed:', error.message);
throw error;
}
};Error Handling with Retry (Python)
import requests
import time
def make_api_request(url, **kwargs):
max_retries = 3
base_delay = 1
for attempt in range(max_retries):
try:
response = requests.post(url, **kwargs)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
print('Authentication failed:', e.response.json())
raise # Don't retry auth errors
elif e.response.status_code == 429:
# Rate limited - wait and retry
retry_after = int(e.response.headers.get('X-RateLimit-Reset', 60))
wait_time = (retry_after * 1000) - (time.time() * 1000)
print(f'Rate limited. Waiting {wait_time}ms...')
time.sleep(wait_time / 1000)
continue
elif e.response.status_code >= 500:
# Server error - retry with backoff
if attempt < max_retries - 1:
delay = base_delay * (2 ** attempt)
print(f'Server error. Retrying in {delay}s...')
time.sleep(delay)
continue
raise
except requests.exceptions.RequestException as e:
print('Request failed:', str(e))
raiseCustom Error Class (JavaScript)
class SolatisError extends Error {
constructor(code, message, details = null, requestId = null) {
super(message);
this.name = 'SolatisError';
this.code = code;
this.details = details;
this.requestId = requestId;
}
isRetryable() {
return ['rate_limit_exceeded', 'internal_server_error'].includes(this.code);
}
isAuthError() {
return ['invalid_api_key', 'missing_authorization', 'insufficient_permissions']
.includes(this.code);
}
}
const handleApiError = (response, data) => {
const { error } = data;
throw new SolatisError(
error.code,
error.message,
error.details,
error.request_id
);
};
// Usage
try {
// Make request
} catch (error) {
if (error instanceof SolatisError) {
if (error.isRetryable()) {
console.log('Will retry:', error.message);
} else if (error.isAuthError()) {
console.log('Auth error:', error.message);
// Redirect to re-authenticate
} else {
console.log('Other error:', error.message);
}
// Log for support
if (error.requestId) {
console.log('Support reference:', error.requestId);
}
}
}Debugging Tips
1. Use Request ID for Support
Every error includes a request_id. Include this when contacting support:
try {
await makeApiRequest();
} catch (error) {
const { request_id } = error;
console.error(`Error (ref: ${request_id}): ${error.message}`);
// Email support with request_id
}2. Log Full Response
When debugging, log the complete error response:
const response = await fetch(url, options);
if (!response.ok) {
const data = await response.json();
console.error({
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
body: data
});
}3. Check Headers
Rate limiting and other info are in headers:
const response = await fetch(url, options);
console.log({
rateLimit: response.headers.get('X-RateLimit-Limit'),
remaining: response.headers.get('X-RateLimit-Remaining'),
reset: response.headers.get('X-RateLimit-Reset'),
retryAfter: response.headers.get('Retry-After')
});4. Validate Before Sending
Catch errors early by validating requests:
const validateAnalyzeRequest = (params) => {
if (!params.document_url) throw new Error('document_url required');
if (!params.analysis_type) throw new Error('analysis_type required');
const validTypes = ['contract_review', 'financial_analysis', 'legal_review'];
if (!validTypes.includes(params.analysis_type)) {
throw new Error(`analysis_type must be one of: ${validTypes.join(', ')}`);
}
return true;
};
// Validate before API call
validateAnalyzeRequest(params);
const result = await analyzeDocument(params);Common Error Scenarios
Scenario 1: Invalid API Key
Error:
{
"error": {
"code": "invalid_api_key",
"message": "Invalid or expired API key"
}
}Solution:
- Go to Settings → Developer → API Keys
- Generate a new key
- Update your application with new key
- Delete the old key (if compromised)
Scenario 2: Rate Limited
Error:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded: 60 requests per minute"
}
}Solution:
- Check X-RateLimit-Reset header for when limit resets
- Wait before retrying
- Implement exponential backoff
- Consider upgrading plan for higher limits
Scenario 3: Server Temporarily Down
Error:
{
"error": {
"code": "internal_server_error",
"message": "An internal server error occurred",
"request_id": "req_abc123"
}
}Solution:
- Check status.solatis.team
- Retry with exponential backoff
- If persistent, email support with request_id
Scenario 4: Missing Required Field
Error:
{
"error": {
"code": "invalid_request",
"message": "Missing required field: document_url",
"details": {
"field": "document_url",
"type": "required"
}
}
}Solution:
- Add the missing field to your request
- Check API documentation for required fields
- Validate locally before sending
Getting Support
When reporting issues to support:
- Include request ID from error response
- Provide exact error code (e.g.,
invalid_request) - Show request and response (redact sensitive data)
- Describe steps to reproduce
- Mention your plan type (Individual, Team, Enterprise)
Email: developers@solatis.team
Monitoring Best Practices
Track Error Rates
const errorRates = new Map();
const trackError = (code) => {
const count = (errorRates.get(code) || 0) + 1;
errorRates.set(code, count);
// Alert if error rate too high
if (count > 100) {
sendAlert(`High error rate: ${code} (${count} errors)`);
}
};Log Errors Consistently
const logError = (error, context) => {
console.error({
timestamp: new Date().toISOString(),
code: error.code,
message: error.message,
requestId: error.requestId,
context,
environment: process.env.NODE_ENV
});
};Set Up Alerts
Monitor for specific errors:
const monitorErrors = async () => {
const alertThresholds = {
'rate_limit_exceeded': 10, // Alert if > 10 rate limit errors
'invalid_api_key': 1, // Alert on any auth errors
'internal_server_error': 5 // Alert if > 5 server errors
};
// Check error logs periodically
const recentErrors = await getErrorsFromLastHour();
for (const [code, threshold] of Object.entries(alertThresholds)) {
const count = recentErrors.filter(e => e.code === code).length;
if (count > threshold) {
sendAlert(`High error count for ${code}: ${count}`);
}
}
};Next Steps
- Getting Started - Make your first request
- Rate Limiting - Handle rate limits
- Code Examples - Error handling examples