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

# Errors

> Error codes, response formats, and troubleshooting

# Error Handling

The ChainPal API uses conventional HTTP status codes to indicate the success or failure of requests. All error responses follow a consistent JSON structure.

## HTTP Status Codes

| Code  | Status                | Description                                                |
| :---- | :-------------------- | :--------------------------------------------------------- |
| `200` | OK                    | Request succeeded                                          |
| `400` | Bad Request           | Invalid request parameters or validation error             |
| `401` | Unauthorized          | Missing or invalid API key                                 |
| `403` | Forbidden             | Valid API key but access denied (e.g., IP not whitelisted) |
| `404` | Not Found             | Requested resource doesn't exist                           |
| `429` | Too Many Requests     | Rate limit exceeded                                        |
| `500` | Internal Server Error | Server-side error                                          |

## Error Response Format

All error responses use this structure:

```json theme={null}
{
  "success": false,
  "message": "Descriptive error message",
  "data": null
}
```

| Field     | Type      | Description                      |
| :-------- | :-------- | :------------------------------- |
| `success` | `boolean` | Always `false` for errors        |
| `message` | `string`  | Human-readable error description |
| `data`    | `null`    | Always `null` for errors         |

## Common Errors

### Authentication Errors (401)

**Missing API Key**

```json theme={null}
{
  "success": false,
  "message": "api key not provided, use the format 'Bearer <api key>'",
  "data": null
}
```

**Invalid API Key**

```json theme={null}
{
  "success": false,
  "message": "api key is invalid, use the format 'Bearer <api key>'",
  "data": null
}
```

**Wrong Key Type**

```json theme={null}
{
  "success": false,
  "message": "endpoint requires a secret key",
  "data": null
}
```

### Authorization Errors (403)

**IP Not Whitelisted**

```json theme={null}
{
  "success": false,
  "message": "access denied",
  "data": null
}
```

### Validation Errors (400)

**Missing Required Field**

```json theme={null}
{
  "success": false,
  "message": "Key: 'InitializePaymentDTO.Amount' Error:Field validation for 'Amount' failed on the 'required' tag",
  "data": null
}
```

**Invalid Email**

```json theme={null}
{
  "success": false,
  "message": "Key: 'InitializePaymentDTO.CustomerEmail' Error:Field validation for 'CustomerEmail' failed on the 'email' tag",
  "data": null
}
```

**Amount Below Minimum**

```json theme={null}
{
  "success": false,
  "message": "amount must be at least 1000.00 NGN",
  "data": null
}
```

**Amount Above Maximum**

```json theme={null}
{
  "success": false,
  "message": "amount cannot exceed 1000000.00 NGN",
  "data": null
}
```

**Duplicate Reference**

```json theme={null}
{
  "success": false,
  "message": "the reference you provided is already in use, please try again with a different reference",
  "data": null
}
```

**Invalid Reference Format**

```json theme={null}
{
  "success": false,
  "message": "Key: 'InitializePaymentDTO.Reference' Error:Field validation for 'Reference' failed on the 'alphanum' tag",
  "data": null
}
```

**Unsupported Token/Network**

```json theme={null}
{
  "success": false,
  "message": "pair not supported",
  "data": null
}
```

**Webhook Secret Required**

```json theme={null}
{
  "success": false,
  "message": "You must generate a webhook signing secret before configuring webhook URLs",
  "data": null
}
```

### Not Found Errors (404)

**Payment Not Found**

```json theme={null}
{
  "success": false,
  "message": "payment not found",
  "data": null
}
```

**Invalid Payment ID Format**

```json theme={null}
{
  "success": false,
  "message": "invalid payment ID format",
  "data": null
}
```

### Rate Limit Errors (429)

**Too Many Requests**

```json theme={null}
{
  "success": false,
  "message": "too many requests",
  "data": null
}
```

### Server Errors (500)

**Generic Server Error**

```json theme={null}
{
  "success": false,
  "message": "something went wrong, please try again",
  "data": null
}
```

## Handling Errors

### Best Practices

1. **Check the `success` field first**

   ```javascript theme={null}
   const response = await fetch('/api/v1/payments', { ... });
   const data = await response.json();

   if (!data.success) {
     console.error('API Error:', data.message);
     // Handle error
     return;
   }

   // Process successful response
   ```

2. **Handle specific status codes**

   ```javascript theme={null}
   if (response.status === 401) {
     // Re-authenticate or check API key
   } else if (response.status === 429) {
     // Wait and retry with exponential backoff
   } else if (response.status >= 500) {
     // Server error, retry later
   }
   ```

3. **Implement retry logic for transient errors**

   ```javascript theme={null}
   async function fetchWithRetry(url, options, maxRetries = 3) {
     for (let i = 0; i < maxRetries; i++) {
       const response = await fetch(url, options);

       if (response.status === 429 || response.status >= 500) {
         const delay = Math.pow(2, i) * 1000; // Exponential backoff
         await new Promise((resolve) => setTimeout(resolve, delay));
         continue;
       }

       return response;
     }
     throw new Error("Max retries exceeded");
   }
   ```

4. **Log errors for debugging**
   ```javascript theme={null}
   if (!data.success) {
     console.error({
       endpoint: "/api/v1/payments",
       status: response.status,
       message: data.message,
       requestId: response.headers.get("x-request-id"),
       timestamp: new Date().toISOString(),
     });
   }
   ```

## Validation Rules

### Amount Field

* Must be a positive number
* Must meet minimum and maximum limits for the currency
* See [Types & Enums](./types#transaction-limits) for limits

### Reference Field

* Optional (auto-generated if not provided)
* 12-16 alphanumeric characters
* Must be unique per merchant

### Email Field

* Must be a valid email format

### URL Fields (callbackURL, failureURL)

* Must be valid URLs
* Must use HTTPS protocol

### Token/Network

* Must be a supported combination for your country
* See [Types & Enums](./types#tokennetwork-availability-by-country)
