Error Codes
This page documents all error codes returned by the LuxCore API, along with their meanings and recommended solutions.Error Response Format
All errors follow a consistent JSON format:{
"statusCode": 400,
"message": "Human-readable error message",
"error_code": "ERROR_CODE",
"timestamp": "2025-01-28T10:00:00.000Z"
}
HTTP Status Codes
| Status Code | Meaning |
|---|---|
200 | Success |
201 | Created |
204 | No Content (successful deletion) |
400 | Bad Request - Invalid parameters |
401 | Unauthorized - Invalid or missing API key |
403 | Forbidden - Insufficient permissions |
404 | Not Found - Resource doesn’t exist |
422 | Unprocessable Entity - Validation error |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error |
503 | Service Unavailable |
Payment Error Codes Quick Reference
The following error codes can be returned in theerror_code field when a payment fails:
| Error Code | HTTP Status | Description | Recoverable |
|---|---|---|---|
INSUFFICIENT_BALANCE | 400 | Merchant balance too low for withdrawal | ✅ Wait for deposits |
MISSING_REQUISITES | 400 | No available requisites for this amount | ✅ Wait/retry |
NO_AVAILABLE_REQUISITES | 400 | All requisites are locked by pending transactions | ✅ Wait/retry |
INVALID_METHOD | 400 | Payment method not configured or inactive | ❌ Contact support |
INVALID_WITHDRAWAL_DATA | 400 | Invalid payout details (bank account, etc.) | ✅ Fix data |
UNSUPPORTED_CURRENCY | 400 | Currency not supported | ❌ Use different currency |
WITHDRAWAL_NOT_SUPPORTED | 400 | Method doesn’t support withdrawals | ❌ Use different method |
MERCHANT_REFERENCE_DUPLICATE | 200 | Payment with this reference exists | ⚠️ Returns existing |
VALIDATION_ERROR | 400 | Request validation failed | ✅ Fix request |
PROVIDER_ERROR | 500 | Payment provider returned an error | ✅ Retry later |
TTL_EXPIRED | 400 | Payment expired before completion | ❌ Create new payment |
LOCK_TIMEOUT | 400 | Could not acquire lock on resource | ✅ Retry |
TRANSACTION_ERROR | 500 | Transaction processing error | ✅ Retry |
INVALID_CLABE | 400 | Invalid CLABE format (18 digits) | ✅ Fix data |
INVALID_CVU | 400 | Invalid CVU format (22 digits) | ✅ Fix data |
INVALID_BSB | 400 | Invalid BSB format (6 digits, XXX-XXX) | ✅ Fix data |
INVALID_PAYID | 400 | Invalid PayID identifier | ✅ Fix data |
PAYID_NOT_FOUND | 400 | PayID identifier not registered in NPP | ✅ Verify with recipient |
LIMIT_EXCEEDED | 400 | Transaction limit exceeded | ❌ Reduce amount |
DAILY_LIMIT_EXCEEDED | 400 | Daily transaction limit reached | ❌ Wait for next day |
MONTHLY_LIMIT_EXCEEDED | 400 | Monthly transaction limit reached | ❌ Wait for next month |
METHOD_NOT_AVAILABLE | 400 | Payment method not available | ❌ Use different method |
METHOD_NOT_CONFIGURED | 400 | Payment method not configured for merchant | ❌ Contact support |
DUPLICATE_REFERENCE | 400 | Duplicate reference detected | ⚠️ Use unique reference |
PAYMENT_ALREADY_PROCESSED | 400 | Payment already in terminal status | ❌ Cannot modify |
PAYMENT_ALREADY_EXISTS | 400 | Payment already exists | ⚠️ Returns existing |
DATABASE_ERROR | 500 | Internal database error | ✅ Retry |
TIMEOUT | 504 | Operation timed out | ✅ Retry |
Recoverable errors (✅) can typically be resolved by waiting and retrying, or by fixing the request data.
Non-recoverable errors (❌) require configuration changes or using different parameters.
Authentication Errors
INVALID_API_KEY
| HTTP Status | 401 |
| Message | API key not found or invalid |
| Cause | The provided API key is incorrect, expired, or doesn’t exist |
| Solution | Verify you’re using the correct API key provided by your LuxCore account manager. Ensure you’re using the correct key for the environment (qp_test_sk_* or qp_prod_sk_*). |
{
"statusCode": 401,
"message": "API key not found or invalid",
"error": "INVALID_API_KEY"
}
MISSING_API_KEY
| HTTP Status | 401 |
| Message | API key is required |
| Cause | No X-API-Key header was provided |
| Solution | Include the X-API-Key header in your request |
INSUFFICIENT_SCOPES
| HTTP Status | 403 |
| Message | API key lacks required scope: |
| Cause | Your API key doesn’t have permission for this operation |
| Solution | Contact your LuxCore account manager to request additional scopes for your API key |
Payment Errors
INSUFFICIENT_BALANCE
| HTTP Status | 400 |
| Message | Insufficient balance for withdrawal |
| Cause | Your merchant balance is too low for the requested withdrawal |
| Solution | Check your balance via the Balance API. To add funds, you can request the LuxCore team to finalize a pending deposit for the required amount, which will credit your merchant balance. |
{
"statusCode": 400,
"message": "Insufficient balance for withdrawal",
"error": "INSUFFICIENT_BALANCE"
}
MISSING_REQUISITES
| HTTP Status | 400 |
| Message | No available requisites for this operation |
| Cause | No requisites (bank accounts/payment instruments) are currently available for processing. This typically happens when: (1) Multiple transactions with the same amount are created simultaneously, exceeding the number of available requisites, (2) All requisites are already locked by pending transactions, (3) No requisites are configured for this payment method/currency combination |
| Solution | Wait for existing pending transactions to complete or fail (freeing up requisites). If this persists, contact LuxCore support to check requisite configuration or increase capacity. Consider implementing request queuing on your side. |
{
"transaction_id": "pay_1761290149387_6149e9c2",
"status": "failed",
"amount": 200000,
"currency": "ARS",
"method": "bank_transfer",
"type": "deposit",
"merchant_reference": "fb384323-a356-4877-b9ff-9de8d0a3c126",
"created_at": "2025-10-24T07:15:49.387Z",
"error_code": "MISSING_REQUISITES",
"error_message": "No available requisites for this operation"
}
NO_AVAILABLE_REQUISITES
| HTTP Status | 400 |
| Message | No available requisites for this operation |
| Cause | Similar to MISSING_REQUISITES - no free requisites are available. This is a more specific error code used when the system attempted to find a requisite but all were locked or unavailable. |
| Solution | Same as MISSING_REQUISITES. Wait for pending transactions to reach terminal status (completed/failed), or contact support for requisite capacity increase. |
INVALID_METHOD
| HTTP Status | 400 |
| Message | Payment method is not configured or inactive |
| Cause | The requested payment method is not enabled for your merchant account, not supported for this currency, or has been deactivated |
| Solution | Contact support to enable the payment method. Verify the method is supported for your target currency and region. |
{
"statusCode": 400,
"message": "Payment method 'bank_transfer' is not configured for currency USD",
"error": "INVALID_METHOD"
}
INVALID_WITHDRAWAL_DATA
| HTTP Status | 400 |
| Message | Invalid withdrawal data provided |
| Cause | The payout object contains invalid or incomplete data (e.g., invalid bank account format, missing recipient name, unsupported bank code) |
| Solution | Verify all payout fields: recipient_name (required), bank_account (valid format for country), bank_code (valid bank identifier). Check country-specific validation rules. |
{
"statusCode": 400,
"message": "Invalid bank account format for ARS withdrawals",
"error": "INVALID_WITHDRAWAL_DATA"
}
UNSUPPORTED_CURRENCY
| HTTP Status | 400 |
| Message | Currency is not supported |
| Cause | The specified currency code is not supported by LuxCore or not enabled for your merchant account |
| Solution | Use a supported currency code. Contact support to enable additional currencies. Supported currencies: ARS, AUD, BRL, CNY, COP, EUR, GEL, LKR, MXN, TRY, USD, UYU. |
{
"statusCode": 400,
"message": "Currency 'EUR' is not supported for this merchant",
"error": "UNSUPPORTED_CURRENCY"
}
WITHDRAWAL_NOT_SUPPORTED
| HTTP Status | 400 |
| Message | Withdrawals are not supported for this payment method |
| Cause | The specified payment method only supports deposits, not withdrawals |
| Solution | Use a different payment method that supports withdrawals. Check method capabilities via the Methods API. |
MERCHANT_REFERENCE_DUPLICATE
| HTTP Status | 200 (returns existing payment) |
| Message | N/A - existing payment is returned |
| Cause | A payment with this merchant_reference already exists. LuxCore uses idempotency based on merchant_reference to prevent duplicate payments. |
| Solution | This is not an error - the API returns the existing payment. If you need to create a new payment, use a unique merchant_reference. |
{
"transaction_id": "pay_existing_123",
"status": "pending",
"merchant_reference": "order-12345",
"created_at": "2025-10-24T07:10:00.000Z",
"_note": "Existing payment returned due to duplicate merchant_reference"
}
Payment Status Errors
METHOD_NOT_AVAILABLE
| HTTP Status | 400 |
| Message | Payment method '' is not available |
| Cause | The requested payment method is not enabled for your account or not supported for this operation |
| Solution | Contact support to enable the payment method, or use an alternative method |
INVALID_AMOUNT
| HTTP Status | 400 |
| Message | Amount must be between and |
| Cause | The payment amount is outside allowed limits |
| Solution | Ensure amount is within the method’s min/max limits. Check limits via the Methods API. |
INVALID_CURRENCY
| HTTP Status | 400 |
| Message | Currency '' is not supported |
| Cause | The specified currency is not valid or not enabled |
| Solution | Use a supported currency code (e.g., MXN, TRY, USD) |
PAYMENT_NOT_FOUND
| HTTP Status | 404 |
| Message | Payment not found |
| Cause | The payment ID doesn’t exist or doesn’t belong to your merchant |
| Solution | Verify the payment ID is correct |
PAYMENT_ALREADY_PROCESSED
| HTTP Status | 400 |
| Message | Payment cannot be cancelled in current status |
| Cause | The payment is already in a terminal status (only pending payments can be cancelled) |
| Solution | Check the payment status. Completed, failed, or cancelled payments cannot be modified. |
INVALID_CLABE
| HTTP Status | 400 |
| Message | Invalid CLABE format |
| Cause | The bank account number (CLABE) is invalid |
| Solution | Verify the CLABE is 18 digits and passes checksum validation |
INVALID_CVU
| HTTP Status | 400 |
| Message | Invalid CVU format |
| Cause | The bank account number (CVU) is invalid |
| Solution | Verify the CVU is 22 digits and passes checksum validation |
INVALID_BSB
| HTTP Status | 400 |
| Message | Invalid BSB format |
| Cause | The BSB (Bank-State-Branch) number is invalid |
| Solution | Verify the BSB is 6 digits in XXX-XXX format (e.g., 062-000). BSB must be a valid Australian bank branch code. |
INVALID_PAYID
| HTTP Status | 400 |
| Message | Invalid PayID identifier |
| Cause | The PayID value does not match the specified payid_type format |
| Solution | Verify the PayID format: email must be a valid email, phone must be in E.164 format (e.g., +61412345678), abn must be a valid 11-digit Australian Business Number. |
{
"statusCode": 400,
"message": "Invalid PayID: expected valid email for payid_type 'email'",
"error": "INVALID_PAYID"
}
PAYID_NOT_FOUND
| HTTP Status | 400 |
| Message | PayID not registered |
| Cause | The PayID identifier is not registered in Australia’s New Payments Platform (NPP) |
| Solution | Verify the PayID with the recipient. The recipient must register their PayID through their Australian bank before receiving payments. |
PAYOUT_DETAILS_REQUIRED
| HTTP Status | 400 |
| Message | Payout details are required for withdrawal |
| Cause | Withdrawal request is missing required payout object |
| Solution | Include payout with recipient_name and either bank_account/bank_code (for bank transfers) or payid/payid_type (for PayID) |
Webhook Errors
WEBHOOK_NOT_FOUND
| HTTP Status | 404 |
| Message | Webhook not found |
| Cause | The webhook ID doesn’t exist |
| Solution | Verify the webhook ID or list all webhooks to find the correct one |
INVALID_WEBHOOK_URL
| HTTP Status | 400 |
| Message | Invalid webhook URL |
| Cause | The URL is not a valid HTTPS endpoint |
| Solution | Use a publicly accessible HTTPS URL |
WEBHOOK_DELIVERY_FAILED
| HTTP Status | N/A (webhook event status) |
| Message | Webhook delivery failed after attempts |
| Cause | Your server returned a non-2xx response or timed out |
| Solution | Check your server logs. Ensure your endpoint returns 200 within 30 seconds. |
Rate Limit Errors
RATE_LIMIT_EXCEEDED
| HTTP Status | 429 |
| Message | Too Many Requests |
| Cause | You’ve exceeded the rate limit for this endpoint |
| Solution | Implement exponential backoff. Check the Retry-After header for wait time. |
{
"statusCode": 429,
"message": "Too Many Requests",
"error": "RATE_LIMIT_EXCEEDED"
}
| Endpoint Type | Limit |
|---|---|
| Payment creation | 5000 requests/minute (burst: 500/10sec) |
| Standard endpoints | 100 requests/minute |
Validation Errors
VALIDATION_ERROR
| HTTP Status | 400 or 422 |
| Message | Varies based on field |
| Cause | Request body failed validation |
| Solution | Check the error message for specific field issues |
{
"statusCode": 400,
"message": [
"amount must be a positive number",
"customer.email must be a valid email"
],
"error": "Bad Request"
}
Server Errors
INTERNAL_ERROR
| HTTP Status | 500 |
| Message | Internal server error |
| Cause | An unexpected error occurred on our servers |
| Solution | Retry the request. If the issue persists, contact support. |
SERVICE_UNAVAILABLE
| HTTP Status | 503 |
| Message | Service Unavailable |
| Cause | The service is temporarily unavailable |
| Solution | Wait and retry. Check our status page for outages. |
Error Handling Best Practices
Log All Errors
Log error responses with request IDs for debugging
Retry with Backoff
Implement exponential backoff for 429 and 5xx errors
Validate Before Sending
Validate inputs client-side before API calls
Handle Gracefully
Show user-friendly messages, not raw API errors
Example Error Handler
async function makeApiRequest(endpoint, options, attempt = 0, maxRetries = 3) {
try {
const response = await fetch(endpoint, options);
if (!response.ok) {
const error = await response.json();
switch (response.status) {
case 401:
throw new AuthenticationError(error.message);
case 429:
if (attempt >= maxRetries) throw new ApiError('Max retries exceeded', 429);
const retryAfter = response.headers.get('Retry-After') || 60;
await sleep(retryAfter * 1000);
return makeApiRequest(endpoint, options, attempt + 1, maxRetries);
case 400:
case 422:
throw new ValidationError(error.message);
default:
throw new ApiError(error.message, response.status);
}
}
return response.json();
} catch (error) {
if (error.name === 'NetworkError') {
if (attempt >= maxRetries) throw error;
await sleep(1000 * Math.pow(2, attempt));
return makeApiRequest(endpoint, options, attempt + 1, maxRetries);
}
throw error;
}
}
