Skip to main content

Error Handling

Comprehensive guide to handling errors across the customer lifecycle flows.

Error Response Format

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

CodeDescriptionCommon Causes
400Bad RequestValidation errors, missing fields
401UnauthorizedInvalid/expired token, wrong credentials
403ForbiddenInsufficient permissions, role mismatch
404Not FoundResource doesn’t exist
409ConflictDuplicate resource, state conflict
422Unprocessable EntityBusiness rule violation
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-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:
  1. Call GET /categorization/hierarchy/{tenantId} to get available options
  2. Check mandatoryKeys for the feature
  3. Ensure all mandatory keys are provided
  4. 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

  • Valid email format
  • Password meets requirements (8+ chars, mixed case, numbers, special)
  • password matches matchingPassword
  • Valid tenant ID in header
  • Categorization values match allowed values

Authentication Issues

  • Correct username (email)
  • Correct password
  • Valid tenant key and secret
  • Account not locked
  • Token not expired

Activation Issues

  • Verification status is APPROVED
  • All three consents accepted (Terms, Privacy, Data Processing)
  • Customer not already active
  • For B2B: At least one employee with ADMIN_USER role

Transaction Issues

  • Wallet is ACTIVE
  • Sufficient balance
  • Within transaction limits
  • Beneficiary exists and is active
  • Valid payment consent in place

Error Handling Best Practices

  1. Parse error responses - Always check the data object for detailed information
  2. Handle retries carefully - Don’t retry on 400/403/422 errors
  3. Log error details - Store code, message, and data for debugging
  4. Show user-friendly messages - Map technical errors to user-friendly text
  5. Implement exponential backoff - For 429 and 500 errors