Errors
ZevPay uses standard HTTP status codes and consistent error response formats.
Error response format
All error responses follow this structure:
json
{
"success": false,
"error": {
"code": "HTTP_ERROR",
"message": "A human-readable error description"
},
"correlationId": "-"
}| Field | Type | Description |
|---|---|---|
success | boolean | Always false for errors |
error.code | string | Machine-readable error code |
error.message | string | Human-readable description of what went wrong |
correlationId | string | Request correlation ID (from x-correlation-id header, or "-") |
Error codes
| Code | Description |
|---|---|
HTTP_ERROR | Standard HTTP error (bad request, not found, unauthorized, etc.) |
INTERNAL_ERROR | Unexpected server error |
HTTP status codes
| Code | Meaning | Description |
|---|---|---|
200 | OK | Request succeeded |
400 | Bad Request | Invalid parameters, expired session, or business logic error |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | Origin not allowed for this API key |
404 | Not Found | Resource does not exist |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Something went wrong on our end |
Common errors
Authentication errors
| Status | Message | Cause | Solution |
|---|---|---|---|
401 | Invalid API key | API key not found or inactive | Check your API key is correct and active |
403 | Origin not allowed for this API key | Request origin doesn't match allowed domains | Add your domain to the API key's allowed domains in the dashboard |
Session errors
| Status | Message | Cause | Solution |
|---|---|---|---|
404 | Session not found. | Invalid session ID | Verify the session ID is correct |
400 | Session is expired. | Session status is expired | Create a new session |
400 | Session is completed. | Payment already received | No action needed — payment is done |
400 | Session has expired. | Session's expiresAt time has passed | Create a new session |
400 | Session does not belong to this API key. | API key not from the same key pair | Use a key from the same key pair used to create the session |
Payment method errors
| Status | Message | Cause | Solution |
|---|---|---|---|
400 | Unsupported payment method: | Invalid payment_method value | Use "bank_transfer" or "payid" |
Validation errors
| Status | Message | Cause | Solution |
|---|---|---|---|
400 | amount must not be less than 100 | Amount below minimum | Minimum is 100 kobo (NGN 1.00) |
400 | email must be an email | Invalid email format | Provide a valid email address |
Rate limit errors
| Status | Message | Cause | Solution |
|---|---|---|---|
429 | Too Many Requests | Exceeded 100 requests/min (or 30/min for session initialization) | Wait and retry with exponential backoff — see Rate Limiting |
Handling errors
Always check the success field in the response. If false, read error.message for details. Implement exponential backoff for 429 and 5xx errors.
Error handling example
js
const response = await fetch('https://api.zevpaycheckout.com/v1/checkout/session/initialize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'sk_test_your_secret_key',
},
body: JSON.stringify({
amount: 500000,
currency: 'NGN',
email: 'customer@example.com',
}),
});
const result = await response.json();
if (!response.ok || result.success === false) {
console.error(`Error: ${result.error?.message || 'Unknown error'}`);
// Handle error appropriately
return;
}
// Success
const session = result.data;python
import requests
response = requests.post(
"https://api.zevpaycheckout.com/v1/checkout/session/initialize",
headers={
"Content-Type": "application/json",
"x-api-key": "sk_test_your_secret_key",
},
json={
"amount": 500000,
"currency": "NGN",
"email": "customer@example.com",
},
)
result = response.json()
if not response.ok or not result.get("success"):
error = result.get("error", {})
print(f"Error: {error.get('message', 'Unknown error')}")
# Handle error
else:
session = result["data"]