> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lux-core.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Codes

> Complete reference of API error codes and how to handle them

# 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:

```json theme={null}
{
  "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 the `error_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                  |

<Note>
  **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.
</Note>

## 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_*`). |

```json theme={null}
{
  "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: {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. |

```json theme={null}
{
  "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.                                                                                                                                                     |

```json theme={null}
{
  "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.               |

```json theme={null}
{
  "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. |

```json theme={null}
{
  "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. |

```json theme={null}
{
  "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`.           |

```json theme={null}
{
  "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 '{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 {min} and {max}                                                 |
| **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 '{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. |

```json theme={null}
{
  "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} 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. |

```json theme={null}
{
  "statusCode": 429,
  "message": "Too Many Requests",
  "error": "RATE_LIMIT_EXCEEDED"
}
```

**Rate Limits:**

| 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 |

```json theme={null}
{
  "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

<CardGroup cols={2}>
  <Card title="Log All Errors" icon="clipboard-list">
    Log error responses with request IDs for debugging
  </Card>

  <Card title="Retry with Backoff" icon="arrows-rotate">
    Implement exponential backoff for 429 and 5xx errors
  </Card>

  <Card title="Validate Before Sending" icon="check">
    Validate inputs client-side before API calls
  </Card>

  <Card title="Handle Gracefully" icon="shield">
    Show user-friendly messages, not raw API errors
  </Card>
</CardGroup>

## Example Error Handler

```javascript theme={null}
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;
  }
}
```
