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

# Error Codes

> Complete reference for all API error codes

## Error Response Format

All errors follow a consistent structure:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": [
      {
        "field": "amount",
        "message": "Amount must be positive"
      }
    ]
  }
}
```

## HTTP Status Codes

| Status | Description                                                     |
| ------ | --------------------------------------------------------------- |
| `400`  | Bad Request - Invalid parameters                                |
| `401`  | Unauthorized - Invalid or missing API key                       |
| `404`  | Not Found - Resource doesn't exist                              |
| `409`  | Conflict - Duplicate or conflicting resource                    |
| `422`  | Unprocessable Entity - Payment declined or business logic error |
| `429`  | Too Many Requests - Rate limit exceeded                         |
| `500`  | Internal Server Error - Server error (rare)                     |
| `503`  | Service Unavailable - Temporary disruption                      |

## Client Errors (400-499)

### Validation Errors

#### VALIDATION\_ERROR

**Status:** 400\
**Meaning:** Invalid request parameters

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": [
      {
        "field": "amount",
        "message": "Amount must be positive"
      }
    ]
  }
}
```

**Common Causes:**

* Missing required fields
* Invalid data types
* Out of range values
* Invalid format (email, phone, etc.)

**Resolution:**

* Review request parameters
* Check data types and formats
* Ensure all required fields are included

### Authentication Errors

#### UNAUTHORIZED

**Status:** 401\
**Meaning:** Invalid or missing API key

```json theme={null}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}
```

**Common Causes:**

* Missing or invalid `x-api-key` header
* Wrong environment (sandbox key in production)
* Incorrect header format

**Resolution:**

* Verify your `x-api-key` is correct
* Ensure using correct environment credentials

### Resource Errors

#### NOT\_FOUND

**Status:** 404\
**Meaning:** Resource not found

```json theme={null}
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Payment order not found"
  }
}
```

**Common Causes:**

* Invalid resource ID
* Resource doesn't exist
* Wrong ID format

**Resolution:**

* Verify the resource ID
* Check if resource was deleted
* Use the correct ID (Cheqpay ID or external ID)

#### DUPLICATE

**Status:** 409\
**Meaning:** Resource already exists

```json theme={null}
{
  "error": {
    "code": "DUPLICATE",
    "message": "Payment with this externalId already exists",
    "existingResource": {
      "id": "ord_abc123",
      "externalId": "order-12345",
      "status": "COMPLETED"
    }
  }
}
```

**Common Causes:**

* Duplicate `externalId`
* Resource already created

**Resolution:**

* Use the existing resource
* Create resource with different ID
* Check if idempotency is working as expected

### Payment Errors

#### DECLINED

**Status:** 422\
**Meaning:** Payment declined by issuing bank

```json theme={null}
{
  "error": {
    "code": "DECLINED",
    "message": "Payment declined by issuing bank",
    "declineReason": "insufficient_funds"
  }
}
```

**Decline Reasons:**

| Reason               | Description         | Customer Message                                              |
| -------------------- | ------------------- | ------------------------------------------------------------- |
| `insufficient_funds` | Low balance         | "Payment couldn't be processed. Please try a different card." |
| `invalid_card`       | Invalid card number | "Unable to process this card. Please check your details."     |
| `expired_card`       | Card expired        | "This card has expired. Please use a different card."         |
| `card_declined`      | Generic decline     | "Payment couldn't be completed. Please try another method."   |
| `processing_error`   | Temporary error     | "We're having trouble processing. Please try again."          |

**Resolution:**

* Show customer-friendly error message
* Suggest trying different payment method
* Allow customer to retry
* Consider offering SPEI, PAYCASH, or CIE Cash Net as alternatives

#### INSUFFICIENT\_FUNDS

**Status:** 422\
**Meaning:** Customer has insufficient funds

```json theme={null}
{
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "Insufficient funds for this transaction"
  }
}
```

**Resolution:**

* Suggest trying different card
* Offer alternative payment methods
* Suggest lower amount if applicable

#### EXPIRED\_CARD

**Status:** 422\
**Meaning:** Card has expired

```json theme={null}
{
  "error": {
    "code": "EXPIRED_CARD",
    "message": "This card has expired"
  }
}
```

**Resolution:**

* Request updated card information
* Suggest using different card
* Offer to update saved card

#### INVALID\_CARD

**Status:** 422\
**Meaning:** Invalid card number

```json theme={null}
{
  "error": {
    "code": "INVALID_CARD",
    "message": "Invalid card number"
  }
}
```

**Resolution:**

* Ask customer to re-enter card details
* Validate card number client-side
* Check for typos

#### INVALID\_CVC

**Status:** 422\
**Meaning:** Invalid or incorrect CVC

```json theme={null}
{
  "error": {
    "code": "INVALID_CVC",
    "message": "Invalid security code"
  }
}
```

**Resolution:**

* Ask customer to re-enter CVC
* Show CVC location on card
* Verify correct CVC length (3-4 digits)

### 3D Secure Errors

#### AUTHENTICATION\_REQUIRED

**Status:** 422\
**Meaning:** 3D Secure authentication is required

```json theme={null}
{
  "paymentOrder": {
    "status": "PAYER_AUTHENTICATION_CHALLENGE_REQUIRED"
  },
  "payerAuthentication": {
    "stepUpUrl": "...",
    "jwt": "..."
  }
}
```

**Note:** This is not an error - it indicates 3DS is required.

**Resolution:**

* Display 3DS authentication challenge
* Follow 3DS implementation guide

<Card title="3D Secure Guide" icon="shield" href="/features/3d-secure">
  Learn how to handle 3DS authentication
</Card>

#### AUTHENTICATION\_FAILED

**Status:** 422\
**Meaning:** Customer failed 3D Secure verification

```json theme={null}
{
  "error": {
    "code": "AUTHENTICATION_FAILED",
    "message": "Customer failed to complete authentication"
  }
}
```

**Resolution:**

* Show friendly message: "We couldn't verify your identity"
* Allow customer to retry
* Offer alternative payment method

#### AUTHENTICATION\_TIMEOUT

**Status:** 422\
**Meaning:** 3DS authentication session expired

```json theme={null}
{
  "error": {
    "code": "AUTHENTICATION_TIMEOUT",
    "message": "Authentication session expired"
  }
}
```

**Resolution:**

* Start new payment request
* Inform customer of timeout
* Provide retry option

### Rate Limiting

#### RATE\_LIMIT\_EXCEEDED

**Status:** 429\
**Meaning:** Too many requests

```json theme={null}
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests",
    "retryAfter": 60
  }
}
```

**Resolution:**

* Wait for `retryAfter` seconds
* Implement exponential backoff
* Reduce request frequency
* Contact support for higher limits

### Refund Errors

#### INVALID\_OPERATION

**Status:** 400\
**Meaning:** The payment order cannot be refunded in its current state

```json theme={null}
{
  "error": {
    "code": "INVALID_OPERATION",
    "message": "Payment order is not in a refundable state"
  }
}
```

**Common Causes:**

* Payment not yet authorized or captured
* Payment already fully refunded
* Missing `amount` in the request body (`amount` is required, in minor units)
* Refund amount exceeds the remaining refundable amount
* Split-tender order refund without a `paymentId`

**Resolution:**

* Check the payment order status and `refundedAmount`
* Pass a valid `amount` no greater than the remaining refundable amount
* For split-tender orders, include the `paymentId` to refund

## Server Errors (500-599)

### INTERNAL\_ERROR

**Status:** 500\
**Meaning:** Internal server error

```json theme={null}
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An internal error occurred"
  }
}
```

**Resolution:**

* Retry request with exponential backoff
* Contact support if persistent
* Check API status page

### SERVICE\_UNAVAILABLE

**Status:** 503\
**Meaning:** Temporary service disruption

```json theme={null}
{
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "message": "Service temporarily unavailable",
    "retryAfter": 60
  }
}
```

**Resolution:**

* Wait and retry after specified time
* Implement exponential backoff
* Check status page for incidents

## Error Handling Best Practices

### 1. Show User-Friendly Messages

```javascript theme={null}
function getCustomerMessage(error) {
  const messages = {
    'DECLINED': 'Payment couldn\'t be processed. Please try a different card.',
    'EXPIRED_CARD': 'This card has expired. Please use a different card.',
    'INSUFFICIENT_FUNDS': 'Payment couldn\'t be completed. Please try another method.'
  };
  
  return messages[error.code] || 
         'Unable to process payment. Please try again.';
}
```

### 2. Implement Retry Logic

```javascript theme={null}
async function createPaymentWithRetry(data, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await createPayment(data);
    } catch (error) {
      // Only retry server errors
      if (error.status >= 500 && attempt < maxRetries - 1) {
        const delay = Math.pow(2, attempt) * 1000;
        await sleep(delay);
        continue;
      }
      throw error;
    }
  }
}
```

### 3. Log Errors Appropriately

```javascript theme={null}
function logError(error, context) {
  logger.error('Payment error', {
    code: error.code,
    message: error.message,
    status: error.status,
    context: {
      externalId: context.externalId,
      amount: context.amount
    }
    // Never log: card numbers, CVCs, API keys
  });
}
```

### 4. Handle Specific Error Types

```javascript theme={null}
try {
  const payment = await createPayment(data);
} catch (error) {
  switch (error.code) {
    case 'DECLINED':
      return showDeclineMessage();
    case 'AUTHENTICATION_REQUIRED':
      return show3DSChallenge(error.payerAuthentication);
    case 'RATE_LIMIT_EXCEEDED':
      return retryAfter(error.retryAfter);
    case 'INTERNAL_ERROR':
      return retryWithBackoff();
    default:
      return showGenericError();
  }
}
```

## Complete Error Reference

| Code                      | Status | Category   | Action                       |
| ------------------------- | ------ | ---------- | ---------------------------- |
| `VALIDATION_ERROR`        | 400    | Client     | Fix parameters               |
| `UNAUTHORIZED`            | 401    | Auth       | Check API key                |
| `NOT_FOUND`               | 404    | Resource   | Verify ID                    |
| `DUPLICATE`               | 409    | Resource   | Use existing                 |
| `DECLINED`                | 422    | Payment    | Try different card           |
| `INSUFFICIENT_FUNDS`      | 422    | Payment    | Try different card           |
| `EXPIRED_CARD`            | 422    | Payment    | Update card                  |
| `INVALID_CARD`            | 422    | Payment    | Re-enter card                |
| `INVALID_CVC`             | 422    | Payment    | Re-enter CVC                 |
| `AUTHENTICATION_REQUIRED` | 422    | 3DS        | Show challenge               |
| `AUTHENTICATION_FAILED`   | 422    | 3DS        | Allow retry                  |
| `AUTHENTICATION_TIMEOUT`  | 422    | 3DS        | Start new payment            |
| `RATE_LIMIT_EXCEEDED`     | 429    | Rate Limit | Wait and retry               |
| `INVALID_OPERATION`       | 400    | Refund     | Check order state and amount |
| `INTERNAL_ERROR`          | 500    | Server     | Retry with backoff           |
| `SERVICE_UNAVAILABLE`     | 503    | Server     | Retry after delay            |

## Need Help?

<CardGroup cols={2}>
  <Card title="Error Handling Guide" icon="triangle-exclamation" href="/guides/error-handling">
    Complete error handling patterns
  </Card>

  <Card title="Testing Guide" icon="flask" href="/guides/testing">
    Test error scenarios
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    Complete API documentation
  </Card>

  <Card title="Contact Support" icon="headset" href="mailto:support@cheqpay.mx">
    Get help with errors
  </Card>
</CardGroup>
