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:
  • X-RateLimit-Limit: Maximum requests per window
  • X-RateLimit-Remaining: Requests remaining
  • X-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 requestId from the error response. We can trace exactly what happened.