Skip to main content

Error Handling

VesuvioPay uses conventional HTTP status codes and structured error responses to indicate the success or failure of API requests. This guide explains how to handle errors effectively in your integration.

HTTP Status Codes​

VesuvioPay API uses the following HTTP status codes:

Status CodeDescriptionWhen to Expect
200 OKRequest succeededSuccessful GET, PUT, PATCH, DELETE requests
201 CreatedResource created successfullySuccessful POST requests that create new resources
400 Bad RequestInvalid request parameters or validation failedMissing required fields, invalid data format
401 UnauthorizedAuthentication failedInvalid or missing API key, expired JWT token
403 ForbiddenAccess deniedInsufficient permissions, wrong store access
404 Not FoundResource doesn't existCustomer, product, order, or other resource not found
409 ConflictResource conflictDuplicate email/phone, resource already exists
429 Too Many RequestsRate limit exceededToo many requests in a short time period
500 Internal Server ErrorServer errorUnexpected server-side issue
503 Service UnavailableService temporarily unavailableMaintenance, temporary outage

Error Response Structure​

All error responses follow a consistent JSON structure:

Basic Error Response​

{
"success": false,
"message": "Human-readable error description",
"errorCode": "SPECIFIC_ERROR_CODE"
}

Validation Error Response​

When validation fails (HTTP 400), the response includes detailed field-level errors:

{
"success": false,
"message": "Validation failed",
"errorCode": "VALIDATION_FAILED",
"errors": [
{
"field": "email",
"message": "Email address is required"
},
{
"field": "phoneNumber",
"message": "Invalid phone number format"
}
]
}

Error Code Reference​

Customer Errors​

Error CodeHTTP StatusDescriptionResolution
CUSTOMER_NOT_FOUND404Customer doesn't existVerify customer ID is correct
CUSTOMER_ALREADY_DELETED409Customer was already deletedCannot perform operations on deleted customers
CUSTOMER_PROFILE_UPDATE_FAILED500Failed to update customer profileRetry request or contact support

Address Errors​

Error CodeHTTP StatusDescriptionResolution
ADDRESS_NOT_FOUND404Address doesn't existVerify address ID is correct
ADDRESS_CREATION_FAILED500Failed to create addressCheck address data and retry
ADDRESS_UPDATE_FAILED500Failed to update addressRetry request or contact support
ADDRESS_DELETION_FAILED500Failed to delete addressRetry request or contact support
INVALID_ADDRESS_DATA400Invalid address informationCheck required fields and format

Authentication Errors​

Error CodeHTTP StatusDescriptionResolution
INVALID_TOKEN401JWT token is invalidObtain a new JWT token
TOKEN_EXPIRED401JWT token has expiredRefresh or obtain a new token
ACCESS_DENIED403Insufficient permissionsUse appropriate API key type
INVALID_CREDENTIALS401Login credentials are incorrectVerify username/password
USER_NOT_FOUND404User account doesn't existCheck user identifier
USER_ALREADY_EXISTS409User with this email/phone existsUse different credentials or login
REGISTRATION_INCOMPLETE400Registration process not finishedComplete all registration steps
AUTHENTICATION_FAILED401Authentication process failedRetry authentication flow
SOCIAL_AUTH_FAILED401Social login failedRetry or use alternative method
COMPANY_SETUP_FAILED500Failed to set up companyContact support

API Key Errors​

Error CodeHTTP StatusDescriptionResolution
API_KEY_NOT_FOUND404API key doesn't existVerify API key ID
INVALID_API_KEY401API key is invalid or malformedCheck API key format and value
API_KEY_INACTIVE401API key has been revokedGenerate a new API key
API_KEY_EXPIRED401API key has expiredGenerate a new API key
API_KEY_CREATION_FAILED500Failed to create API keyRetry or contact support
API_KEY_UPDATE_FAILED500Failed to update API keyRetry or contact support
API_KEY_ROTATION_FAILED500Failed to rotate API keyRetry or contact support
API_KEY_REVOCATION_FAILED500Failed to revoke API keyRetry or contact support
NO_STORE_ACCESS403API key lacks store accessUse correct API key for this store

Email & Phone Errors​

Error CodeHTTP StatusDescriptionResolution
EMAIL_ALREADY_IN_USE409Email is registered to another accountUse different email or login
EMAIL_VERIFICATION_FAILED400Email verification failedRetry verification process
EMAIL_CHANGE_NOT_AVAILABLE400Email change not allowedCheck account restrictions
EMAIL_CHANGE_FAILED500Failed to change emailRetry or contact support
PHONE_ALREADY_IN_USE409Phone number is registeredUse different number or login
PHONE_VERIFICATION_FAILED400Phone verification failedRetry verification process
PHONE_CHANGE_NOT_AVAILABLE400Phone change not allowedCheck account restrictions
INVALID_PHONE_FORMAT400Phone number format invalidUse E.164 format (+1234567890)
PHONE_CHANGE_FAILED500Failed to change phoneRetry or contact support

Payment Errors​

Error CodeHTTP StatusDescriptionResolution
PAYMENT_GATEWAY_ERROR500Payment gateway returned errorCheck gateway status, retry
PAYMENT_METHOD_NOT_FOUND404Payment method doesn't existVerify payment method ID
PAYMENT_METHOD_CREATION_FAILED500Failed to create payment methodCheck payment details, retry
PAYMENT_PROCESSING_FAILED500Payment processing failedVerify payment details, retry
PAYMENT_INTENT_CREATION_FAILED500Failed to create payment intentRetry or contact support
PAYMENT_INTENT_CONFIRMATION_FAILED500Failed to confirm payment intentVerify payment details, retry
TRANSFER_CREATION_FAILED500Failed to create transferRetry or contact support
WEBHOOK_VALIDATION_FAILED400Webhook signature invalidCheck webhook secret configuration

Payment Account Errors​

Error CodeHTTP StatusDescriptionResolution
PAYMENT_ACCOUNT_NOT_FOUND404Payment account doesn't existVerify account ID
PAYMENT_ACCOUNT_CREATION_FAILED500Failed to create payment accountRetry or contact support
PAYMENT_ACCOUNT_UPDATE_FAILED500Failed to update payment accountRetry or contact support
EXTERNAL_ACCOUNT_ID_MISSING400External account ID requiredProvide Stripe account ID

Card & Bank Account Errors​

Error CodeHTTP StatusDescriptionResolution
CARD_NOT_FOUND404Card doesn't existVerify card ID
CARD_CREATION_FAILED500Failed to create cardCheck card details, retry
CARD_DELETION_FAILED500Failed to delete cardRetry or contact support
CANNOT_DELETE_DEFAULT_CARD400Cannot delete default cardSet new default first
CARD_SYNC_FAILED500Failed to sync cardRetry or contact support
SET_DEFAULT_CARD_FAILED500Failed to set default cardRetry or contact support
STRIPE_CUSTOMER_CREATION_FAILED500Failed to create Stripe customerRetry or contact support
BANK_ACCOUNT_NOT_FOUND404Bank account doesn't existVerify account ID
BANK_ACCOUNT_CREATION_FAILED500Failed to create bank accountCheck account details, retry
BANK_ACCOUNT_DELETION_FAILED500Failed to delete bank accountRetry or contact support
CANNOT_DELETE_DEFAULT_BANK_ACCOUNT400Cannot delete default accountSet new default first
BANK_ACCOUNT_SYNC_FAILED500Failed to sync bank accountRetry or contact support

Cart & Checkout Errors​

Error CodeHTTP StatusDescriptionResolution
CART_NOT_FOUND404Cart doesn't existCreate a new cart
EMPTY_CART400Cart has no itemsAdd items before checkout
CHECKOUT_NOT_FOUND404Checkout session doesn't existVerify checkout ID or create new
CHECKOUT_CREATION_FAILED500Failed to create checkoutRetry or contact support
CHECKOUT_INVALID_STATE400Checkout in invalid stateVerify checkout status
INSUFFICIENT_PAYMENT_METHODS400No valid payment methodAdd payment method

Product & Inventory Errors​

Error CodeHTTP StatusDescriptionResolution
PRODUCT_NOT_FOUND404Product doesn't existVerify product ID
PRODUCT_VARIANT_NOT_FOUND404Product variant doesn't existVerify variant ID
INSUFFICIENT_INVENTORY400Not enough stock availableReduce quantity or wait for restock
PRODUCT_OUT_OF_STOCK400Product is out of stockRemove from cart or wait for restock
INVENTORY_LIMIT_EXCEEDED400Requested quantity too highReduce quantity to available stock

Order Errors​

Error CodeHTTP StatusDescriptionResolution
ORDER_NOT_FOUND404Order doesn't existVerify order ID

Subscription & Invoice Errors​

Error CodeHTTP StatusDescriptionResolution
SUBSCRIPTION_NOT_FOUND404Subscription doesn't existVerify subscription ID
PLAN_NOT_FOUND404Subscription plan doesn't existVerify plan ID
INVOICE_NOT_FOUND404Invoice doesn't existVerify invoice ID
INVOICE_NOT_PAID400Invoice has not been paidProcess payment first
INVOICE_DOWNLOAD_FAILED500Failed to download invoiceRetry or contact support

File Upload Errors​

Error CodeHTTP StatusDescriptionResolution
FILE_NOT_PROVIDED400No file was uploadedInclude file in request
FILE_SIZE_EXCEEDED400File size too largeReduce file size
INVALID_FILE_FORMAT400File format not supportedUse supported format
INVALID_CONTENT_TYPE400Content-Type header incorrectSet proper Content-Type
FILE_UPLOAD_FAILED500File upload failedRetry or contact support

SMS & Template Errors​

Error CodeHTTP StatusDescriptionResolution
SMS_NOT_FOUND404SMS record doesn't existVerify SMS ID
TWILIO_SETTINGS_NOT_FOUND404Twilio configuration missingConfigure Twilio settings
TEMPLATE_TYPE_NOT_FOUND404Template type doesn't existVerify template type
TEMPLATE_WORD_NOT_FOUND404Template word doesn't existVerify template word
TEMPLATE_NOT_FOUND404Template doesn't existVerify template ID
TEMPLATE_CREATION_FAILED500Failed to create templateRetry or contact support
TEMPLATE_UPDATE_FAILED500Failed to update templateRetry or contact support
TEMPLATE_DELETION_FAILED500Failed to delete templateRetry or contact support
TEMPLATE_IN_USE400Template is being usedCannot delete active template

Platform & Store Errors​

Error CodeHTTP StatusDescriptionResolution
PLATFORM_NOT_FOUND404Platform doesn't existVerify platform ID
STORE_NOT_FOUND404Store doesn't existVerify store ID
COMPANY_NOT_FOUND404Company doesn't existVerify company ID

General Errors​

Error CodeHTTP StatusDescriptionResolution
VALIDATION_FAILED400Request validation failedCheck errors array for details
INVALID_INPUT400Input data is invalidVerify request parameters
INVALID_OPERATION400Operation not allowedCheck resource state
INVALID_ENTITY_TYPE400Entity type is invalidUse valid entity type
STORE_ID_REQUIRED400Store ID is requiredInclude store ID in request
INVALID_PREFIX400ID prefix is invalidUse valid prefix
RESOURCE_NOT_FOUND404Requested resource not foundVerify resource identifier
DUPLICATE_RESOURCE409Resource already existsUse different identifier
INTERNAL_ERROR500Internal server errorRetry or contact support
INTERNAL_SERVER_ERROR500Internal server errorRetry or contact support
SERVICE_UNAVAILABLE503Service temporarily unavailableWait and retry with backoff
TIMEOUT504Request timeoutRetry request
HTTP_REQUEST_FAILED500HTTP request failedCheck network, retry

Common Error Scenarios​

Scenario 1: Invalid API Key​

Problem: Using an incorrect or revoked API key

{
"success": false,
"message": "Invalid API key",
"errorCode": "INVALID_API_KEY"
}

Solution:

  • Verify your API key is correct
  • Check if the key has been revoked
  • Ensure you're using the right environment key (test vs live)
  • Generate a new API key if necessary

Scenario 2: Resource Not Found​

Problem: Attempting to access a non-existent resource

{
"success": false,
"message": "Customer not found",
"errorCode": "CUSTOMER_NOT_FOUND"
}

Solution:

  • Verify the resource ID is correct
  • Check if the resource was deleted
  • Ensure you're searching in the correct store
  • Handle 404 errors gracefully in your application

Scenario 3: Validation Errors​

Problem: Submitting invalid data

{
"success": false,
"message": "Validation failed",
"errorCode": "VALIDATION_FAILED",
"errors": [
{
"field": "email",
"message": "Email address is required"
},
{
"field": "phoneNumber",
"message": "Phone number must be in E.164 format"
}
]
}

Solution:

  • Check all required fields are provided
  • Validate data format before sending
  • Display field-level errors to users
  • Refer to API documentation for field requirements

Scenario 4: Duplicate Resource​

Problem: Attempting to create a resource that already exists

{
"success": false,
"message": "Email already in use",
"errorCode": "EMAIL_ALREADY_IN_USE"
}

Solution:

  • Check if the resource exists before creating
  • Use update endpoint instead of create
  • Implement proper conflict handling
  • Inform users about existing resources

Scenario 5: Rate Limiting​

Problem: Exceeding API rate limits

{
"success": false,
"message": "Too many requests",
"errorCode": "RATE_LIMIT_EXCEEDED"
}

Solution:

  • Implement exponential backoff
  • Cache responses when possible
  • Batch requests if supported
  • Monitor rate limit headers

Scenario 6: Payment Processing Failed​

Problem: Payment processing encountered an error

{
"success": false,
"message": "Payment processing failed",
"errorCode": "PAYMENT_PROCESSING_FAILED"
}

Solution:

  • Verify payment method details
  • Check if payment method is valid
  • Ensure sufficient funds
  • Ask customer to try a different payment method
  • Contact support if issue persists

Retry Logic Recommendations​

When to Retry​

Retry requests for these scenarios:

  • Network errors: Connection timeouts, DNS failures
  • HTTP 429: Rate limit exceeded
  • HTTP 500: Internal server error
  • HTTP 503: Service unavailable
  • HTTP 504: Gateway timeout

When NOT to Retry​

Do not retry for these errors:

  • HTTP 400: Bad request (fix the request instead)
  • HTTP 401: Unauthorized (update credentials)
  • HTTP 403: Forbidden (check permissions)
  • HTTP 404: Not found (resource doesn't exist)
  • HTTP 409: Conflict (handle conflict resolution)

Exponential Backoff Strategy​

Implement exponential backoff for retries:

async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);

// Success - return response
if (response.ok) {
return await response.json();
}

// Don't retry client errors (4xx except 429)
if (response.status >= 400 && response.status < 500 && response.status !== 429) {
const error = await response.json();
throw new Error(`API Error: ${error.message}`);
}

// Retry on 429, 5xx errors
if (response.status === 429 || response.status >= 500) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
console.log(`Retry attempt ${attempt + 1} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}

} catch (error) {
// Network error - retry
if (attempt < maxRetries - 1) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`Network error, retry after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}

throw new Error('Max retries exceeded');
}
// C# Retry with Exponential Backoff
public async Task<T> MakeRequestWithRetryAsync<T>(
Func<Task<HttpResponseMessage>> requestFunc,
int maxRetries = 3)
{
for (int attempt = 0; attempt < maxRetries; attempt++)
{
try
{
var response = await requestFunc();

// Success
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<T>(content);
}

// Don't retry client errors (except 429)
if ((int)response.StatusCode >= 400 &&
(int)response.StatusCode < 500 &&
response.StatusCode != HttpStatusCode.TooManyRequests)
{
var error = await response.Content.ReadAsStringAsync();
throw new ApiException($"API Error: {error}");
}

// Retry on 429, 5xx
if (response.StatusCode == HttpStatusCode.TooManyRequests ||
(int)response.StatusCode >= 500)
{
var delay = (int)Math.Pow(2, attempt) * 1000;
Console.WriteLine($"Retry attempt {attempt + 1} after {delay}ms");
await Task.Delay(delay);
continue;
}
}
catch (HttpRequestException ex)
{
// Network error - retry
if (attempt < maxRetries - 1)
{
var delay = (int)Math.Pow(2, attempt) * 1000;
Console.WriteLine($"Network error, retry after {delay}ms");
await Task.Delay(delay);
continue;
}
throw;
}
}

throw new Exception("Max retries exceeded");
}

Error Handling Best Practices​

1. Always Check Response Status​

Always verify the response status before processing data:

const response = await fetch(url, options);

if (!response.ok) {
const error = await response.json();
console.error('API Error:', error.errorCode, error.message);
// Handle error appropriately
throw new Error(error.message);
}

const data = await response.json();
// Process successful response

2. Use try-catch Blocks​

Wrap API calls in try-catch blocks:

try {
const customer = await getCustomer(customerId);
// Process customer data
} catch (error) {
if (error.errorCode === 'CUSTOMER_NOT_FOUND') {
// Handle missing customer
console.log('Customer does not exist');
} else if (error.errorCode === 'INVALID_API_KEY') {
// Handle authentication error
console.error('Authentication failed');
} else {
// Handle unexpected errors
console.error('Unexpected error:', error);
}
}
// C# Example
try
{
var customer = await GetCustomerAsync(customerId);
// Process customer data
}
catch (ApiException ex) when (ex.ErrorCode == "CUSTOMER_NOT_FOUND")
{
// Handle missing customer
Console.WriteLine("Customer does not exist");
}
catch (ApiException ex) when (ex.ErrorCode == "INVALID_API_KEY")
{
// Handle authentication error
Console.Error.WriteLine("Authentication failed");
}
catch (Exception ex)
{
// Handle unexpected errors
Console.Error.WriteLine($"Unexpected error: {ex.Message}");
}

3. Log Errors for Debugging​

Log errors with context for troubleshooting:

function logError(error, context) {
console.error('VesuvioPay API Error', {
timestamp: new Date().toISOString(),
errorCode: error.errorCode,
message: error.message,
context: context,
statusCode: error.statusCode
});

// Send to error tracking service
// errorTracker.captureException(error, { context });
}

4. Display User-Friendly Messages​

Don't expose technical errors to end users:

function getUserFriendlyMessage(errorCode) {
const messages = {
'CUSTOMER_NOT_FOUND': 'We couldn\'t find your account. Please try again.',
'PAYMENT_PROCESSING_FAILED': 'Your payment could not be processed. Please check your payment details.',
'INSUFFICIENT_INVENTORY': 'This item is out of stock. Please try a different product.',
'INVALID_API_KEY': 'Authentication failed. Please contact support.',
'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment and try again.'
};

return messages[errorCode] || 'An unexpected error occurred. Please try again later.';
}

5. Implement Proper Error Boundaries​

For frontend applications, use error boundaries:

class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };

static getDerivedStateFromError(error) {
return { hasError: true, error };
}

componentDidCatch(error, errorInfo) {
logError(error, { component: errorInfo.componentStack });
}

render() {
if (this.state.hasError) {
return (
<div className="error-container">
<h2>Something went wrong</h2>
<p>Please refresh the page or contact support.</p>
</div>
);
}

return this.props.children;
}
}

6. Validate Before Sending​

Validate data client-side before making API requests:

function validateCustomerData(data) {
const errors = [];

if (!data.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
errors.push({ field: 'email', message: 'Valid email is required' });
}

if (!data.phoneNumber || !/^\+[1-9]\d{1,14}$/.test(data.phoneNumber)) {
errors.push({ field: 'phoneNumber', message: 'Phone must be in E.164 format' });
}

if (errors.length > 0) {
throw { errorCode: 'VALIDATION_FAILED', errors };
}
}

7. Monitor and Alert​

Set up monitoring for critical errors:

// Monitor error rates
function trackError(errorCode, statusCode) {
// Send to analytics/monitoring service
analytics.track('api_error', {
error_code: errorCode,
status_code: statusCode,
timestamp: Date.now()
});

// Alert on critical errors
if (statusCode >= 500 || errorCode === 'PAYMENT_PROCESSING_FAILED') {
alerting.send({
severity: 'high',
message: `Critical API error: ${errorCode}`,
statusCode: statusCode
});
}
}

8. Handle Validation Errors Gracefully​

Display field-level validation errors:

function displayValidationErrors(errors) {
// Clear previous errors
document.querySelectorAll('.error-message').forEach(el => el.remove());

// Display new errors
errors.forEach(error => {
const field = document.querySelector(`[name="${error.field}"]`);
if (field) {
const errorElement = document.createElement('span');
errorElement.className = 'error-message';
errorElement.textContent = error.message;
field.parentNode.appendChild(errorElement);
field.classList.add('error');
}
});
}

Testing Error Handling​

Test Different Error Scenarios​

describe('VesuvioPay Error Handling', () => {
test('handles CUSTOMER_NOT_FOUND error', async () => {
// Mock API to return 404
mockFetch.mockResolvedValueOnce({
ok: false,
status: 404,
json: async () => ({
success: false,
errorCode: 'CUSTOMER_NOT_FOUND',
message: 'Customer not found'
})
});

await expect(getCustomer('invalid-id'))
.rejects.toThrow('Customer not found');
});

test('retries on 500 error', async () => {
// First two calls fail, third succeeds
mockFetch
.mockResolvedValueOnce({ ok: false, status: 500 })
.mockResolvedValueOnce({ ok: false, status: 500 })
.mockResolvedValueOnce({
ok: true,
json: async () => ({ success: true, data: {} })
});

const result = await makeRequestWithRetry(url, options);
expect(mockFetch).toHaveBeenCalledTimes(3);
});
});
Best Practice

Always test both success and error paths in your integration to ensure graceful error handling.

Next Steps​

Need Help?

If you encounter errors not covered in this guide, please contact support at support@vesuviopay.com with:

  • Error code and message
  • Request details (endpoint, parameters)
  • Steps to reproduce
  • Expected vs actual behavior