Error Handling
The Cashfin Business API uses conventional HTTP response codes to indicate the success or failure of requests. This guide covers common errors and how to handle them.
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
200 | OK | Request succeeded |
201 | Created | Resource successfully created |
400 | Bad Request | Invalid request parameters |
401 | Unauthorized | Invalid or missing API key |
403 | Forbidden | Valid key but insufficient permissions |
404 | Not Found | Requested resource doesn't exist |
409 | Conflict | Resource conflict (e.g., duplicate entry) |
422 | Unprocessable Entity | Validation errors |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server-side error |
Error Response Format
All error responses follow a consistent structure:
json
{
"success": false,
"error": "Brief error description",
"errors": {
"field_name": "Specific field error message"
},
"message": "Detailed error message"
}Error Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Always false for errors |
error | string | Brief error description |
errors | object | Field-specific validation errors (optional) |
message | string | Detailed error message (optional) |
Common Error Scenarios
Authentication Errors (401)
json
{
"success": false,
"message": "Unauthorized access!"
}Causes:
- Missing
Authorizationheader - Invalid or expired API key
- Malformed API key format
Solution:
- Verify your API key is correct
- Ensure the
Authorizationheader is present - Check if the key has been revoked
Validation Errors (400/422)
json
{
"success": false,
"error": "There are problems with your submission",
"errors": {
"title": "Title is required",
"price": "Price must be greater than 0"
}
}Causes:
- Missing required fields
- Invalid field formats
- Values outside allowed ranges
Solution:
- Check the
errorsobject for field-specific issues - Refer to the API documentation for field requirements
Resource Not Found (404)
json
{
"success": false,
"error": "Product not found"
}Causes:
- Invalid resource ID
- Resource doesn't belong to your business
- Resource has been deleted
Solution:
- Verify the resource ID is correct
- Ensure you have access to the resource
Conflict Errors (409)
json
{
"success": false,
"error": "Category with this title already exists"
}Causes:
- Duplicate unique field (e.g., SKU, title)
- Resource already exists
Solution:
- Use a unique value for the conflicting field
- Update the existing resource instead
Rate Limit Errors (429)
json
{
"success": false,
"error": "Rate limit exceeded. Please try again later.",
"retry_after": 30
}Solution:
- Wait for the
retry_afterperiod - Implement exponential backoff
- See Rate Limiting for best practices
Error Handling Examples
JavaScript/TypeScript
typescript
interface CashfinError {
success: false;
error: string;
errors?: Record<string, string>;
message?: string;
}
async function createProduct(productData: object) {
try {
const response = await fetch(
"https://api.cashfin.africa/business/product/create",
{
method: "POST",
headers: {
Authorization: process.env.CASHFIN_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify(productData),
}
);
const data = await response.json();
if (!response.ok) {
// Handle specific error types
switch (response.status) {
case 401:
throw new Error("Authentication failed. Check your API key.");
case 422:
const fieldErrors = (data as CashfinError).errors;
throw new Error(`Validation failed: ${JSON.stringify(fieldErrors)}`);
case 429:
throw new Error("Rate limit exceeded. Retry later.");
default:
throw new Error(data.error || "An unexpected error occurred");
}
}
return data;
} catch (error) {
console.error("API Error:", error);
throw error;
}
}PHP
php
<?php
function createProduct(array $productData): array
{
$apiKey = getenv('CASHFIN_API_KEY');
$ch = curl_init('https://api.cashfin.africa/business/product/create');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: {$apiKey}",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode($productData)
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);
if ($httpCode >= 400) {
switch ($httpCode) {
case 401:
throw new Exception('Authentication failed. Check your API key.');
case 422:
$errors = $data['errors'] ?? [];
throw new Exception('Validation failed: ' . json_encode($errors));
case 429:
throw new Exception('Rate limit exceeded. Retry later.');
default:
throw new Exception($data['error'] ?? 'An unexpected error occurred');
}
}
return $data;
}Python
python
import requests
import os
class CashfinAPIError(Exception):
def __init__(self, message, status_code, errors=None):
self.message = message
self.status_code = status_code
self.errors = errors or {}
super().__init__(self.message)
def create_product(product_data: dict) -> dict:
api_key = os.environ.get('CASHFIN_API_KEY')
response = requests.post(
'https://api.cashfin.africa/business/product/create',
headers={
'Authorization': api_key,
'Content-Type': 'application/json'
},
json=product_data
)
data = response.json()
if not response.ok:
if response.status_code == 401:
raise CashfinAPIError('Authentication failed', 401)
elif response.status_code == 422:
raise CashfinAPIError('Validation failed', 422, data.get('errors'))
elif response.status_code == 429:
raise CashfinAPIError('Rate limit exceeded', 429)
else:
raise CashfinAPIError(data.get('error', 'Unknown error'), response.status_code)
return dataDebugging Tips
- Log Full Responses: Include status codes and response bodies in logs
- Use Request IDs: Include custom request IDs for tracing
- Check Timestamps: Verify your server's time is synchronized
- Validate Locally: Validate data before sending to the API
- Test in Sandbox: Use the sandbox environment to reproduce issues
Need Help?
If you encounter persistent errors:
- Check the Status Page for outages
- Review the specific endpoint documentation
- Contact [email protected] with:
- Your request ID
- Error response
- Timestamp
- Request details (sanitized)