Errors
Lira uses consistent error shapes and standard HTTP status codes across all endpoints — this page is the central reference for everything that can go wrong and how to handle it.
Error response format
All errors from Lira follow this standard shape:
{
"message": "Human-readable description of the error",
"code": "MACHINE_READABLE_CODE",
"statusCode": 422
}
| Field | Type | Description |
|---|---|---|
message |
string | A human-readable explanation of the error. |
code |
string | A machine-readable code for programmatic error handling. |
statusCode |
number | The HTTP status code, mirrored in the response body for convenience. |
HTTP status codes
| Status | Name | When it occurs |
|---|---|---|
400 |
Bad Request | Malformed request body or invalid JSON |
401 |
Unauthorized | Missing, invalid, or expired authentication credential |
403 |
Forbidden | Valid authentication but insufficient role or permissions for this action |
404 |
Not Found | The requested resource (webhook, verification, API key) does not exist |
422 |
Unprocessable Entity | The request is valid JSON but fails validation — missing required field, wrong format, etc. |
429 |
Too Many Requests | Rate limit exceeded |
500 |
Internal Server Error | Unexpected server error — if persistent, contact support with the request ID |
Verification error codes
These codes appear in the error.code field of a verification response when status is failed or error. They are returned with an HTTP 200 OK — the request was processed successfully, but the verification itself did not pass.
| Code | Verification type | Meaning | Recommended action |
|---|---|---|---|
ACCOUNT_NOT_FOUND |
Bank account | Account number not found at the specified bank | Ask the user to check their account number and bank code |
INVALID_BANK_CODE |
Bank account | The bank code is not recognised | Check the bank code against the supported banks list |
INVALID_ACCOUNT_NUMBER |
Bank account | Account number format is invalid | Validate the format before submitting (10 digits for Nigeria) |
SUBSCRIBER_NOT_FOUND |
Phone number | Phone number is not registered with the carrier | Ask the user to verify their number |
INVALID_PHONE_NUMBER |
Phone number | Phone number format is invalid | Validate E.164 or local format before submitting |
INVALID_NETWORK_CODE |
Phone number | Network code is not recognised for the given country | Check the supported network codes in Verify a Phone Number |
NETWORK_CODE_REQUIRED |
Phone number | Ghana verifications require a networkCode |
Add the networkCode field to the request |
PROVIDER_ERROR |
Both | The upstream provider returned an unexpected error | Retry with exponential backoff |
PROVIDER_TIMEOUT |
Both | The upstream provider did not respond within the timeout window | Retry — this is a transient error |
Note: A
200 OKdoes not mean the verification succeeded. Always check thestatusfield in the response body. A status offailedis a valid, expected outcome — it means the account or number was not found, not that the API call itself failed.
Webhook error codes
Webhook-related errors are returned as standard HTTP error responses when creating or updating a webhook. The status field on a webhook object reflects its delivery health.
| Webhook status | Meaning |
|---|---|
active |
Webhook is enabled and will receive deliveries |
inactive |
Webhook has been manually disabled |
failed |
All retry attempts for the most recent delivery were exhausted |
| Condition | HTTP status | Action |
|---|---|---|
| All retry attempts exhausted | — (webhook status set to failed) |
PATCH the webhook status back to active to resume deliveries |
| Invalid or non-HTTPS URL on create or update | 422 |
Provide a valid https:// URL that is publicly reachable |
| Webhook not found | 404 |
Check the WEBHOOK_ID — use GET /client/webhooks to list all webhooks |
Handling errors in your code
The example below shows a verification request that returns a failed result and how to handle it:
curl -X POST https://api.lira.com/api/v1/verify/account \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountNumber": "0000000001",
"country": "NG",
"bankCode": "044"
}'
Response 200 OK (note: HTTP 200, but verification failed)
{
"id": "ver_a1b2c3d4-...",
"status": "failed",
"verified": false,
"error": {
"code": "ACCOUNT_NOT_FOUND",
"message": "No account found for the provided details"
}
}
In your code, always branch on status first, then on error.code:
const result = await response.json();
if (result.status === 'success') {
// proceed — read accountName, bankName, etc.
console.log('Verified:', result.accountName);
} else if (result.status === 'failed') {
// handle based on error.code
switch (result.error.code) {
case 'ACCOUNT_NOT_FOUND':
// prompt user to recheck their account number and bank code
break;
case 'INVALID_BANK_CODE':
// show bank code validation error
break;
case 'SUBSCRIBER_NOT_FOUND':
// prompt user to verify their phone number
break;
default:
// unknown failure — log and surface a generic user message
}
} else if (result.status === 'error') {
// transient failure — retry with exponential backoff
} else if (result.status === 'pending') {
// async mode — wait for webhook or poll GET /verify/:id
}
Note: A
200 OKdoes not mean the verification succeeded. Always check thestatusfield in the response body.
Next steps
- Go Live — checklist of all error codes you must handle before going to production
- Verify a Bank Account — bank account verification with full error examples
- Verify a Phone Number — phone number verification with country-specific error codes