Skip to main content

Error Response Format

All errors follow a consistent structure:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": [
      {
        "field": "amount",
        "message": "Amount must be positive"
      }
    ]
  }
}

HTTP Status Codes

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

Client Errors (400-499)

Validation Errors

VALIDATION_ERROR

Status: 400
Meaning: Invalid request parameters
{
  "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
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}
Common Causes:
  • Missing Authorization header
  • Invalid API key
  • Wrong environment (sandbox key in production)
  • Incorrect header format
Resolution:
  • Verify API key is correct
  • Check Authorization header: Bearer YOUR_API_KEY
  • Ensure using correct environment credentials

Resource Errors

NOT_FOUND

Status: 404
Meaning: Resource not found
{
  "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
{
  "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
{
  "error": {
    "code": "DECLINED",
    "message": "Payment declined by issuing bank",
    "declineReason": "insufficient_funds"
  }
}
Decline Reasons:
ReasonDescriptionCustomer Message
insufficient_fundsLow balance”Payment couldn’t be processed. Please try a different card.”
invalid_cardInvalid card number”Unable to process this card. Please check your details.”
expired_cardCard expired”This card has expired. Please use a different card.”
card_declinedGeneric decline”Payment couldn’t be completed. Please try another method.”
processing_errorTemporary 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 as alternative

INSUFFICIENT_FUNDS

Status: 422
Meaning: Customer has insufficient funds
{
  "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
{
  "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
{
  "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
{
  "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
{
  "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

3D Secure Guide

Learn how to handle 3DS authentication

AUTHENTICATION_FAILED

Status: 422
Meaning: Customer failed 3D Secure verification
{
  "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
{
  "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
{
  "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

NOT_REFUNDABLE

Status: 422
Meaning: Payment cannot be refunded
{
  "error": {
    "code": "NOT_REFUNDABLE",
    "message": "Payment cannot be refunded",
    "details": "Only completed payments can be refunded"
  }
}
Common Causes:
  • Payment not completed
  • Payment already fully refunded
  • Payment too old
Resolution:
  • Check payment status
  • Verify refund eligibility
  • Contact support for special cases

INVALID_REFUND_AMOUNT

Status: 422
Meaning: Refund amount exceeds available balance
{
  "error": {
    "code": "INVALID_AMOUNT",
    "message": "Refund amount exceeds available balance",
    "details": {
      "originalAmount": 10000,
      "alreadyRefunded": 8000,
      "maxRefundable": 2000,
      "requested": 5000
    }
  }
}
Resolution:
  • Check remaining refundable amount
  • Issue partial refund for available amount
  • Verify refund history

Server Errors (500-599)

INTERNAL_ERROR

Status: 500
Meaning: Internal server error
{
  "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
{
  "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

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

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

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

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

CodeStatusCategoryAction
VALIDATION_ERROR400ClientFix parameters
UNAUTHORIZED401AuthCheck API key
NOT_FOUND404ResourceVerify ID
DUPLICATE409ResourceUse existing
DECLINED422PaymentTry different card
INSUFFICIENT_FUNDS422PaymentTry different card
EXPIRED_CARD422PaymentUpdate card
INVALID_CARD422PaymentRe-enter card
INVALID_CVC422PaymentRe-enter CVC
AUTHENTICATION_REQUIRED4223DSShow challenge
AUTHENTICATION_FAILED4223DSAllow retry
AUTHENTICATION_TIMEOUT4223DSStart new payment
RATE_LIMIT_EXCEEDED429Rate LimitWait and retry
NOT_REFUNDABLE422RefundCheck status
INVALID_AMOUNT422RefundCheck amount
INTERNAL_ERROR500ServerRetry with backoff
SERVICE_UNAVAILABLE503ServerRetry after delay

Need Help?