Error Response Format

The GetBill API uses conventional HTTP response codes to indicate the success or failure of an API request. All error responses follow a consistent JSON format:
{
  "error": true,
  "message": "A human-readable error message",
  "code": 400,
  "details": {
    "field_name": ["Specific field error message"]
  }
}
error
boolean
Always true for error responses
message
string
A human-readable description of the error
code
integer
The HTTP status code
details
object
Additional error details, often including field-specific validation errors

HTTP Status Codes

  • 200 OK: The request was successful
  • 201 Created: A new resource was successfully created
  • 400 Bad Request: The request was invalid or malformed
  • 401 Unauthorized: Authentication credentials are missing or invalid
  • 403 Forbidden: The authenticated user doesn’t have permission to access the resource
  • 404 Not Found: The requested resource doesn’t exist
  • 422 Unprocessable Entity: The request is valid but contains semantic errors
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: An unexpected error occurred on the server
  • 502 Bad Gateway: The server received an invalid response from an upstream server
  • 503 Service Unavailable: The service is temporarily unavailable
  • 504 Gateway Timeout: The server didn’t receive a response from an upstream server in time

Common Error Scenarios

Authentication Errors

{
  "error": true,
  "message": "Authentication credentials are missing or invalid",
  "code": 401
}
Solution: Ensure you’re including a valid access token in the Authorization header.

Authorization Errors

{
  "error": true,
  "message": "Required scope \"debts:write\" not found in token",
  "code": 403
}
Solution: Request the appropriate scopes when obtaining your access token.

Validation Errors

{
  "error": true,
  "message": "Validation failed",
  "code": 400,
  "details": {
    "firstname": ["First name is required"],
    "amount": ["Valid amount is required"],
    "phone": ["Phone number is required"]
  }
}
Solution: Check the details object for field-specific errors and correct your request data.

Resource Not Found

{
  "error": true,
  "message": "Debt not found or invalid ID",
  "code": 404
}
Solution: Verify the resource ID exists and you have permission to access it.

Rate Limiting

{
  "error": true,
  "message": "Rate limit exceeded. Please try again later.",
  "code": 429,
  "details": {
    "retry_after": 60,
    "limit": 100,
    "reset_time": "2024-01-15T10:30:00Z"
  }
}
Solution: Implement exponential backoff and respect the retry_after value.

Error Handling Best Practices

1. Implement Proper Error Handling

async function createDebt(debtData) {
  try {
    const response = await fetch('/external-api/v1/debts', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(debtData)
    });

    if (!response.ok) {
      const error = await response.json();
      
      if (response.status === 401) {
        // Handle authentication error
        await refreshToken();
        return createDebt(debtData); // Retry
      }
      
      if (response.status === 400 && error.details) {
        // Handle validation errors
        handleValidationErrors(error.details);
        return;
      }
      
      throw new Error(error.message);
    }

    return await response.json();
  } catch (error) {
    console.error('Failed to create debt:', error);
    throw error;
  }
}

2. Implement Retry Logic

async function apiRequestWithRetry(url, options, maxRetries = 3) {
  let retries = 0;
  
  while (retries < maxRetries) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        // Rate limited - wait and retry
        const retryAfter = response.headers.get('Retry-After') || 1;
        await sleep(retryAfter * 1000);
        retries++;
        continue;
      }
      
      if (response.status >= 500) {
        // Server error - exponential backoff
        await sleep(Math.pow(2, retries) * 1000);
        retries++;
        continue;
      }
      
      return response;
    } catch (error) {
      if (retries === maxRetries - 1) throw error;
      await sleep(Math.pow(2, retries) * 1000);
      retries++;
    }
  }
}

3. Log Errors for Debugging

function logApiError(endpoint, error, requestData = null) {
  console.error('API Error:', {
    endpoint,
    status: error.code,
    message: error.message,
    details: error.details,
    requestData,
    timestamp: new Date().toISOString()
  });
}

4. Handle Specific Error Types

catch (error) {
  if (error instanceof TypeError && error.message.includes('fetch')) {
    // Network connectivity issue
    showNetworkErrorMessage();
    return;
  }
  throw error;
}

Debugging Tips

1. Check Response Headers

Important headers to examine:
  • X-RateLimit-Remaining: Number of requests remaining in the current window
  • X-RateLimit-Reset: When the rate limit window resets
  • Retry-After: How long to wait before retrying (for 429 responses)

2. Validate Request Format

Common issues:
  • Missing or incorrect Content-Type header
  • Malformed JSON in request body
  • Invalid field values or types
  • Missing required fields

3. Use API Testing Tools

Test your requests using tools like:
  • Postman
  • curl
  • Insomnia
  • HTTPie

4. Enable Debug Logging

Include request/response logging in your application to track API interactions and identify patterns in errors.

Support

If you encounter persistent errors or need help with error handling:
  • Check our Status Page for ongoing incidents
  • Review the specific endpoint documentation
  • Contact support at contact@getbill.io with:
    • The specific error message
    • Your request details (without sensitive data)
    • Steps to reproduce the issue