Documentation Index
Fetch the complete documentation index at: https://docs.finhub.cloud/llms.txt
Use this file to discover all available pages before exploring further.
Error Handling
Comprehensive guide to handling errors across the customer lifecycle flows.
All API errors follow a consistent format:
{
"code": 400,
"message": "Human-readable error message",
"data": {
"error": "Error type",
"details": "Detailed explanation",
"field": "Affected field (if applicable)",
"suggestions": ["Suggested fix 1", "Suggested fix 2"]
}
}
HTTP Status Codes
| Code | Description | Common Causes |
|---|
400 | Bad Request | Validation errors, missing fields |
401 | Unauthorized | Invalid/expired token, wrong credentials |
403 | Forbidden | Insufficient permissions, role mismatch |
404 | Not Found | Resource doesn’t exist |
409 | Conflict | Duplicate resource, state conflict |
422 | Unprocessable Entity | Business rule violation |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server-side error |
Registration Errors
Password Mismatch (400)
{
"code": 400,
"message": "Request validation failed",
"data": {
"errors": [
{
"field": "matchingPassword",
"message": "Password and matching password must be identical"
}
]
}
}
Solution: Ensure password and matchingPassword fields contain identical values.
Invalid Categorization (400)
{
"code": 400,
"message": "Categorization validation failed",
"data": {
"error": "Invalid categorization",
"details": "Feature 'ENHANCED_AML_MONITORING' requires mandatory key 'riskLevel'",
"missingKeys": ["riskLevel"],
"invalidValues": {
"monitoring": "HOURLY is not in allowed values: [WEEKLY, DAILY, REAL_TIME]"
}
}
}
Solution:
- Call
GET /categorization/hierarchy/{tenantId} to get available options
- Check
mandatoryKeys for the feature
- Ensure all mandatory keys are provided
- Validate values against
allowedValues
Tenant Access Denied (403)
{
"code": 403,
"message": "Tenant access denied or categorization not available",
"data": {
"error": "Tenant access denied",
"tenantId": "97e7ff29-15f3-49ef-9681-3bbfcce4f6cd"
}
}
Solution: Verify the X-Tenant-ID header matches your assigned tenant and that categorization is enabled for your tenant.
Organization Already Exists (409)
{
"code": 409,
"message": "Organization already exists",
"data": {
"error": "Duplicate organization",
"registrationNumber": "REG123456789",
"existingOrganizationId": "org-880e8400..."
}
}
Solution: Use a unique registration number or retrieve the existing organization.
Authentication Errors
Invalid Credentials (401)
{
"code": 401,
"message": "Authentication failed",
"data": {
"success": false,
"errorType": "AUTHENTICATION",
"message": "Invalid username or password",
"attempts": 3,
"maxAttempts": 5,
"lockoutTime": null
}
}
Solution: Verify username (email) and password are correct.
Account Locked (401)
{
"code": 401,
"message": "Account locked",
"data": {
"success": false,
"errorType": "AUTHENTICATION",
"message": "Account locked due to multiple failed login attempts",
"attempts": 5,
"maxAttempts": 5,
"lockoutTime": "2026-01-13T11:30:00.000Z",
"lockoutDuration": "30 minutes"
}
}
Solution: Wait for lockout period to expire (30 minutes) or contact support.
Token Expired (401)
{
"code": 401,
"message": "Token expired",
"data": {
"error": "JWT_EXPIRED",
"expiredAt": "2026-01-13T12:00:00.000Z"
}
}
Solution: Obtain a new token via the session creation endpoint.
Verification Errors
Insufficient Permission (403)
{
"code": 403,
"message": "Access denied: Only COMPLIANCE_OFFICER or ADMIN_USER can initiate verification",
"data": {
"userId": "user-660e8400...",
"currentRoles": ["EMPLOYEE", "TRANSACTION_APPROVER"],
"requiredRoles": ["COMPLIANCE_OFFICER", "ADMIN_USER"]
}
}
Solution: Use an account with COMPLIANCE_OFFICER or ADMIN_USER role.
Activation Errors
Missing Consents (400)
{
"code": 400,
"message": "Missing required consents",
"data": {
"activationStatus": "CONSENT_REQUIRED",
"customerId": "cust-550e8400...",
"missingConsentTypes": ["PRIVACY_POLICY", "DATA_PROCESSING"],
"missingConsentDetails": {
"PRIVACY_POLICY": {
"consentType": "PRIVACY_POLICY",
"status": "MISSING",
"acceptUrl": "/api/v2.1/customer/individual/{customerId}/consents/privacy"
}
},
"totalRequiredConsents": 3,
"totalMissingConsents": 2,
"nextSteps": [
"Accept Privacy Policy",
"Accept Data Processing Agreement",
"Retry activation"
]
}
}
Solution: Accept all missing consents using the provided acceptUrl endpoints.
Not Verified (422)
{
"code": 422,
"message": "Customer not verified",
"data": {
"activationStatus": "VERIFICATION_REQUIRED",
"verificationStatus": "PENDING_REVIEW",
"reason": "Customer verification must be APPROVED before activation",
"estimatedCompletionTime": "1-2 business days"
}
}
Solution: Wait for verification to be approved before attempting activation.
Missing ADMIN_USER Role (400)
{
"code": 400,
"message": "Missing required role 'ADMIN_USER' for BUSINESS_TYPE_CLIENT_TO_TENANT organization. At least one employee must have this role."
}
Solution: Ensure the first employee added has the ADMIN_USER role.
Transaction Errors
Insufficient Balance (400)
{
"code": 400,
"message": "Insufficient balance",
"data": {
"availableBalance": "100000",
"requestedAmount": "150000",
"currency": "EUR"
}
}
Solution: Top up the wallet or reduce the transaction amount.
Limit Exceeded (400)
{
"code": 400,
"message": "Transaction limit exceeded",
"data": {
"limitType": "DAILY",
"limit": "5000",
"currentUsage": "4500",
"requestedAmount": "1000",
"currency": "EUR"
}
}
Solution: Wait for limit reset or use a smaller amount.
Beneficiary Not Found (404)
{
"code": 404,
"message": "Beneficiary not found",
"data": {
"iban": "GB82WEST12345698765432",
"suggestion": "Add beneficiary before making transfer"
}
}
Solution: Add the beneficiary using the beneficiaries endpoint before attempting the transfer.
Troubleshooting Checklist
Registration Issues
Authentication Issues
Activation Issues
Transaction Issues
Error Handling Best Practices
- Parse error responses - Always check the
data object for detailed information
- Handle retries carefully - Don’t retry on 400/403/422 errors
- Log error details - Store
code, message, and data for debugging
- Show user-friendly messages - Map technical errors to user-friendly text
- Implement exponential backoff - For 429 and 500 errors