All API errors return a consistent JSON structure:
{
"error": "Error Type",
"message": "Human-readable error description",
"details": {
"field": "Additional context"
}
}
HTTP Status Codes
2xx Success
Request successful, data returned
4xx Client Errors
Invalid request parameters or malformed queryCommon causes:
- Invalid parameter type (e.g., string instead of integer)
- Parameter value out of range
- Malformed query syntax
- Missing required parameters
Example:{
"error": "Bad Request",
"message": "Invalid value for 'limit' parameter",
"details": {
"parameter": "limit",
"provided": "invalid",
"expected": "integer (1-100)"
}
}
Missing or invalid API keyCommon causes:
- Missing
Authorization header
- Invalid API key format
- Revoked API key
- Expired API key
Example:{
"error": "Unauthorized",
"message": "Invalid or missing API key",
"details": {
"hint": "Include 'Authorization: Bearer YOUR_API_KEY' header"
}
}
Solution: Include valid API key in Authorization header
Valid API key but insufficient permissionsCommon causes:
- Plan doesn’t include requested feature
- Endpoint requires higher tier
- Resource access restricted
Example:{
"error": "Forbidden",
"message": "Your current plan does not include access to this endpoint",
"details": {
"required_plan": "Pro",
"current_plan": "Free",
"upgrade_url": "https://api.pricingsaas.com/pricing"
}
}
Solution: Upgrade to required plan or contact support
Requested resource doesn’t existCommon causes:
- Invalid company slug
- Typo in resource identifier
- Resource has been deleted
Example:{
"error": "Not Found",
"message": "Company with slug 'invalid-slug' not found",
"details": {
"slug": "invalid-slug",
"suggestion": "Use /api/companies?search=invalid to search"
}
}
Solution: Verify resource identifier or use search endpoint
Rate limit exceededHeaders included:
X-RateLimit-Limit: Maximum requests allowed
X-RateLimit-Remaining: Requests remaining
X-RateLimit-Reset: Unix timestamp when limit resets
Retry-After: Seconds to wait before retrying
Example:{
"error": "Rate limit exceeded",
"message": "You have exceeded your rate limit of 100 requests per hour",
"details": {
"limit": 100,
"remaining": 0,
"reset_at": "2024-01-15T11:00:00Z",
"retry_after": 3600
}
}
Solution: Wait for reset or upgrade to higher tier
5xx Server Errors
500 Internal Server Error
Unexpected server errorExample:{
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"details": {
"request_id": "req_abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Solution: Retry after brief delay. Contact support if persistent with request_id
Temporary service disruptionExample:{
"error": "Service Unavailable",
"message": "Service temporarily unavailable. Please retry.",
"details": {
"retry_after": 60
}
}
Solution: Retry with exponential backoff. Check status page
Common Error Scenarios
Invalid API Key
curl "https://api.pricingsaas.com/functions/v1/api/companies" \
-H "Authorization: Bearer invalid_key"
{
"error": "Unauthorized",
"message": "Invalid or missing API key"
}
Invalid Parameter Type
curl "https://api.pricingsaas.com/functions/v1/api/companies?limit=abc" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"error": "Bad Request",
"message": "Invalid value for 'limit' parameter. Must be an integer between 1 and 100.",
"details": {
"parameter": "limit",
"provided": "abc",
"expected": "integer (1-100)"
}
}
Out of Range Parameter
curl "https://api.pricingsaas.com/functions/v1/api/companies?limit=500" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"error": "Bad Request",
"message": "Parameter 'limit' exceeds maximum value",
"details": {
"parameter": "limit",
"provided": 500,
"max": 100
}
}
Invalid Category
curl "https://api.pricingsaas.com/functions/v1/api/companies?category=InvalidCategory" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"error": "Bad Request",
"message": "Invalid category value",
"details": {
"parameter": "category",
"provided": "InvalidCategory",
"valid_values": [
"Communication",
"Productivity",
"Development",
"Marketing",
"Sales",
"Customer Support",
"Finance",
"HR"
]
}
}
Company Not Found
curl "https://api.pricingsaas.com/functions/v1/api/companies/nonexistent" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"error": "Not Found",
"message": "Company with slug 'nonexistent' not found",
"details": {
"slug": "nonexistent",
"suggestion": "Use /api/companies?search=nonexistent to search"
}
}
Rate Limit Exceeded
# 101st request in an hour on free tier
curl "https://api.pricingsaas.com/functions/v1/api/companies" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"error": "Rate limit exceeded",
"message": "You have exceeded your rate limit of 100 requests per hour",
"details": {
"limit": 100,
"remaining": 0,
"reset_at": "2024-01-15T11:00:00Z",
"retry_after": 3600
}
}
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 3600
Insufficient Permissions
# Accessing enterprise-only endpoint with free tier
curl "https://api.pricingsaas.com/functions/v1/api/companies/advanced-analytics" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"error": "Forbidden",
"message": "This endpoint requires an Enterprise plan",
"details": {
"required_plan": "Enterprise",
"current_plan": "Free",
"upgrade_url": "https://api.pricingsaas.com/pricing"
}
}
Error Handling Best Practices
Check Status Codes
Always check HTTP status codes before processing responses:
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
if (!response.ok) {
const error = await response.json();
console.error(`API Error (${response.status}):`, error.message);
throw new Error(error.message);
}
const data = await response.json();
Handle Specific Errors
Handle different error types appropriately:
try {
const response = await fetch(url);
const data = await response.json();
if (!response.ok) {
switch (response.status) {
case 400:
console.error('Invalid request:', data.details);
break;
case 401:
console.error('Authentication failed');
// Redirect to login or refresh credentials
break;
case 403:
console.error('Insufficient permissions');
// Show upgrade prompt
break;
case 404:
console.error('Resource not found');
// Show not found message
break;
case 429:
const retryAfter = data.details.retry_after;
console.log(`Rate limited. Retry in ${retryAfter}s`);
// Implement retry logic
break;
case 500:
case 503:
console.error('Server error. Retrying...');
// Implement retry with backoff
break;
default:
console.error('Unexpected error:', data.message);
}
}
} catch (error) {
console.error('Network error:', error);
}
Log Error Details
Always log full error context for debugging:
console.error('API Error:', {
status: response.status,
error: errorData.error,
message: errorData.message,
details: errorData.details,
requestId: errorData.details?.request_id,
timestamp: new Date().toISOString(),
url: response.url
});
Implement Retry Logic
Retry transient errors with exponential backoff:
async function fetchWithRetry(url, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
// Retry on rate limit or server errors
if (response.status === 429 || response.status >= 500) {
const error = await response.json();
const retryAfter = error.details?.retry_after || Math.pow(2, attempt);
const delayMs = retryAfter * 1000;
console.log(`Attempt ${attempt + 1} failed. Retrying in ${delayMs}ms`);
await new Promise(resolve => setTimeout(resolve, delayMs));
continue;
}
return response;
} catch (error) {
if (attempt === maxRetries - 1) throw error;
}
}
}
Need Help?