Error Handling
Complete reference for API error codes, formats, and handling strategies
Error Handling
The Heppu AI API uses conventional HTTP response codes to indicate the success or failure of an API request. Errors include both machine-readable error codes and human-readable messages to help you debug issues quickly.
Error Response Format
All error responses follow a consistent structure:
{
"error": {
"message": "Human-readable error description",
"status": 400,
"code": "invalid_request",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"field": "agentId",
"reason": "Agent not found"
}
}
}Fields:
message(string): Human-readable error descriptionstatus(number): HTTP status codecode(string): Machine-readable error code (optional)timestamp(string): ISO 8601 timestampdetails(object): Additional error context (optional)
The details field provides additional context for debugging and may include field names, validation errors, or other helpful information.
HTTP Status Codes
The API returns standard HTTP status codes:
| Status Code | Description | Common Causes |
|---|---|---|
200 | OK | Successful request |
201 | Created | Resource created successfully |
204 | No Content | Successful deletion |
400 | Bad Request | Invalid parameters or request body |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | Valid API key but insufficient permissions |
404 | Not Found | Resource doesn't exist |
409 | Conflict | Resource conflict (duplicate, state mismatch) |
422 | Unprocessable Entity | Validation failed |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server-side error |
502 | Bad Gateway | Upstream service unavailable |
503 | Service Unavailable | Temporary server maintenance |
504 | Gateway Timeout | Request timeout |
Error Codes
Authentication Errors (401)
invalid_api_key
The provided API key is invalid or malformed.
{
"error": {
"message": "Invalid API key format",
"status": 401,
"code": "invalid_api_key",
"timestamp": "2024-12-01T12:00:00Z"
}
}Solution:
- Verify your API key is correct
- Check for extra spaces or newlines
- Ensure you're using the correct environment (test vs. live)
missing_api_key
No API key was provided in the request.
{
"error": {
"message": "API key required. Include x-api-key header or Authorization: Bearer header.",
"status": 401,
"code": "missing_api_key",
"timestamp": "2024-12-01T12:00:00Z"
}
}Solution:
# Include the x-api-key header
curl https://v2.heppu.ai/api/v1/agents \
-H "x-api-key: your_api_key_here"revoked_api_key
The API key has been revoked and is no longer valid.
{
"error": {
"message": "API key has been revoked",
"status": 401,
"code": "revoked_api_key",
"timestamp": "2024-12-01T12:00:00Z"
}
}Solution:
- Create a new API key in your dashboard
- Update your application with the new key
- Remove the revoked key from your systems
Authorization Errors (403)
insufficient_permissions
Your API key doesn't have permission to perform this action.
{
"error": {
"message": "Insufficient permissions to access this resource",
"status": 403,
"code": "insufficient_permissions",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"required_permission": "agents:write"
}
}
}Solution:
- Check your organization role and permissions
- Contact your organization admin to upgrade permissions
- Use a different API key with appropriate permissions
Resource Errors (404)
resource_not_found
The requested resource doesn't exist.
{
"error": {
"message": "Agent not found",
"status": 404,
"code": "resource_not_found",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"resource_type": "agent",
"resource_id": "agent_abc123"
}
}
}Solution:
- Verify the resource ID is correct
- Check that the resource belongs to your organization
- Ensure the resource hasn't been deleted
Validation Errors (400, 422)
invalid_request
The request body or parameters are invalid.
{
"error": {
"message": "Invalid request parameters",
"status": 400,
"code": "invalid_request",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"errors": [
{
"field": "name",
"message": "Name is required"
},
{
"field": "temperature",
"message": "Temperature must be between 0 and 2"
}
]
}
}
}Solution:
- Review the
details.errorsarray for specific validation failures - Check API documentation for required fields and formats
- Validate input before sending requests
validation_failed
Request data failed validation rules.
{
"error": {
"message": "Validation failed",
"status": 422,
"code": "validation_failed",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"field": "systemPrompt",
"message": "System prompt cannot be empty"
}
}
}Rate Limit Errors (429)
rate_limit_exceeded
You've exceeded your API rate limit.
{
"error": {
"message": "Rate limit exceeded. Please retry after 60 seconds.",
"status": 429,
"code": "rate_limit_exceeded",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"limit": 100,
"remaining": 0,
"reset": 1638360060
}
}
}Response Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1638360060
Retry-After: 60Solution:
- Implement exponential backoff
- Respect the
Retry-Afterheader - Upgrade your plan for higher limits
Conflict Errors (409)
resource_conflict
The operation conflicts with the current state of the resource.
{
"error": {
"message": "Agent with this name already exists",
"status": 409,
"code": "resource_conflict",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"field": "name",
"conflict": "duplicate_name"
}
}
}Solution:
- Use a different name or identifier
- Update the existing resource instead
- Check current resource state before creating
Server Errors (500, 502, 503, 504)
internal_error
An unexpected error occurred on our servers.
{
"error": {
"message": "An internal error occurred. Please try again later.",
"status": 500,
"code": "internal_error",
"timestamp": "2024-12-01T12:00:00Z",
"details": {
"request_id": "req_xyz789"
}
}
}Solution:
- Retry the request with exponential backoff
- Contact support with the
request_idif the issue persists
Error Handling Best Practices
1. Always Check Response Status
async function makeRequest(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
console.error(`API Error ${error.error.status}:`, error.error.message);
throw new Error(error.error.message);
}
return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
// Usage
const data = await makeRequest('https://v2.heppu.ai/api/v1/agents', {
headers: { 'x-api-key': process.env.HEPPU_API_KEY }
});import requests
def make_request(url, **kwargs):
try:
response = requests.get(url, **kwargs)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as error:
error_data = error.response.json()
print(f"API Error {error_data['error']['status']}: {error_data['error']['message']}")
raise
except requests.exceptions.RequestException as error:
print(f"Request failed: {error}")
raise
# Usage
data = make_request(
'https://v2.heppu.ai/api/v1/agents',
headers={'x-api-key': os.environ.get('HEPPU_API_KEY')}
)# Use -f to fail on HTTP errors
# Use -w to print status code
curl -f -w "\nHTTP Status: %{http_code}\n" \
https://v2.heppu.ai/api/v1/agents \
-H "x-api-key: $HEPPU_API_KEY"2. Implement Retry Logic with Exponential Backoff
async function retryRequest(fn, maxRetries = 3, baseDelay = 1000) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
// Don't retry client errors (4xx except 429)
if (error.status >= 400 && error.status < 500 && error.status !== 429) {
throw error;
}
// Last attempt, throw error
if (attempt === maxRetries - 1) {
throw error;
}
// Calculate exponential backoff with jitter
const delay = baseDelay * Math.pow(2, attempt) + Math.random() * 1000;
console.log(`Retry attempt ${attempt + 1} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
// Usage
const data = await retryRequest(async () => {
return await makeRequest('https://v2.heppu.ai/api/v1/agents', {
headers: { 'x-api-key': process.env.HEPPU_API_KEY }
});
});3. Handle Rate Limits Gracefully
async function makeRequestWithRateLimit(url, options) {
try {
const response = await fetch(url, options);
// Check rate limit headers
const limit = response.headers.get('X-RateLimit-Limit');
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
console.log(`Rate limit: ${remaining}/${limit} (resets at ${new Date(reset * 1000)})`);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return makeRequestWithRateLimit(url, options); // Retry
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}4. Log Errors with Context
function logError(error, context) {
console.error({
timestamp: new Date().toISOString(),
error: {
message: error.message,
status: error.status,
code: error.code
},
context: {
endpoint: context.endpoint,
method: context.method,
requestId: error.details?.request_id
}
});
// Send to error tracking service
// Sentry.captureException(error, { extra: context });
}
// Usage
try {
await createAgent(data);
} catch (error) {
logError(error, {
endpoint: '/api/v1/agents',
method: 'POST',
userId: 'user_123'
});
}5. Provide User-Friendly Error Messages
function getUserFriendlyMessage(error) {
switch (error.code) {
case 'invalid_api_key':
case 'missing_api_key':
case 'revoked_api_key':
return 'Authentication failed. Please check your API key configuration.';
case 'resource_not_found':
return 'The requested resource was not found. It may have been deleted.';
case 'rate_limit_exceeded':
return 'Too many requests. Please wait a moment and try again.';
case 'validation_failed':
case 'invalid_request':
return `Invalid input: ${error.details?.message || error.message}`;
case 'internal_error':
return 'We encountered an unexpected error. Our team has been notified.';
default:
return 'An error occurred. Please try again later.';
}
}
// Usage
catch (error) {
const userMessage = getUserFriendlyMessage(error);
res.status(error.status || 500).json({ message: userMessage });
}Complete Error Handling Example
Here's a production-ready error handling implementation:
const fetch = require('node-fetch');
class HeppuAPIError extends Error {
constructor(message, status, code, details) {
super(message);
this.name = 'HeppuAPIError';
this.status = status;
this.code = code;
this.details = details;
}
}
class HeppuClient {
constructor(apiKey, options = {}) {
this.apiKey = apiKey;
this.baseUrl = options.baseUrl || 'https://v2.heppu.ai/api/v1';
this.maxRetries = options.maxRetries || 3;
this.timeout = options.timeout || 30000;
}
async request(endpoint, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const config = {
...options,
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json',
...options.headers
},
timeout: this.timeout
};
return await this._retryRequest(async () => {
const response = await fetch(url, config);
return await this._handleResponse(response);
});
}
async _retryRequest(fn, attempt = 0) {
try {
return await fn();
} catch (error) {
// Don't retry client errors (except 429)
if (error.status >= 400 && error.status < 500 && error.status !== 429) {
throw error;
}
// Max retries reached
if (attempt >= this.maxRetries) {
throw error;
}
// Calculate backoff with jitter
const baseDelay = 1000;
const delay = baseDelay * Math.pow(2, attempt) + Math.random() * 1000;
console.log(`Retry attempt ${attempt + 1}/${this.maxRetries} after ${Math.round(delay)}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
return await this._retryRequest(fn, attempt + 1);
}
}
async _handleResponse(response) {
// Handle rate limiting
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
const error = await response.json();
throw new HeppuAPIError(
error.error.message,
429,
'rate_limit_exceeded',
{ retryAfter, ...error.error.details }
);
}
// Handle error responses
if (!response.ok) {
const error = await response.json();
throw new HeppuAPIError(
error.error.message,
error.error.status,
error.error.code,
error.error.details
);
}
// Handle successful responses
if (response.status === 204) {
return null; // No content
}
return await response.json();
}
// Helper methods
async getAgents() {
return await this.request('/agents');
}
async createAgent(data) {
return await this.request('/agents', {
method: 'POST',
body: JSON.stringify(data)
});
}
}
// Usage
async function main() {
const client = new HeppuClient(process.env.HEPPU_API_KEY, {
maxRetries: 3,
timeout: 30000
});
try {
const agents = await client.getAgents();
console.log('Agents:', agents.data);
} catch (error) {
if (error instanceof HeppuAPIError) {
console.error(`API Error [${error.code}]:`, error.message);
console.error('Status:', error.status);
console.error('Details:', error.details);
} else {
console.error('Unexpected error:', error);
}
}
}
main();Testing Error Handling
Test your error handling with these common scenarios:
// Test invalid API key
await client.request('/agents', {
headers: { 'x-api-key': 'invalid_key' }
});
// Test missing resource
await client.request('/agents/nonexistent_id');
// Test validation error
await client.createAgent({ /* missing required fields */ });
// Test rate limiting (make many requests quickly)
const promises = Array(200).fill().map(() => client.getAgents());
await Promise.all(promises);Debugging Tips
- Check Request ID: Include the
request_idfrom error details when contacting support - Enable Verbose Logging: Log full request/response for debugging
- Test in Sandbox: Use test API keys to debug without affecting production
- Monitor Rate Limits: Track
X-RateLimit-*headers to avoid hitting limits - Use Try-Catch: Always wrap API calls in try-catch blocks
Next Steps
Authentication
Learn about API key management and security
Webhooks
Handle webhook errors and retries
Quick Start
Build your first agent with proper error handling
Need Help?
If you're experiencing persistent errors:
- Review recent changes to your API integration
- Contact support@heppu.ai with the error
request_id