Skip to main content

Error Codes

Every error response follows a consistent envelope. This page lists all HTTP status codes and application-level error codes.

Error Response Format

{
"success": false,
"error": "Human-readable error message",
"code": "ERROR_CODE",
"details": [],
"timestamp": "2026-02-27T14:22:00Z",
"path": "/api/v1/transfers/external",
"method": "POST"
}
FieldTypeDescription
successbooleanAlways false for errors
errorstringHuman-readable description
codestringMachine-readable error code
detailsarrayValidation errors or additional context
timestampstringISO 8601 timestamp
pathstringRequest path
methodstringHTTP method

HTTP Status Codes

StatusTitleWhen It Occurs
400Bad RequestInvalid input, missing required fields, malformed JSON
401UnauthorizedMissing token, expired token, invalid token
403ForbiddenInsufficient permissions, feature disabled, wallet frozen
404Not FoundResource doesn't exist
409ConflictDuplicate entry (e.g. beneficiary already exists)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server failure
503Service UnavailableDependency unavailable (NIBSS, Interswitch)

Application Error Codes

Authentication

CodeHTTPDescription
INVALID_CREDENTIALS401Email or password incorrect
UNAUTHORIZED401No authorization token provided
INVALID_TOKEN401Token is malformed or signature verification failed
TOKEN_EXPIRED401Access token has expired — refresh it
ACCOUNT_LOCKED403Account locked after too many failed login attempts
MFA_REQUIRED4032FA code required but not provided
INVALID_MFA_CODE4012FA code is incorrect or expired

Validation

CodeHTTPDescription
VALIDATION_ERROR400One or more fields failed validation. Check details array.
MISSING_FIELD400Required field not provided
INVALID_FORMAT400Field value doesn't match expected format

Tenant

CodeHTTPDescription
TENANT_NOT_FOUND404The specified tenant ID doesn't exist
TENANT_INACTIVE403Tenant account is disabled
FEATURE_DISABLED403Requested feature is not enabled for this tenant

Accounts & Wallets

CodeHTTPDescription
USER_NOT_FOUND404User doesn't exist in this tenant
ACCOUNT_NOT_FOUND404Wallet or account doesn't exist
WALLET_FROZEN403Wallet is frozen — debits are blocked
WALLET_INACTIVE403Wallet has been deactivated

Transfers

CodeHTTPDescription
INSUFFICIENT_FUNDS400Wallet balance is less than transfer amount + fees
LIMIT_EXCEEDED400Daily or monthly transaction limit exceeded
TRANSFER_FAILED500Transfer processing failed at the provider
INVALID_ACCOUNT400Recipient account number is invalid
INVALID_BANK_CODE400Bank code not recognized
FRAUD_DETECTED403Transaction blocked by fraud detection
DUPLICATE_TRANSFER409Identical transfer submitted within dedup window

Loans

CodeHTTPDescription
LOAN_NOT_ELIGIBLE400User doesn't meet eligibility criteria
LOAN_LIMIT_EXCEEDED400Requested amount exceeds maximum for this product
EXISTING_LOAN409User has an outstanding loan that must be repaid first
APPLICATION_NOT_FOUND404Loan application doesn't exist

Savings

CodeHTTPDescription
MINIMUM_AMOUNT400Deposit is below the product minimum
EARLY_WITHDRAWAL400Cannot withdraw from locked savings before maturity
SAVINGS_NOT_FOUND404Savings account doesn't exist

Bill Payments

CodeHTTPDescription
BILLER_NOT_FOUND404Biller ID is invalid
CUSTOMER_NOT_FOUND400Customer reference not recognized by biller
PAYMENT_FAILED500Payment processing failed at the provider

Rate Limiting

CodeHTTPDescription
RATE_LIMIT_EXCEEDED429Too many requests — wait and retry

General

CodeHTTPDescription
DUPLICATE_ENTRY409Resource already exists
INVALID_REFERENCE400Foreign key or reference doesn't exist
INTERNAL_ERROR500Unexpected server error
SERVICE_UNAVAILABLE503External dependency is down

Common Error Scenarios

Missing X-Tenant-ID header

{
"success": false,
"error": "X-Tenant-ID header is required",
"code": "TENANT_NOT_FOUND"
}

Fix: Include the X-Tenant-ID header in every request.

Expired Token

{
"success": false,
"error": "Token has expired",
"code": "TOKEN_EXPIRED"
}

Fix: Call POST /api/v1/auth/refresh with your refresh token to get a new access token.

Insufficient Funds

{
"success": false,
"error": "Insufficient funds for this transaction",
"code": "INSUFFICIENT_FUNDS",
"details": {
"required": 100100.00,
"available": 50000.00
}
}

Fix: Ensure the source wallet has enough balance to cover the amount plus fees.

Validation Error

{
"success": false,
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": [
{ "field": "amount", "message": "Amount must be greater than 0" },
{ "field": "recipientAccountNumber", "message": "Account number is required" }
]
}

Fix: Correct the fields listed in the details array and retry.

Best Practices

  • Check code, not error — The error string may change; the code is stable.
  • Retry on 503 — External provider errors are transient. Retry with exponential backoff.
  • Never retry 4xx — Client errors require fixing the request before retrying.
  • Log the full response — Include timestamp, path, and method in your logs for debugging.