API Reference
Responses & Errors
Every API response — success or failure — uses the same JSON envelope, so your client can parse them uniformly.
#The response envelope
1{
2 "status": "success | failed | pending | error",
3 "message": "Human-readable description",
4 "data": {}
5}
| Field | Description |
|---|---|
status |
The outcome — one of success, failed, pending, or error (see below). |
message |
A human-readable summary of the result. |
data |
Result payload (object); usually an empty array on error. |
#Top-level status values
The top-level status describes the outcome, not merely whether the HTTP
request worked. This is the single most important field to branch on.
status |
HTTP | Meaning |
|---|---|---|
success |
200 |
The call succeeded — a payment was initiated, or a verified transaction is successful. |
failed |
200 |
Returned by verification: the payment itself failed at the provider. The API call worked. |
pending |
200 |
Returned by verification: the payment has not settled yet (awaiting the payer / provider). |
error |
4xx / 5xx |
The API call could not be completed — bad auth, validation, no eligible provider, or the provider was unreachable. Never means "the payment failed". |
Key distinction: a failed payment is
status: "failed"with HTTP200(verification reached the provider and the payment was declined). Anerrormeans the request itself failed. Don't treaterroras a declined payment.
#Success
200 OK — the payment was initiated by a provider:
1{
2 "status": "success",
3 "message": "Payment request initiated successfully",
4 "data": {
5 "transaction_id": "9b6c2f1e-2a4d-4c7e-9f3a-1b2c3d4e5f6a",
6 "reference": "lenco_ref_abc123"
7 }
8}
#Failed & pending (verification)
Only the verification endpoint returns failed or
pending — both with HTTP 200, because the verification call succeeded:
1{
2 "status": "failed",
3 "message": "Transaction failed",
4 "data": { "status": "failed", "provider_status": "failed", "...": "..." }
5}
1{
2 "status": "pending",
3 "message": "Transaction is still pending",
4 "data": { "status": "pending", "provider_status": "pay-offline", "...": "..." }
5}
#Errors
| Status | Example message |
Meaning |
|---|---|---|
401 |
Unauthorized |
Missing Bearer token. |
401 |
Invalid API token |
Token does not match any account. |
422 |
The amount field is required. |
Validation failed for amount, account_number, or country. |
400 |
Providers not configured yet. Please configure at least 1 (one) provider |
Your account has no providers. |
400 |
No active providers support the requested country |
No active provider serves the requested country. |
400 |
Unsupported mobile operator |
The account number didn't map to a supported operator (provider-level). |
4xx |
(provider message) | The provider that processed the request returned an error; the switch surfaces the last provider error after fallback. |
500 |
No provider could process the payment request |
Every eligible provider failed. |
#Validation errors (422)
Validation responses include an errors object alongside the envelope:
1{
2 "message": "The country field must be 2 characters.",
3 "errors": {
4 "country": ["The country field must be 2 characters."]
5 }
6}
#Handling fallback in your client
Because the switch tries providers sequentially, a non-200 response means all eligible providers were exhausted (or the request was rejected before routing). Recommended client handling:
200— recordtransaction_idandreference; reconcile via verification.400/422— fix configuration or input; retrying unchanged won't help.401— refresh or correct your API token.500— safe to retry after a short backoff; a provider may recover.
When verifying, branch on the top-level status field instead of the HTTP
code (which is 200 for success, failed, and pending alike): treat
success / failed as final and keep polling while pending.
Always send the
Accept: application/jsonheader so error and validation responses are returned as JSON.