Heppu AI

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 description
  • status (number): HTTP status code
  • code (string): Machine-readable error code (optional)
  • timestamp (string): ISO 8601 timestamp
  • details (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 CodeDescriptionCommon Causes
200OKSuccessful request
201CreatedResource created successfully
204No ContentSuccessful deletion
400Bad RequestInvalid parameters or request body
401UnauthorizedMissing or invalid API key
403ForbiddenValid API key but insufficient permissions
404Not FoundResource doesn't exist
409ConflictResource conflict (duplicate, state mismatch)
422Unprocessable EntityValidation failed
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side error
502Bad GatewayUpstream service unavailable
503Service UnavailableTemporary server maintenance
504Gateway TimeoutRequest 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.errors array 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: 60

Solution:

  • Implement exponential backoff
  • Respect the Retry-After header
  • 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_id if 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

  1. Check Request ID: Include the request_id from error details when contacting support
  2. Enable Verbose Logging: Log full request/response for debugging
  3. Test in Sandbox: Use test API keys to debug without affecting production
  4. Monitor Rate Limits: Track X-RateLimit-* headers to avoid hitting limits
  5. Use Try-Catch: Always wrap API calls in try-catch blocks

Next Steps

Need Help?

If you're experiencing persistent errors:

  • Review recent changes to your API integration
  • Contact support@heppu.ai with the error request_id

On this page