Error Codes
Every error response follows a consistent format. This page lists all HTTP status codes and application-level error codes.
Error Response Format
{
"code": "VALIDATION_ERROR",
"message": "Invalid format for field: account_id",
"details": [
{
"field": "account_id",
"reason": "Expected format: UUID",
"value": "invalid-id"
}
],
"request_id": "req-a1b2c3d4",
"timestamp": "2026-02-28T10:00:00Z",
"documentation_url": "https://docs.korastratum.com/cba/reference/error-codes"
}
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable description |
details | array | Field-level validation errors (if applicable) |
request_id | string | Unique request ID for support/tracing |
timestamp | string | ISO 8601 timestamp |
documentation_url | string | Link to relevant documentation |
HTTP Status Codes
| Status | When It Occurs |
|---|---|
400 | Invalid input, missing required fields, malformed JSON |
401 | Missing token, expired token, invalid signature |
403 | Insufficient role, insufficient scope, feature disabled |
404 | Resource not found |
409 | Duplicate resource, idempotency conflict |
422 | Business rule violation (insufficient funds, limit exceeded, unbalanced journal) |
429 | Rate limit exceeded |
500 | Internal server error or database error |
503 | Dependent service unavailable |
Application Error Codes
Authentication & Authorization
| Code | HTTP | Description |
|---|---|---|
UNAUTHORIZED | 401 | No authorization token provided |
INVALID_TOKEN | 401 | JWT signature verification failed |
TOKEN_EXPIRED | 401 | Access token has expired |
FORBIDDEN | 403 | Action not permitted for this user |
INSUFFICIENT_ROLE | 403 | User role does not meet minimum requirement |
INSUFFICIENT_SCOPE | 403 | Token scopes do not include required permission |
Validation
| Code | HTTP | Description |
|---|---|---|
VALIDATION_ERROR | 400 | One or more fields failed validation — check details |
INVALID_FORMAT | 400 | Field value doesn't match expected format |
MISSING_FIELD | 400 | Required field not provided |
Resources
| Code | HTTP | Description |
|---|---|---|
RESOURCE_NOT_FOUND | 404 | Generic resource not found |
ACCOUNT_NOT_FOUND | 404 | Account ID or number doesn't exist |
CUSTOMER_NOT_FOUND | 404 | Customer doesn't exist in this tenant |
CONFLICT | 409 | Resource state conflict |
DUPLICATE_RESOURCE | 409 | Resource with this identifier already exists |
Idempotency
| Code | HTTP | Description |
|---|---|---|
IDEMPOTENCY_CONFLICT | 409 | Idempotency key reused with a different request body |
Accounts
| Code | HTTP | Description |
|---|---|---|
ACCOUNT_FROZEN | 422 | Account is frozen — debits are blocked |
ACCOUNT_CLOSED | 422 | Account is closed — all operations blocked |
ACCOUNT_BLOCKED | 422 | Account is blocked by compliance |
Transactions
| Code | HTTP | Description |
|---|---|---|
INSUFFICIENT_FUNDS | 422 | Available balance is less than the transfer amount + fees |
DAILY_LIMIT_EXCEEDED | 422 | Daily transaction limit exceeded |
WEEKLY_LIMIT_EXCEEDED | 422 | Weekly transaction limit exceeded |
MONTHLY_LIMIT_EXCEEDED | 422 | Monthly transaction limit exceeded |
SINGLE_LIMIT_EXCEEDED | 422 | Single transaction amount exceeds limit |
DUPLICATE_REFERENCE | 409 | Transaction reference already used |
TRANSACTION_NOT_FOUND | 404 | Transaction ID doesn't exist |
General Ledger
| Code | HTTP | Description |
|---|---|---|
JOURNAL_NOT_BALANCED | 422 | Total debits do not equal total credits |
JOURNAL_EMPTY | 422 | Journal has no entries |
PERIOD_CLOSED | 422 | Cannot post to a closed or locked fiscal period |
ACCOUNT_CLOSED | 422 | Cannot post to a closed GL account |
HEADER_ACCOUNT | 422 | Cannot post directly to a header account |
Rate Limiting
| Code | HTTP | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests — includes retry_after field in seconds |
System
| Code | HTTP | Description |
|---|---|---|
INTERNAL_ERROR | 500 | Unexpected server error |
DATABASE_ERROR | 500 | Database operation failed |
SERVICE_UNAVAILABLE | 503 | Dependent service (NIBSS, Interswitch) is down |
Common Error Scenarios
Unbalanced Journal
{
"code": "JOURNAL_NOT_BALANCED",
"message": "Journal entries do not balance: debits=100000.00, credits=95000.00",
"request_id": "req-abc123"
}
Fix: Ensure total debit amounts equal total credit amounts.
Insufficient Funds
{
"code": "INSUFFICIENT_FUNDS",
"message": "Insufficient funds: available=50000.00, required=100500.00",
"request_id": "req-def456"
}
Fix: The required amount includes fees. Ensure the source account has enough available balance.
Idempotency Conflict
{
"code": "IDEMPOTENCY_CONFLICT",
"message": "Idempotency key already used with a different request body",
"request_id": "req-ghi789"
}
Fix: Use a new idempotency key, or ensure you're sending the exact same request body as the original.
Best Practices
- Check
code, notmessage— The message may change; the code is stable. - Retry on 503 — External provider errors are transient. Retry with exponential backoff.
- Never retry 4xx — Fix the request before retrying.
- Use
request_idfor support — Include it when contacting support for faster resolution.