Error Codes
Understand and handle errors returned by the Venshack API.
Error Response Format
All API errors return a consistent JSON format:
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Wallet balance is insufficient for this transaction",
"details": {
"required": 5000,
"available": 2500
}
},
"requestId": "req_xyz789"
}
Error Object Fields
| Field | Type | Description |
|---|---|---|
code |
string | Machine-readable error code |
message |
string | Human-readable error description |
details |
object | Additional context (optional) |
requestId |
string | Unique ID for support inquiries |
HTTP Status Codes
The API uses standard HTTP status codes to indicate success or failure:
| Code | Meaning | Description |
|---|---|---|
200 |
OK | Request succeeded |
201 |
Created | Resource created successfully |
400 |
Bad Request | Invalid request parameters |
401 |
Unauthorized | Missing or invalid API key |
403 |
Forbidden | API key lacks required permissions |
404 |
Not Found | Resource doesn't exist |
409 |
Conflict | Resource already exists or state conflict |
422 |
Unprocessable Entity | Valid format but logical error |
429 |
Too Many Requests | Rate limit exceeded |
500 |
Internal Server Error | Server error (retry with backoff) |
503 |
Service Unavailable | Service temporarily down |
Authentication Errors
| Code | HTTP | Description | Resolution |
|---|---|---|---|
MISSING_API_KEY |
401 | No API key provided | Include API key in Authorization header |
INVALID_API_KEY |
401 | API key is malformed or doesn't exist | Check your API key in the dashboard |
EXPIRED_API_KEY |
401 | API key has been revoked or expired | Generate a new API key |
INSUFFICIENT_PERMISSIONS |
403 | API key lacks required scope | Use a key with appropriate permissions |
Validation Errors
| Code | HTTP | Description | Resolution |
|---|---|---|---|
VALIDATION_ERROR |
400 | Request body validation failed | Check the details field for specific issues |
INVALID_METER_NUMBER |
400 | Meter number format is invalid | Verify meter number (usually 11-13 digits) |
INVALID_AMOUNT |
400 | Amount is invalid or out of range | Check minimum (₦500) and maximum (₦500,000) limits |
INVALID_DISCO |
400 | Unknown distribution company code | Use valid DISCO codes (EKEDC, IKEDC, etc.) |
Vending Errors
| Code | HTTP | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_BALANCE |
422 | Wallet balance is too low | Fund wallet before attempting vend |
METER_NOT_FOUND |
404 | Meter not registered in system | Register the meter first via /meters endpoint |
METER_VALIDATION_FAILED |
422 | Meter couldn't be validated with DISCO | Verify meter number and DISCO are correct |
VEND_IN_PROGRESS |
409 | A vend is already processing for this meter | Wait for current transaction to complete |
DISCO_UNAVAILABLE |
503 | DISCO service is temporarily unavailable | Retry after a few minutes |
VEND_FAILED |
500 | Vend failed at provider level | Funds auto-refund; check webhook for details |
MINIMUM_VEND_AMOUNT |
400 | Amount below minimum | Increase amount to at least ₦500 |
MAXIMUM_VEND_AMOUNT |
400 | Amount exceeds maximum | Reduce amount to ₦500,000 or less |
Wallet Errors
| Code | HTTP | Description | Resolution |
|---|---|---|---|
WALLET_NOT_FOUND |
404 | Wallet doesn't exist for this account | Contact support to initialize wallet |
WALLET_LOCKED |
423 | Wallet is locked due to suspicious activity | Contact support to unlock |
DUPLICATE_REFERENCE |
409 | Transaction reference already used | Generate a unique reference for each transaction |
Access Code Errors
| Code | HTTP | Description | Resolution |
|---|---|---|---|
CODE_ALREADY_USED |
409 | Access code has already been used | Generate a new code for the visitor |
CODE_EXPIRED |
410 | Access code has expired | Generate a new code with valid expiry |
CODE_NOT_FOUND |
404 | Access code doesn't exist | Verify the code or generate a new one |
MAX_CODES_REACHED |
429 | Maximum active codes limit reached | Wait for existing codes to expire or delete some |
Rate Limiting
When you exceed rate limits, you'll receive a 429 response:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please retry after 60 seconds.",
"details": {
"retryAfter": 60,
"limit": 100,
"window": "1m"
}
}
}
Rate Limit Headers
Check response headers for rate limit info:
Check response headers for rate limit info:
X-RateLimit-Limit: Maximum requests per windowX-RateLimit-Remaining: Requests remainingX-RateLimit-Reset: Unix timestamp when limit resets
Error Handling Best Practices
1. Check Error Codes, Not Messages
Error messages may change over time. Always use the code field
for programmatic handling:
// ✅ Good
if (error.code === 'INSUFFICIENT_BALANCE') {
promptUserToFundWallet();
}
// ❌ Bad
if (error.message.includes('insufficient')) {
promptUserToFundWallet();
}
2. Implement Retry Logic
For transient errors (5xx, DISCO_UNAVAILABLE), implement exponential backoff:
async function vendWithRetry(params, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await venshack.vend(params);
} catch (error) {
if (!isRetryable(error) || i === maxRetries - 1) {
throw error;
}
await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
}
}
}
function isRetryable(error) {
return error.status >= 500 ||
error.code === 'DISCO_UNAVAILABLE';
}
3. Log Request IDs
Always log the requestId from error responses. This helps
support debug issues quickly:
try {
await venshack.vend(params);
} catch (error) {
console.error('Vend failed', {
code: error.code,
message: error.message,
requestId: error.requestId // Important for support
});
}
4. Handle Validation Errors Gracefully
Validation errors include details about which fields failed:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"fields": [
{ "field": "meterNumber", "error": "Must be 11-13 digits" },
{ "field": "amount", "error": "Must be at least 500" }
]
}
}
}
Need Help?
If you encounter persistent errors, contact support with the
If you encounter persistent errors, contact support with the
requestId from the error response. We can trace exactly what
happened.