> ## Documentation Index
> Fetch the complete documentation index at: https://docs.txncheck.com/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 TxnCheck 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": "Error Type"
}
```

## HTTP Status Codes

| Status Code | Meaning                                   |
| ----------- | ----------------------------------------- |
| `200`       | Success                                   |
| `202`       | Accepted - Request queued                 |
| `400`       | Bad Request - Invalid parameters          |
| `401`       | Unauthorized - Invalid or missing API key |
| `402`       | Payment Required - Insufficient balance   |
| `403`       | Forbidden - Access denied                 |
| `404`       | Not Found - Resource doesn't exist        |
| `429`       | Too Many Requests - Rate limit exceeded   |
| `500`       | Internal Server Error                     |

## Authentication Errors

### Missing API Key

|                 |                                                |
| --------------- | ---------------------------------------------- |
| **HTTP Status** | 401                                            |
| **Message**     | Missing X-API-Key header                       |
| **Cause**       | No `X-API-Key` header was provided             |
| **Solution**    | Include the `X-API-Key` header in your request |

```json theme={null}
{
  "statusCode": 401,
  "message": "Missing X-API-Key header",
  "error": "Unauthorized"
}
```

### Invalid API Key

|                 |                                                             |
| --------------- | ----------------------------------------------------------- |
| **HTTP Status** | 401                                                         |
| **Message**     | Invalid API key                                             |
| **Cause**       | The provided API key is incorrect or doesn't exist          |
| **Solution**    | Verify you're using the correct API key from your dashboard |

```json theme={null}
{
  "statusCode": 401,
  "message": "Invalid API key",
  "error": "Unauthorized"
}
```

### Merchant Deactivated

|                 |                                            |
| --------------- | ------------------------------------------ |
| **HTTP Status** | 403                                        |
| **Message**     | Merchant account is deactivated            |
| **Cause**       | Your merchant account has been deactivated |
| **Solution**    | Contact support to reactivate your account |

```json theme={null}
{
  "statusCode": 403,
  "message": "Merchant account is deactivated",
  "error": "Forbidden"
}
```

### Invalid Signature

|                 |                                                             |
| --------------- | ----------------------------------------------------------- |
| **HTTP Status** | 401                                                         |
| **Message**     | Invalid request signature                                   |
| **Cause**       | The HMAC signature doesn't match the expected value         |
| **Solution**    | Verify your signature calculation (see Authentication docs) |

```json theme={null}
{
  "statusCode": 401,
  "message": "Invalid request signature",
  "error": "Unauthorized"
}
```

### Expired Timestamp

|                 |                                                            |
| --------------- | ---------------------------------------------------------- |
| **HTTP Status** | 401                                                        |
| **Message**     | Request timestamp expired (signature older than 5 minutes) |
| **Cause**       | The `X-Timestamp` header is more than 5 minutes old        |
| **Solution**    | Use the current timestamp when signing requests            |

```json theme={null}
{
  "statusCode": 401,
  "message": "Request timestamp expired (signature older than 5 minutes)",
  "error": "Unauthorized"
}
```

## Authorization Errors

### Method Not Allowed

|                 |                                                                       |
| --------------- | --------------------------------------------------------------------- |
| **HTTP Status** | 403                                                                   |
| **Message**     | Access to method '{method}' is not allowed                            |
| **Cause**       | Your merchant account doesn't have access to this verification method |
| **Solution**    | Contact your account manager to enable the method                     |

```json theme={null}
{
  "statusCode": 403,
  "message": "Access to method 'full-check' is not allowed",
  "error": "Forbidden"
}
```

### IP Not Whitelisted

|                 |                                                    |
| --------------- | -------------------------------------------------- |
| **HTTP Status** | 403                                                |
| **Message**     | Request from non-whitelisted IP                    |
| **Cause**       | Your request came from an IP not in your whitelist |
| **Solution**    | Add the IP to your whitelist in the dashboard      |

```json theme={null}
{
  "statusCode": 403,
  "message": "Request from non-whitelisted IP",
  "error": "Forbidden"
}
```

## Payment Errors

### Insufficient Balance

|                 |                                                                    |
| --------------- | ------------------------------------------------------------------ |
| **HTTP Status** | 402                                                                |
| **Message**     | Insufficient wallet balance                                        |
| **Cause**       | Your merchant account doesn't have enough balance for this request |
| **Solution**    | Top up your account balance in the dashboard                       |

```json theme={null}
{
  "statusCode": 402,
  "message": "Insufficient wallet balance",
  "error": "Payment Required"
}
```

## Validation Errors

### Invalid Mobile Number

|                 |                                                        |
| --------------- | ------------------------------------------------------ |
| **HTTP Status** | 400                                                    |
| **Message**     | Mobile must be in format +91XXXXXXXXXX (Indian number) |
| **Cause**       | The mobile number doesn't match the required format    |
| **Solution**    | Use Indian mobile format: `+91` followed by 10 digits  |

```json theme={null}
{
  "statusCode": 400,
  "message": ["Mobile must be in format +91XXXXXXXXXX (Indian number)"],
  "error": "Bad Request"
}
```

### Invalid VPA Format

|                 |                                                  |
| --------------- | ------------------------------------------------ |
| **HTTP Status** | 400                                              |
| **Message**     | Each VPA must be in format username\@bank        |
| **Cause**       | One or more VPAs don't match the required format |
| **Solution**    | Use format `username@bank` (e.g., `user@upi`)    |

```json theme={null}
{
  "statusCode": 400,
  "message": ["Each VPA must be in format username@bank (e.g., user@upi)"],
  "error": "Bad Request"
}
```

### VPA Array Size

|                 |                                                                     |
| --------------- | ------------------------------------------------------------------- |
| **HTTP Status** | 400                                                                 |
| **Message**     | At least one VPA is required / Maximum 100 VPAs allowed per request |
| **Cause**       | The VPA array is empty or exceeds the maximum size                  |
| **Solution**    | Provide between 1 and 100 VPAs per request                          |

```json theme={null}
{
  "statusCode": 400,
  "message": ["Maximum 100 VPAs allowed per request"],
  "error": "Bad Request"
}
```

## Resource Errors

### Request Not Found

|                 |                                                                 |
| --------------- | --------------------------------------------------------------- |
| **HTTP Status** | 404                                                             |
| **Message**     | Request not found                                               |
| **Cause**       | The request ID doesn't exist or doesn't belong to your merchant |
| **Solution**    | Verify the request ID is correct                                |

```json theme={null}
{
  "statusCode": 404,
  "message": "Request not found",
  "error": "Not Found"
}
```

## 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 and retry          |

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

**Rate Limits:**

| Endpoint Type          | Limit               |
| ---------------------- | ------------------- |
| Verification endpoints | 100 requests/minute |
| Status endpoints       | 300 requests/minute |
| Bulk endpoints         | 10 requests/minute  |

## Request Status Error Classes

When a verification request fails, the `error` field contains details:

| Error Class               | Description                        | Recoverable       |
| ------------------------- | ---------------------------------- | ----------------- |
| `VALIDATION_ERROR`        | Input validation failed            | Fix input data    |
| `AUTH_ERROR`              | Authentication/authorization issue | Check credentials |
| `PROVIDER_TEMPORARY`      | Temporary provider issue           | Retry later       |
| `PROVIDER_BUSINESS_ERROR` | Provider rejected the request      | Check input data  |

### Example Failed Request

```json theme={null}
{
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "method": "upi-by-mobile",
  "status": "FAILED",
  "error": {
    "class": "PROVIDER_BUSINESS_ERROR",
    "message": "Mobile number not found in UPI system"
  },
  "webhookStatus": "SENT",
  "createdAt": "2025-01-11T10:30:00.000Z",
  "completedAt": "2025-01-11T10:30:05.000Z"
}
```

## Server Errors

### Internal Server 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. |

```json theme={null}
{
  "statusCode": 500,
  "message": "Internal server error",
  "error": "Internal Server Error"
}
```

## 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) {
  try {
    const response = await fetch(endpoint, options);
    
    if (!response.ok) {
      const error = await response.json();
      
      switch (response.status) {
        case 401:
          // Re-authenticate or check API key
          throw new AuthenticationError(error.message);
        case 402:
          // Insufficient balance - alert admin
          throw new PaymentError(error.message);
        case 403:
          // Method not allowed - check permissions
          throw new AuthorizationError(error.message);
        case 429:
          // Rate limited - wait and retry
          const retryAfter = response.headers.get('Retry-After') || 60;
          await sleep(retryAfter * 1000);
          return makeApiRequest(endpoint, options);
        case 400:
          // Validation error - show to user
          throw new ValidationError(error.message);
        default:
          throw new ApiError(error.message, response.status);
      }
    }
    
    return response.json();
  } catch (error) {
    if (error.name === 'NetworkError') {
      // Network error - retry with backoff
      await sleep(1000);
      return makeApiRequest(endpoint, options);
    }
    throw error;
  }
}
```
