Error Handling
Effective error handling is crucial for building robust integrations with the Localpayment API. Understanding the different error types and their corresponding codes will help you diagnose issues promptly and implement appropriate solutions.
We provide comprehensive error handling through standardized HTTP status codes and detailed error responses. This guide shows you how you can handle errors effectively so you can build a more resilient and user-friendly integration.
Overview
Proper error handling is crucial for creating reliable payment integrations. Localpayment uses a consistent error structure across all API endpoints to help you quickly identify and resolve issues.
Consistent error codes across all API endpoints and payment methods
Human-readable descriptions with specific error details
Proven strategies for handling errors in production environments
HTTP Response Codes
Localpayment utilizes standard HTTP status codes to indicate the success or failure of API requests:
| HTTP Code | Status | Description |
|---|---|---|
| 200 | OK | The request was successful and the response contains the requested data. |
| 201 | Created | The resource was successfully created (e.g., new payment initiated). |
| 400 | Bad Request | The request was malformed, contained invalid parameters, or missing required fields. |
| 401 | Unauthorized | Authentication failed, invalid credentials, or access token missing/expired. |
| 403 | Forbidden | The request is understood but has been refused due to insufficient permissions. |
| 404 | Not Found | The requested resource could not be found (e.g., invalid endpoint or transaction ID). |
| 409 | Conflict | The request conflicts with the current state of the resource (e.g., duplicate transaction). |
| 429 | Too Many Requests | Rate limit exceeded. Too many requests made in a given time frame. |
| 500 | Internal Server Error | An unexpected error occurred on Localpayment's servers. |
Error Response Structure
When an error occurs, Localpayment returns a JSON object with detailed error information:
{
"status": {
"code": "300",
"description": "REJECTED",
"detail": "Invalid param + [paymentMethod] + [Is mandatory]"
},
"errors": [
{
"code": "300",
"description": "REJECTED",
"detail": "Invalid param + [paymentMethod] + [Is mandatory]"
}
]
}Error Response Fields
| Field | Type | Description | Example |
|---|---|---|---|
| status.code | string | Localpayment-specific status code | 300 |
| status.description | string | Brief error description | REJECTED |
| status.detail | string | Detailed error message | Invalid param [paymentMethod] |
| errors[] | array | Array of specific error objects | See below |
| errors[].code | string | Localpayment-specific error code | 300 |
Common Error Scenarios
Authentication Errors
{
"detail": "Given token not valid for any token type",
"code": "token_not_valid",
"messages": [
{
"token_class": "AccessToken",
"token_type": "access",
"message": "Token is invalid or expired"
}
]
}Solution
Check your API credentials and ensure your access token is valid. Use the token refresh endpoint if needed.
Validation Errors
{
"externalId": "46014bdc-c3a7-1b15-8dcf-c7050c1c8199",
"internalId": "caa4e9aa-f634-497c-ba75-7f88b005ca62",
"status": {
"code": "801",
"description": "REJECTED",
"detail": "Params error"
},
"errors": [
{
"code": "300",
"detail": "Invalid param + [paymentMethod] + doesn´t exists for MEX"
},
{
"code": "300",
"detail": "Invalid param + [payer.bank.account.[number, type | alias]] + must not be null"
},
{
"code": "300",
"detail": "Invalid param + [payer.document.type] + is invalid for country MEX"
},
{
"code": "300",
"detail": "Invalid param + [payer.document] + is invalid for payer type"
},
{
"code": "701",
"detail": "IncorrectAccountNumber"
}
]
}Solution
Review the
errorsarray for specific field validation issues. Check API documentation for required fields and format specifications.
Business Logic Errors
{
"externalId": "8c0b537a-e907-4d87-93db-5dab9807e093",
"internalId": "dddfde6c-b61c-4b0e-8916-d88886133c4d",
"status": {
"code": "701",
"description": "REJECTED"
},
"errors": [
{
"code": "701",
"detail": "Invalid bank account number. Account number verification failed."
}
]
}Solution
These errors require business-level resolution. Check account balances, transaction limits, or contact support for specific restrictions.
Best Practices for Error Handling
Pro Tip
Implement structured logging from day one. Include correlation IDs, error codes, and context information to make debugging much easier when issues occur in production.
1. Implement Comprehensive Logging
function handleApiError(error, context) {
const logEntry = {
timestamp: new Date().toISOString(),
context: context,
errorCode: error.status?.code,
errorDescription: error.status?.description,
errorDetail: error.status?.detail,
externalId: error.externalId,
httpStatus: error.httpStatus
};
console.error('Localpayment API Error:', logEntry);
// Send to your monitoring system
sendToMonitoring(logEntry);
}2. User-Friendly Error Messages
Create a mapping from technical error codes to user-friendly messages:
const errorMessages = {
'300': 'Please check your information and try again.',
'701': 'Your payment was declined. Please use a different payment method.',
'702': 'Payment authorization expired. Please try again.',
'703': 'Temporary system issue. Please try again in a few minutes.',
'default': 'An unexpected error occurred. Please contact support.'
};
function getUserMessage(errorCode) {
return errorMessages[errorCode] || errorMessages['default'];
}3. Retry Mechanism with Exponential Backoff
async function makeRequestWithRetry(apiCall, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await apiCall();
} catch (error) {
// Only retry on certain errors
if (!isRetryableError(error)) {
throw error;
}
if (attempt === maxRetries) {
throw error;
}
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
function isRetryableError(error) {
const retryableCodes = ['500', '502', '503', '504', '800'];
return retryableCodes.includes(error.status?.code);
}4. Circuit Breaker Pattern
Implement a circuit breaker to prevent cascading failures:
class CircuitBreaker {
constructor(failureThreshold = 5, resetTimeout = 60000) {
this.failureThreshold = failureThreshold;
this.resetTimeout = resetTimeout;
this.failureCount = 0;
this.lastFailureTime = null;
this.state = 'CLOSED';
}
async call(apiFunction) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailureTime > this.resetTimeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit breaker is OPEN');
}
}
try {
const result = await apiFunction();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= this.failureThreshold) {
this.state = 'OPEN';
}
}
}Next Steps
Updated 2 days ago
