Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Error Handling

Error Handling

All Cashela API endpoints return errors in a consistent, machine-readable JSON format. This guide explains the error structure, common error codes, and best practices for handling failures in your integration.


Error Response Structure

All error responses follow this consistent format:

{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description",
"details": {},
"doc_url": "https://docs.cashela.com/errors#error-code"
},
"request_id": "req_01HJ3KBCD8E9F0G1H2I3J4K5L6"
}

Fields

FieldTypeDescription
successbooleanAlways false for error responses
error.codestringMachine-readable error code for programmatic handling
error.messagestringHuman-readable description, safe to display to users for certain error types
error.detailsobjectAdditional context, field-specific validation errors, or parameters related to the error
error.doc_urlstringLink to documentation explaining this error type
request_idstringUnique identifier for this request. Include when contacting support

HTTP Status Codes

Cashela uses conventional HTTP status codes to indicate success or failure:

Success Codes (2xx)

CodeStatusMeaning
200OKRequest succeeded. Response body contains the requested data
201CreatedResource successfully created (e.g., transaction, quotation)
202AcceptedRequest accepted for processing but not yet completed
204No ContentRequest succeeded with no response body to return

Client Error Codes (4xx)

CodeStatusMeaningAction
400Bad RequestMalformed request syntax or invalid JSONFix request format
401UnauthorizedInvalid or missing authentication credentialsVerify API credentials
403ForbiddenValid credentials but insufficient permissionsCheck IP allowlist or account permissions
404Not FoundRequested resource doesn’t existVerify endpoint URL and resource ID
405Method Not AllowedHTTP method not supported for this endpointUse correct HTTP method (GET, POST, etc.)
409ConflictRequest conflicts with current state (e.g., duplicate idempotency key)Review conflict details and adjust request
422Unprocessable EntityRequest syntax valid but business logic validation failedFix validation errors in request data
429Too Many RequestsRate limit exceededImplement exponential backoff and retry

Server Error Codes (5xx)

CodeStatusMeaningAction
500Internal Server ErrorUnexpected server errorRetry with exponential backoff
502Bad GatewayUpstream service unavailableRetry after brief delay
503Service UnavailableTemporary service interruptionCheck status page, retry with backoff
504Gateway TimeoutRequest timeoutRetry with same idempotency key

Important: 5xx errors are rare and typically transient. Always implement retry logic with exponential backoff for these errors.


Error Types

Cashela categorizes errors into distinct types for easier handling:

Authentication Errors

Error CodeDescriptionResolution
UNAUTHORIZEDMissing or invalid API credentialsVerify your Business Key and Secret are correct
INVALID_API_KEYAPI key format is invalidCheck for typos or encoding issues
EXPIRED_CREDENTIALSAPI credentials have been revokedGenerate new credentials in your dashboard
IP_NOT_ALLOWEDRequest from non-allowlisted IPAdd your server IP to the allowlist

Validation Errors

Error CodeDescriptionResolution
INVALID_INPUTMalformed request body or invalid JSONCheck JSON syntax and encoding
MISSING_REQUIRED_FIELDRequired parameter not providedInclude all required fields
INVALID_FIELD_FORMATField value doesn’t match expected formatCheck field type and format requirements
INVALID_DOCUMENTDocument number failed validationVerify document matches country requirements
INVALID_EMAILEmail format is invalidProvide valid email address
INVALID_PHONEPhone number format is invalidUse E.164 format (e.g., +1234567890)
AMOUNT_TOO_LOWAmount below minimum thresholdCheck minimum amount for payment method
AMOUNT_TOO_HIGHAmount exceeds maximum limitSplit into multiple transactions or contact support

Transaction Errors

Error CodeDescriptionResolution
TRANSACTION_NOT_FOUNDTransaction ID doesn’t existVerify transaction ID is correct
TRANSACTION_EXPIREDTransaction or quotation has expiredCreate new transaction
TRANSACTION_CANCELLEDTransaction was cancelledCreate new transaction if needed
DUPLICATE_TRANSACTIONTransaction with same external_identifier existsUse unique identifier per transaction
INSUFFICIENT_FUNDSAccount balance too lowAdd funds to your business wallet

Idempotency Errors

Error CodeDescriptionResolution
IDEMPOTENCY_CONFLICTSame key used with different request bodyUse new idempotency key or send identical request
IDEMPOTENCY_KEY_REQUIREDPOST request missing Idempotency-Key headerInclude UUID v4 in header
INVALID_IDEMPOTENCY_KEYKey format is invalidUse valid UUID v4 format

Payment Method Errors

Error CodeDescriptionResolution
PAYMENT_METHOD_NOT_FOUNDInvalid payment method codeUse valid code from Get Payment Methods
PAYMENT_METHOD_UNAVAILABLEMethod temporarily unavailableTry alternative method or retry later
UNSUPPORTED_COUNTRYCountry not supported for methodChoose different country or method
UNSUPPORTED_CURRENCYCurrency not supportedCheck supported currencies

Rate Limiting Errors

Error CodeDescriptionResolution
RATE_LIMITEDToo many requests in time windowWait and retry with exponential backoff
QUOTA_EXCEEDEDMonthly transaction quota reachedContact support to increase limits

Validation Error Details

When a validation error occurs, the details object contains field-specific error messages:

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"email": "Invalid email format. Expected: user@domain.com",
"amount": "Amount must be between 10.00 and 50000.00 MXN",
"document_number": "Invalid format for IFE. Expected pattern: XXXX000000XXXXXX00",
"phone": "Phone number must be in E.164 format: +521234567890"
}
},
"request_id": "req_01HJ3KBCD8E9F0G1H2I3J4K5L6"
}

Processing validation errors:

function handleValidationErrors(errorResponse) {
const { details } = errorResponse.error;
// Map API field names to form field names
const fieldMapping = {
'email': 'customerEmail',
'document_number': 'documentId',
'amount': 'paymentAmount'
};
// Display errors to user
Object.entries(details).forEach(([field, message]) => {
const formField = fieldMapping[field] || field;
displayFieldError(formField, message);
});
}

Error Handling Best Practices

1. Always Check the Success Field

async function makeApiRequest(endpoint, data) {
const response = await fetch(endpoint, {
method: 'POST',
headers: getAuthHeaders(),
body: JSON.stringify(data)
});
const result = await response.json();
// Always check success field, not just HTTP status
if (!result.success) {
throw new CashelaApiError(result.error, result.request_id);
}
return result.data;
}

2. Handle Errors by Code, Not Message

Messages may change; codes are stable:

function handleApiError(error) {
switch (error.code) {
case 'UNAUTHORIZED':
case 'INVALID_API_KEY':
// Credential issues - alert operations team
notifyOperations('API credentials invalid');
break;
case 'VALIDATION_ERROR':
// User input issue - show errors to user
displayValidationErrors(error.details);
break;
case 'RATE_LIMITED':
// Temporary - retry with backoff
return scheduleRetry(error);
case 'INSUFFICIENT_FUNDS':
// Balance issue - alert finance team
notifyFinance('Low balance alert');
break;
default:
// Unknown error - log and alert
logError(error);
showGenericError();
}
}

3. Implement Exponential Backoff for Retries

import time
import random
def retry_with_backoff(func, max_retries=5, base_delay=1):
"""Retry function with exponential backoff and jitter."""
for attempt in range(max_retries):
try:
return func()
except RetryableError as e:
if attempt == max_retries - 1:
raise
# Calculate delay with exponential backoff + jitter
delay = base_delay * (2 ** attempt)
jitter = random.uniform(0, delay * 0.1)
total_delay = delay + jitter
print(f"Attempt {attempt + 1} failed. Retrying in {total_delay:.2f}s...")
time.sleep(total_delay)
raise MaxRetriesExceeded()
# Usage
def create_transaction():
response = api.create_deposit(transaction_data)
if response.error and response.error.code in ['RATE_LIMITED', 'INTERNAL_ERROR', 'SERVICE_UNAVAILABLE']:
raise RetryableError(response.error)
return response
result = retry_with_backoff(create_transaction)

4. Log Request IDs for Support

class CashelaApiError extends Error {
constructor(error, requestId) {
super(error.message);
this.code = error.code;
this.details = error.details;
this.requestId = requestId;
// Log for debugging and support
console.error(`Cashela API Error [${requestId}]: ${error.code} - ${error.message}`);
}
}
// When contacting support, include the request_id
function reportErrorToSupport(error) {
return {
message: `API error occurred`,
requestId: error.requestId, // Always include this
errorCode: error.code,
timestamp: new Date().toISOString()
};
}

5. Display User-Friendly Messages

const USER_MESSAGES = {
'VALIDATION_ERROR': 'Please check your information and try again.',
'PAYMENT_METHOD_UNAVAILABLE': 'This payment method is temporarily unavailable. Please try another option.',
'INSUFFICIENT_FUNDS': 'We are unable to process this transaction at the moment. Please try again later.',
'RATE_LIMITED': 'Too many attempts. Please wait a moment and try again.',
'INTERNAL_ERROR': 'Something went wrong on our end. Please try again in a few minutes.'
};
function getUserMessage(errorCode) {
return USER_MESSAGES[errorCode] || 'An unexpected error occurred. Please try again.';
}

Retryable vs Non-Retryable Errors

Retryable Errors (Safe to Retry)

These errors are transient and may succeed on retry:

Error CodeRetry Strategy
RATE_LIMITEDWait for Retry-After header or use exponential backoff
INTERNAL_ERRORRetry up to 3 times with exponential backoff
SERVICE_UNAVAILABLECheck status page, retry with backoff
BAD_GATEWAYRetry after 5-10 seconds
GATEWAY_TIMEOUTRetry immediately with same idempotency key

Non-Retryable Errors (Do Not Retry)

These errors require fixing the request or account:

Error CodeAction Required
UNAUTHORIZEDFix credentials
VALIDATION_ERRORFix request data
INSUFFICIENT_FUNDSAdd funds to account
PAYMENT_METHOD_NOT_FOUNDUse valid payment method
IDEMPOTENCY_CONFLICTUse new idempotency key