Error Handling
Understanding and handling errors in the AuxVault API.
Overview
The AuxVault API uses conventional HTTP response codes to indicate the success or failure of an API request. Errors include helpful information to help you diagnose and resolve issues.
HTTP Status Codes
| Code | Status | Meaning |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Resource conflict (duplicate) |
| 422 | Unprocessable Entity | Validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
| 502 | Bad Gateway | Gateway error |
| 503 | Service Unavailable | Service temporarily down |
Error Response Structure
All errors follow this consistent format:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"field": "fieldName",
"details": {
"additionalInfo": "value"
}
}
}
Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always false for errors |
error.code |
string | Machine-readable error code |
error.message |
string | Human-readable description |
error.field |
string | Field that caused the error (optional) |
error.details |
object | Additional error context (optional) |
Common Error Codes
Authentication Errors
UNAUTHORIZED
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or expired token"
}
}
Solution: Refresh your authentication token.
TENANT_REQUIRED
{
"success": false,
"error": {
"code": "TENANT_REQUIRED",
"message": "X-Tenant-ID header is required"
}
}
Solution: Include X-Tenant-ID header in your request.
TENANT_NOT_FOUND
{
"success": false,
"error": {
"code": "TENANT_NOT_FOUND",
"message": "Tenant not found"
}
}
Solution: Verify your tenant ID is correct.
Validation Errors
VALIDATION_ERROR
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid card number",
"field": "card.number"
}
}
Solution: Fix the invalid field and retry.
REQUIRED_FIELD_MISSING
{
"success": false,
"error": {
"code": "REQUIRED_FIELD_MISSING",
"message": "Required field 'amount' is missing",
"field": "amount"
}
}
Solution: Include all required fields.
INVALID_AMOUNT
{
"success": false,
"error": {
"code": "INVALID_AMOUNT",
"message": "Amount must be greater than 0"
}
}
Solution: Provide a valid positive amount.
Resource Errors
NOT_FOUND
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Transaction not found",
"details": {
"transactionId": "txn_invalid123"
}
}
}
Solution: Verify the resource ID exists.
RESOURCE_CONFLICT
{
"success": false,
"error": {
"code": "RESOURCE_CONFLICT",
"message": "Transaction already voided"
}
}
Solution: Check resource state before retrying.
Payment Errors
TRANSACTION_DECLINED
{
"success": false,
"data": {
"status": "declined",
"declineCode": "insufficient_funds",
"declineReason": "Insufficient funds",
"transactionId": "txn_declined_123"
}
}
Note: This is a 200 OK response with declined status.
AVS_CVV_MISMATCH
{
"success": false,
"error": {
"code": "AVS_CVV_MISMATCH",
"message": "AVS and CVV validation failed",
"details": {
"avsResponse": "N",
"cvvResponse": "N"
}
}
}
Solution: Check billing address and CVV.
GATEWAY_ERROR
{
"success": false,
"error": {
"code": "GATEWAY_ERROR",
"message": "Payment gateway temporarily unavailable"
}
}
Solution: Retry with exponential backoff.
Rate Limiting
RATE_LIMIT_EXCEEDED
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please slow down.",
"details": {
"retryAfter": 60,
"limit": 100,
"remaining": 0,
"resetAt": "2026-01-28T13:00:00Z"
}
}
}
Solution: Wait for retryAfter seconds before retrying.
Permission Errors
FORBIDDEN
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "Insufficient permissions to perform this action"
}
}
Solution: Check your API key permissions.
MERCHANT_NOT_AUTHORIZED
{
"success": false,
"error": {
"code": "MERCHANT_NOT_AUTHORIZED",
"message": "You don't have access to this merchant"
}
}
Solution: Verify merchant ID and your access rights.
Handling Errors in Code
JavaScript/Node.js
try {
const response = await fetch('https://api.auxvault.com/api/v1/transactions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'X-Tenant-ID': tenantId,
'Content-Type': 'application/json'
},
body: JSON.stringify(transactionData)
});
const result = await response.json();
if (!response.ok || !result.success) {
// Handle API error
const error = result.error || { code: 'UNKNOWN_ERROR', message: 'An error occurred' };
switch (error.code) {
case 'UNAUTHORIZED':
// Refresh token and retry
await refreshToken();
return retryRequest();
case 'VALIDATION_ERROR':
// Show validation error to user
console.error(`Validation error on field ${error.field}: ${error.message}`);
break;
case 'RATE_LIMIT_EXCEEDED':
// Wait and retry
const retryAfter = error.details?.retryAfter || 60;
await sleep(retryAfter * 1000);
return retryRequest();
case 'GATEWAY_ERROR':
// Retry with exponential backoff
return retryWithBackoff();
default:
// Log and alert
console.error('API Error:', error);
alert(error.message);
}
throw new Error(error.message);
}
// Success - handle declined transactions
if (result.data?.status === 'declined') {
console.log('Transaction declined:', result.data.declineReason);
// Handle declined transaction
}
return result.data;
} catch (err) {
console.error('Request failed:', err);
throw err;
}
Python
import requests
import time
def process_payment(transaction_data, token, tenant_id):
url = 'https://api.auxvault.com/api/v1/transactions'
headers = {
'Authorization': f'Bearer {token}',
'X-Tenant-ID': tenant_id,
'Content-Type': 'application/json'
}
try:
response = requests.post(url, json=transaction_data, headers=headers)
result = response.json()
if not response.ok or not result.get('success'):
error = result.get('error', {})
code = error.get('code', 'UNKNOWN_ERROR')
message = error.get('message', 'An error occurred')
if code == 'UNAUTHORIZED':
# Refresh token and retry
refresh_token()
return process_payment(transaction_data, new_token, tenant_id)
elif code == 'RATE_LIMIT_EXCEEDED':
# Wait and retry
retry_after = error.get('details', {}).get('retryAfter', 60)
time.sleep(retry_after)
return process_payment(transaction_data, token, tenant_id)
elif code == 'GATEWAY_ERROR':
# Retry with backoff
return retry_with_backoff(transaction_data, token, tenant_id)
else:
raise Exception(f"{code}: {message}")
# Check for declined transaction
if result.get('data', {}).get('status') == 'declined':
print(f"Transaction declined: {result['data'].get('declineReason')}")
return result.get('data')
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
raise
Retry Logic
When to Retry
✅ DO retry these errors:
GATEWAY_ERROR- Gateway temporarily downRATE_LIMIT_EXCEEDED- Rate limit hit503 Service Unavailable- Service temporarily down- Network timeouts
❌ DON'T retry these errors:
VALIDATION_ERROR- Fix validation firstUNAUTHORIZED- Refresh token firstNOT_FOUND- Resource doesn't existFORBIDDEN- Insufficient permissions- Declined transactions - Don't retry declined cards
Exponential Backoff
async function retryWithBackoff(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
// Don't retry non-retryable errors
if (!isRetryable(error)) throw error;
// Wait with exponential backoff
const delay = Math.min(1000 * Math.pow(2, i), 10000); // Max 10s
await sleep(delay);
}
}
}
function isRetryable(error) {
const retryableCodes = [
'GATEWAY_ERROR',
'SERVICE_UNAVAILABLE',
'TIMEOUT'
];
return retryableCodes.includes(error.code) || error.status >= 500;
}
Idempotency
Prevent duplicate transactions by using idempotency keys:
curl -X POST https://api.auxvault.com/api/v1/transactions \
-H "Authorization: Bearer TOKEN" \
-H "X-Tenant-ID: tenant-id" \
-H "Idempotency-Key: unique-key-12345" \
-d '{"type":"sale","amount":100.00,...}'
If you retry with the same key, you'll get the same response without creating a duplicate transaction.
Logging & Monitoring
What to Log
✅ DO log:
- Request IDs for tracking
- Error codes and messages
- User actions that caused errors
- Timestamps
- Retry attempts
❌ DON'T log:
- Full card numbers
- CVV codes
- Raw API tokens
- Customer passwords
Example Log Entry
{
"timestamp": "2026-01-28T12:34:56Z",
"level": "error",
"requestId": "req_abc123",
"errorCode": "VALIDATION_ERROR",
"errorMessage": "Invalid card number",
"field": "card.number",
"userId": "user_123",
"action": "process_payment",
"retryCount": 0
}
Testing Errors
Trigger Specific Errors
Use test card numbers to trigger specific responses:
| Card Number | Result |
|---|---|
| 4000000000000002 | Declined - Insufficient Funds |
| 4000000000000127 | Declined - Invalid CVV |
| 4000000000000119 | Declined - Expired Card |
| 4000000000000101 | Declined - Fraud |
Best Practices
✅ DO:
- Handle all error cases gracefully
- Show user-friendly messages to customers
- Log errors for debugging
- Implement retry logic for transient errors
- Use idempotency keys for critical operations
- Monitor error rates to detect issues early
- Validate data before sending to API
❌ DON'T:
- Don't expose raw errors to end users
- Don't retry indefinitely - set max attempts
- Don't ignore errors - always handle them
- Don't retry validation errors without fixing them
- Don't log sensitive data
Complete Error Code Reference
Next Steps
Need help? Contact support@auxvault.com