Error Handling
This guide explains how to handle errors when integrating with FLUID Network's API, including error code ranges, response structures, retry strategies, and best practices.
Error Response Structure
All API errors return a consistent JSON structure:
{
"error": {
"code": 3009,
"message": "Insufficient funds",
"category": "accounts",
"details": {
"transaction_id": "txn_1234567890",
"available_balance": 5000,
"requested_amount": 10000
}
}
}Response Fields
| Field | Type | Description |
|---|---|---|
code | integer | Numeric error code (see ranges below) |
message | string | Human-readable error message |
category | string | Error category for grouping |
details | object | Additional context (optional) |
Error Code Ranges
FLUID Network uses structured error code ranges to categorize errors:
Range Overview
| Range | Category | Description | Typical Cause |
|---|---|---|---|
| 1000-1999 | General | Application-wide errors | Invalid requests, auth failures, rate limits |
| 2000-2999 | Integration | External service errors | Bank API issues, connector failures, timeouts |
| 3000-3999 | Transactions | Transaction processing | Validation, duplicate references, insufficient funds |
| 4000-4999 | Webhooks | Webhook delivery | Signature validation, delivery failures, timeouts |
| 5000-5999 | Settlements | Settlement processing | Batch errors, invalid currencies, empty batches |
General Errors (1000-1999)
HTTP-Like Errors (1400-1499)
Standard HTTP status code equivalents:
| Code | Error | HTTP Status | Description | Action |
|---|---|---|---|---|
1400 | Bad Request | 400 | Invalid request format or parameters | Fix request structure |
1401 | Unauthorized | 401 | Missing or invalid API key | Check authentication |
1403 | Forbidden | 403 | Insufficient permissions | Verify authorization |
1404 | Not Found | 404 | Resource doesn't exist | Check resource ID |
1405 | Method Not Allowed | 405 | HTTP method not supported | Use correct method |
1409 | Conflict | 409 | Request conflicts with current state | Resolve conflict |
1422 | Invalid Record | 422 | Validation failed on model | Fix validation errors |
1429 | Too Many Requests | 429 | Rate limit exceeded | Implement backoff |
1500 | Internal Server Error | 500 | Unexpected server error | Retry with backoff |
1503 | Service Unavailable | 503 | Service temporarily down | Wait and retry |
Security Errors (1450-1499)
Authentication and authorization failures:
| Code | Error | Severity | Description | Action |
|---|---|---|---|---|
1451 | IP Blocked | High | IP not whitelisted | Add IP to whitelist |
1452 | IP Validation Failed | Medium | IP format invalid | Check IP address |
1453 | Rate Limit by IP | Medium | Too many requests from IP | Implement backoff |
1454 | Rate Limit by Partner | Medium | Partner quota exceeded | Upgrade plan or wait |
1455 | Rate Limit by Bank | Medium | Bank quota exceeded | Contact support |
1456 | Payment Rate Limit | High | Payment processing limit hit | Critical: implement backoff |
HMAC Authentication Errors (1401)
HMAC signature validation failures:
| Code | Error | Description | Action |
|---|---|---|---|
1401 | Signature Missing | No HMAC signature header | Include signature |
1401 | Signature Invalid | Signature doesn't match | Check secret key |
1401 | Timestamp Expired | Request too old (>5 min) | Send fresh request |
1400 | Timestamp Invalid | Timestamp format wrong | Use Unix timestamp |
1401 | Timestamp Missing | No timestamp header | Include timestamp |
Example: Handling Authentication Errors
When handling authentication errors, implement logic to:
Code 1401 (Unauthorized):
- Check if API key is correct for your environment
- Verify Authorization header format:
Bearer {api_key} - For HMAC authentication: verify signature, timestamp, and secret key
- Ensure timestamp is within 5 minutes of current time
Code 1403 (Forbidden):
- Verify account permissions and status
- Check if feature is enabled for your plan
- Contact support if permissions issue persists
Rate Limit Errors (1429, 1453-1456):
- Implement exponential backoff retry strategy
- Log rate limit warnings for monitoring
- Consider implementing request queue to smooth traffic
- Upgrade plan if consistently hitting limits
Integration Errors (2000-2999)
Connector Errors (2001-2099)
Bank integration and connector failures:
| Code | Error | Description | Retry? | Action |
|---|---|---|---|---|
2001 | Bank Connector Error | Generic connector failure | Yes | Retry with backoff |
2002 | Bank API Error | Bank API returned error | Depends | Check error details |
2003 | No Connector Available | Bank not supported | No | Use different bank |
Upstream Errors (2400-2599)
External service communication issues:
| Code | Error | Description | Retry? | Action |
|---|---|---|---|---|
2408 | Upstream Timeout | Request to bank timed out | Yes | Retry with longer timeout |
2500 | Upstream Error | Bank service error | Yes | Retry with backoff |
2502 | Connection Failed | Cannot connect to bank | Yes | Check connectivity |
Example: Handling Integration Errors
When initiating transactions, implement retry logic for integration errors:
Retry Strategy:
- Maximum 3 retry attempts recommended
- Use exponential backoff: 1s, 2s, 4s delays
- Check if error code is retryable before retrying
- Stop immediately for non-retryable errors
Retryable Integration Errors:
2001- Bank Connector Error (temporary connector issue)2002- Bank API Error (may succeed on retry depending on details)2408- Upstream Timeout (retry with longer timeout)2500- Upstream Error (temporary bank service issue)2502- Connection Failed (network connectivity issue)
Implementation Approach:
- Attempt API call
- On error, extract error code from response
- Check if error code is in retryable list
- If retryable and under max attempts: wait with exponential backoff, then retry
- If non-retryable or max attempts reached: throw error permanently
Backoff Calculation:
- Attempt 1 delay: 1000ms (2^0 * 1000)
- Attempt 2 delay: 2000ms (2^1 * 1000)
- Attempt 3 delay: 4000ms (2^2 * 1000)
- Cap maximum delay at 30 seconds
Transaction Errors (3000-3999)
Processing Errors (3001-3099)
Transaction state and validation issues:
| Code | Error | Description | Action |
|---|---|---|---|
3001 | Invalid Status Transition | Cannot change to requested status | Check current status |
3002 | Invalid Approval Method | Approval method not allowed | Use valid method |
3003 | Duplicate Reference | partner_reference already used | Use unique reference |
3004 | Invalid Currency | Currency not supported | Use GHS |
3005 | Limit Exceeded | Amount exceeds transaction limit | Reduce amount |
3006 | Already Processed | Transaction already completed | Check status |
3007 | Invalid Amount | Amount format or value invalid | Validate amount |
3008 | Account Inactive | Customer account not active | Contact support |
3009 | Insufficient Funds | Customer lacks sufficient balance | Notify customer |
Resource Errors (3400+)
| Code | Error | Description | Action |
|---|---|---|---|
3404 | Transaction Not Found | Transaction ID doesn't exist | Verify ID |
Example: Handling Transaction Errors
Implement specific handling for transaction validation and processing errors:
Code 3003 (Duplicate Reference):
- Transaction with this
partner_referencealready exists - Query existing transaction by reference
- Return existing transaction instead of creating duplicate
- This is idempotency in action - safe to return existing result
Code 3004 (Invalid Currency):
- Currency code not supported by FLUID Network
- Valid currency: GHS (Ghana Cedis)
- Display error to user with supported currency
- Do not retry - this is a permanent validation error
Code 3007 (Invalid Amount):
- Amount format or value is invalid
- Amount must be positive integer in smallest currency unit (pesewas)
- Example: 50.00 GHS = 5000 pesewas
- Check for negative values, zero, or non-integer values
Code 3008 (Account Inactive):
- Customer's bank account is not active
- Notify customer to activate their account
- Contact customer support if issue persists
- Do not retry automatically - requires customer action
Code 3009 (Insufficient Funds):
- Customer lacks sufficient balance in their account
- Extract available balance from error details if provided
- Display friendly message: "Insufficient funds. Please add money and try again."
- Notify customer with available vs. requested amount
- Allow customer to retry after adding funds
Webhook Errors (4000-4999)
Delivery Errors (4001-4099)
Webhook sending and receiving issues:
| Code | Error | Description | Action |
|---|---|---|---|
4001 | Delivery Failed | HTTP error from your endpoint | Fix endpoint |
4408 | Timeout | Your endpoint didn't respond in 5s | Optimize response time |
Configuration Errors (4400+)
| Code | Error | Description | Action |
|---|---|---|---|
4400 | Invalid Payload | Webhook payload malformed | Contact support |
4401 | Signature Invalid | HMAC signature mismatch | Check webhook secret |
4403 | Not Subscribed | Event type not enabled | Enable event |
4404 | Not Configured | No webhook URL set | Set webhook URL |
Example: Webhook Error Monitoring
Implement monitoring to track webhook delivery health:
Code 4001 (Delivery Failed):
- Webhook delivery to your endpoint returned HTTP error
- Check your endpoint health and availability
- Verify endpoint URL is correct and accessible
- Review server logs for request handling errors
Code 4408 (Timeout):
- Your endpoint didn't respond within 5 seconds
- Optimize webhook endpoint response time
- Acknowledge webhook immediately (return 200 OK)
- Process webhook payload asynchronously in background job
Code 4401 (Signature Invalid):
- HMAC signature verification failed
- Verify webhook secret configuration matches FLUID Network dashboard
- Check signature calculation algorithm and header format
Monitoring Strategy:
- Track webhook failure rates per event type
- Alert if overall failure rate exceeds 5%
- Alert if authentication error rate exceeds 1%
- Run health checks every 5 minutes
- Log webhook delivery failures with context (error code, event type, attempt count)
Settlement Errors (5000-5999)
Batch Processing Errors (5001-5099)
Settlement batch issues:
| Code | Error | Description | Action |
|---|---|---|---|
5001 | Batch Not Processable | Batch in invalid state | Check batch status |
5002 | Empty Batch | No transactions to settle | Verify transactions |
5003 | Invalid Currency | Currency not supported | Use valid currency |
5004 | Invalid Transaction Type | Wrong transaction in batch | Verify transaction types |
5005 | Already Processed | Batch already settled | Check batch status |
Resource Errors (5400+)
| Code | Error | Description | Action |
|---|---|---|---|
5404 | Batch Not Found | Settlement batch doesn't exist | Verify batch ID |
Error Handling Best Practices
1. Categorize Errors by Retryability
Classify errors into retryable and permanent categories:
Retryable Errors (temporary failures - safe to retry):
1429- Rate limit exceeded1453,1454,1455,1456- Various rate limit errors1500- Internal server error1503- Service unavailable2001,2002- Connector errors2408,2500,2502- Upstream communication errors4001,4408- Webhook delivery issues
Permanent Errors (won't succeed on retry - fix required):
1401- Unauthorized (invalid credentials)1403- Forbidden (insufficient permissions)1404- Not found (resource doesn't exist)3003- Duplicate reference (already processed)3004- Invalid currency (unsupported currency)3007- Invalid amount (validation failure)3008- Account inactive (requires customer action)3009- Insufficient funds (requires customer action)
Implementation: Check error code against retryable list before implementing retry logic.
2. Implement Exponential Backoff
Use exponential backoff for retrying failed requests:
Retry Strategy:
- Maximum 3 retry attempts recommended
- Base delay: 1000ms (1 second)
- Exponential growth: delay = 1000ms × 2^(attempt - 1)
- Add random jitter (0-1000ms) to prevent thundering herd
- Cap maximum delay at 30 seconds
Delay Calculation:
- Attempt 1: 1000ms + jitter
- Attempt 2: 2000ms + jitter
- Attempt 3: 4000ms + jitter
Logic Flow:
- Attempt API call
- On error, extract error code from response
- Check if error code is retryable (skip retry for permanent errors)
- If retryable and under max attempts: calculate delay, wait, retry
- If non-retryable or max attempts reached: throw error permanently
Important: Never retry permanent errors (authentication failures, validation errors, resource not found).
3. Log Errors with Context
Implement comprehensive error logging with contextual information:
Log Entry Structure:
- Timestamp (ISO 8601 format)
- Error code and message from API response
- Error category (authentication, transactions, integration, etc.)
- HTTP status code
- Request context:
- Transaction ID
- Partner reference
- Amount and currency
- Phone number (masked for privacy - only show last 4 digits)
- Stack trace for debugging
Logging Levels:
- Error: All API errors
- Critical: Errors with high severity (codes 1500, 2500, or flagged as high severity)
- Warning: Rate limit warnings, retryable errors
Privacy Considerations:
- Mask sensitive data (phone numbers, account numbers)
- Never log full API keys or secrets
- Use last 4 digits or character masking (e.g.,
+233200****002)
Alerting:
- Send critical alerts for:
- High severity errors (1500, 2500)
- Authentication failures (1401, 1403)
- Sustained rate limiting (1429, 145x)
- Include full context in alerts for faster incident response
4. Provide User-Friendly Messages
Map technical error codes to customer-facing messages:
Error Message Principles:
- Use clear, non-technical language
- Provide actionable guidance when possible
- Avoid exposing internal technical details
- Be empathetic and helpful in tone
Common User-Facing Messages:
| Error Code | User-Friendly Message |
|---|---|
1401 | "We couldn't process your request. Please try again." |
1429 | "Too many requests. Please wait a moment and try again." |
1456 | "High transaction volume. Please try again in a few minutes." |
3003 | "This transaction has already been processed." |
3004 | "The selected currency is not supported." |
3007 | "The amount entered is invalid. Please check and try again." |
3008 | "Your account is inactive. Please contact support." |
3009 | "Insufficient funds. Please add money to your account and try again." |
2001 | "We're experiencing technical difficulties. Please try again later." |
2408 | "The request timed out. Please try again." |
2502 | "Unable to connect to payment service. Please try again." |
| Default | "An unexpected error occurred. Please try again or contact support." |
Implementation Pattern:
- Extract error code from API response
- Map error code to user-friendly message
- Display message to user in UI
- Log technical error details separately for debugging
5. Monitor Error Rates
Track error metrics to proactively identify integration issues:
Key Metrics to Monitor:
- Overall error rate (errors per total requests)
- Error rate by category (authentication, transactions, integration, webhooks, settlements)
- Error rate by specific error code
- Error rate over time windows (last 1 minute, 5 minutes, 15 minutes, 1 hour)
Alerting Thresholds:
- High Priority: Overall error rate exceeds 5%
- Critical: Authentication error rate exceeds 1%
- Warning: Specific error code appears more than 10 times per minute
- Critical: Integration errors (2xxx) exceed 3% of requests
Monitoring Implementation:
- Record each error with: error code, category, timestamp
- Calculate error rates over sliding time windows
- Group errors by category for targeted analysis
- Trigger alerts when thresholds are exceeded
- Track total requests for accurate rate calculation
Dashboard Metrics:
- Error count by category (pie chart)
- Error rate over time (line chart)
- Top 10 error codes by frequency (bar chart)
- Recent error log with context
Best Practices:
- Review error dashboards daily
- Set up real-time alerts for critical thresholds
- Investigate sudden spikes in error rates immediately
- Track error rate trends to identify degradation over time
Testing Error Scenarios
Sandbox Error Simulation
Use FLUID Network sandbox environment with specific test data to trigger errors:
Test Insufficient Funds Error (3009):
- Use very large amount (e.g., 999999999 pesewas)
- Use sandbox test phone number:
+233200000002 - Expected response: Error code 3009 with insufficient funds message
Test Invalid Currency Error (3004):
- Use invalid currency code (e.g.,
ZZZ) - Expected response: Error code 3004 with invalid currency message
Test Duplicate Reference Error (3003):
- Create transaction with specific
partner_reference - Attempt to create another transaction with same
partner_reference - Expected response: First succeeds, second returns error code 3003
Sandbox Test Phone Numbers:
+233200000001- Successful transactions+233200000002- Insufficient funds error+233200000003- Account inactive error+233200000004- Invalid account error
Error Handling Test Suite
Implement comprehensive tests for error handling logic:
Test Cases to Include:
Retry on Transient Errors:
- Mock API to return error code 1500 (internal server error) twice, then succeed
- Verify retry logic attempts request 3 times total
- Verify final result is successful response
No Retry on Permanent Errors:
- Mock API to return error code 3009 (insufficient funds)
- Verify retry logic throws error immediately
- Verify only 1 API attempt is made (no retries)
Log Errors with Context:
- Mock API to return error code 3007 (invalid amount)
- Verify error logging function is called with correct parameters
- Verify log entry contains error code, category, and request context
Exponential Backoff Timing:
- Mock API to fail with retryable error
- Measure delay between retry attempts
- Verify delays follow exponential pattern: ~1s, ~2s, ~4s
User-Friendly Messages:
- Test error code to user message mapping
- Verify all error codes have appropriate messages
- Verify default message for unknown error codes
Testing Tools:
- Use HTTP mocking libraries to simulate API responses
- Mock error responses with proper structure (code, message, category, details)
- Use timing assertions to verify backoff delays
- Test both successful and failed retry scenarios
Quick Reference
Error Decision Tree
Error Received
↓
Is code 1xxx?
↓ Yes → Authentication/Rate limit issue
├─ 1401? → Check API key/signature
├─ 1429/145x? → Implement backoff
└─ 1500/1503? → Retry with backoff
↓ No
Is code 2xxx?
↓ Yes → Integration issue
├─ 2001/2002? → Retry with backoff
├─ 2408/250x? → Retry with longer timeout
└─ 2003? → Bank not supported (permanent)
↓ No
Is code 3xxx?
↓ Yes → Transaction issue
├─ 3003? → Duplicate (check existing)
├─ 3009? → Insufficient funds (notify user)
└─ 3004/3007? → Validation error (fix input)
↓ No
Is code 4xxx?
↓ Yes → Webhook issue
├─ 4001/4408? → Fix webhook endpoint
└─ 4401? → Check webhook secret
↓ No
Is code 5xxx?
↓ Yes → Settlement issue
└─ Contact supportRelated Resources
- Rate Limiting Guide - Handling rate limits
- Idempotency Guide - Preventing duplicate transactions
- Webhook Signature Verification - Validating webhooks
- API Reference - Complete API documentation
Support
If you encounter errors not covered in this guide:
- Email: developers@fluidnetwork.africa
- Slack: Join our community