Skip to main content

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:
{
  "statusCode": 400,
  "message": "Human-readable error message",
  "error": "Error Type"
}

HTTP Status Codes

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

Authentication Errors

Missing API Key

HTTP Status401
MessageMissing X-API-Key header
CauseNo X-API-Key header was provided
SolutionInclude the X-API-Key header in your request
{
  "statusCode": 401,
  "message": "Missing X-API-Key header",
  "error": "Unauthorized"
}

Invalid API Key

HTTP Status401
MessageInvalid API key
CauseThe provided API key is incorrect or doesn’t exist
SolutionVerify you’re using the correct API key from your dashboard
{
  "statusCode": 401,
  "message": "Invalid API key",
  "error": "Unauthorized"
}

Merchant Deactivated

HTTP Status403
MessageMerchant account is deactivated
CauseYour merchant account has been deactivated
SolutionContact support to reactivate your account
{
  "statusCode": 403,
  "message": "Merchant account is deactivated",
  "error": "Forbidden"
}

Invalid Signature

HTTP Status401
MessageInvalid request signature
CauseThe HMAC signature doesn’t match the expected value
SolutionVerify your signature calculation (see Authentication docs)
{
  "statusCode": 401,
  "message": "Invalid request signature",
  "error": "Unauthorized"
}

Expired Timestamp

HTTP Status401
MessageRequest timestamp expired (signature older than 5 minutes)
CauseThe X-Timestamp header is more than 5 minutes old
SolutionUse the current timestamp when signing requests
{
  "statusCode": 401,
  "message": "Request timestamp expired (signature older than 5 minutes)",
  "error": "Unauthorized"
}

Authorization Errors

Method Not Allowed

HTTP Status403
MessageAccess to method '' is not allowed
CauseYour merchant account doesn’t have access to this verification method
SolutionContact your account manager to enable the method
{
  "statusCode": 403,
  "message": "Access to method 'full-check' is not allowed",
  "error": "Forbidden"
}

IP Not Whitelisted

HTTP Status403
MessageRequest from non-whitelisted IP
CauseYour request came from an IP not in your whitelist
SolutionAdd the IP to your whitelist in the dashboard
{
  "statusCode": 403,
  "message": "Request from non-whitelisted IP",
  "error": "Forbidden"
}

Payment Errors

Insufficient Balance

HTTP Status402
MessageInsufficient wallet balance
CauseYour merchant account doesn’t have enough balance for this request
SolutionTop up your account balance in the dashboard
{
  "statusCode": 402,
  "message": "Insufficient wallet balance",
  "error": "Payment Required"
}

Validation Errors

Invalid Mobile Number

HTTP Status400
MessageMobile must be in format +91XXXXXXXXXX (Indian number)
CauseThe mobile number doesn’t match the required format
SolutionUse Indian mobile format: +91 followed by 10 digits
{
  "statusCode": 400,
  "message": ["Mobile must be in format +91XXXXXXXXXX (Indian number)"],
  "error": "Bad Request"
}

Invalid VPA Format

HTTP Status400
MessageEach VPA must be in format username@bank
CauseOne or more VPAs don’t match the required format
SolutionUse format username@bank (e.g., user@upi)
{
  "statusCode": 400,
  "message": ["Each VPA must be in format username@bank (e.g., user@upi)"],
  "error": "Bad Request"
}

VPA Array Size

HTTP Status400
MessageAt least one VPA is required / Maximum 100 VPAs allowed per request
CauseThe VPA array is empty or exceeds the maximum size
SolutionProvide between 1 and 100 VPAs per request
{
  "statusCode": 400,
  "message": ["Maximum 100 VPAs allowed per request"],
  "error": "Bad Request"
}

Resource Errors

Request Not Found

HTTP Status404
MessageRequest not found
CauseThe request ID doesn’t exist or doesn’t belong to your merchant
SolutionVerify the request ID is correct
{
  "statusCode": 404,
  "message": "Request not found",
  "error": "Not Found"
}

Rate Limit Errors

Rate Limit Exceeded

HTTP Status429
MessageToo Many Requests
CauseYou’ve exceeded the rate limit for this endpoint
SolutionImplement exponential backoff and retry
{
  "statusCode": 429,
  "message": "Too Many Requests",
  "error": "Too Many Requests"
}
Rate Limits:
Endpoint TypeLimit
Verification endpoints100 requests/minute
Status endpoints300 requests/minute
Bulk endpoints10 requests/minute

Request Status Error Classes

When a verification request fails, the error field contains details:
Error ClassDescriptionRecoverable
VALIDATION_ERRORInput validation failedFix input data
AUTH_ERRORAuthentication/authorization issueCheck credentials
PROVIDER_TEMPORARYTemporary provider issueRetry later
PROVIDER_BUSINESS_ERRORProvider rejected the requestCheck input data

Example Failed Request

{
  "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 Status500
MessageInternal server error
CauseAn unexpected error occurred on our servers
SolutionRetry the request. If the issue persists, contact support.
{
  "statusCode": 500,
  "message": "Internal server error",
  "error": "Internal Server Error"
}

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) {
  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;
  }
}