API Reference
Verify a Payment
Mobile-money collections are often asynchronous — the payer approves the charge on their phone moments after you initiate it. Use this endpoint to check where a transaction stands at any time.
1POST /api/v1/payment/verify
The switch looks up the transaction, asks the same provider that processed it
for the latest status, saves it, and returns the normalised result. If the
transaction has settled and you supplied a callback_url
when initiating it, the switch also notifies that URL — see
Callbacks below.
#Authentication
Required. Send your API token as a Bearer token — see Authentication.
#Request body
| Field | Type | Rules | Description |
|---|---|---|---|
transaction_id |
string | required | The transaction_id returned by Request a Payment. |
#Example request
1curl -X POST https://your-domain.com/api/v1/payment/verify \
2 -H "Authorization: Bearer YOUR_API_TOKEN" \
3 -H "Content-Type: application/json" \
4 -H "Accept: application/json" \
5 -d '{
6 "transaction_id": "9b6c2f1e-2a4d-4c7e-9f3a-1b2c3d4e5f6a"
7 }'
#Response
200 OK — verification always returns HTTP 200 because the request itself
succeeded. The top-level status mirrors the transaction's real outcome
(success, failed, or pending) — it is not a generic "the API call
worked" flag — so you can branch on it directly.
A successful payment:
1{
2 "status": "success",
3 "message": "Transaction completed successfully",
4 "data": {
5 "transaction_id": "9b6c2f1e-2a4d-4c7e-9f3a-1b2c3d4e5f6a",
6 "reference": "lenco_ref_abc123",
7 "status": "success",
8 "provider_status": "successful",
9 "amount": 50.0,
10 "currency": "ZMW"
11 }
12}
A failed payment (note the top-level status is failed, not success):
1{
2 "status": "failed",
3 "message": "Transaction failed",
4 "data": {
5 "transaction_id": "9b6c2f1e-2a4d-4c7e-9f3a-1b2c3d4e5f6a",
6 "reference": "lenco_ref_abc123",
7 "status": "failed",
8 "provider_status": "failed",
9 "amount": 50.0,
10 "currency": "ZMW"
11 }
12}
A pending payment (still awaiting the payer / provider):
1{
2 "status": "pending",
3 "message": "Transaction is still pending",
4 "data": { "status": "pending", "provider_status": "pay-offline", "...": "..." }
5}
| Field | Description |
|---|---|
status (top-level) |
The transaction's normalised outcome: success, failed, or pending. Branch on this. |
message |
A human-readable summary of the outcome. |
data.status |
The same normalised status (mirrors the top-level status). |
data.provider_status |
The raw status string from the provider (e.g. Lenco's successful, pay-offline). |
data.reference |
The provider's reference for the transaction. |
A genuine error (e.g. the provider can't be reached, or the transaction isn't found) is different — those return
status: "error"with a4xx/5xxcode, soerroralways means "verification failed", never "the payment failed".
#Status mapping
The switch normalises each provider's statuses onto three states, so your
integration only ever deals with success, failed, or pending:
| Switch status | Lenco statuses |
|---|---|
success |
successful |
failed |
failed |
pending |
pending, pay-offline, 3ds-auth-required |
#Errors
| Status | message |
Meaning |
|---|---|---|
404 |
Transaction not found |
No transaction with that transaction_id belongs to your account. |
422 |
The provider for this transaction is no longer available |
The driver that created the transaction is missing. |
4xx/5xx |
(provider message) | The provider could not be reached or returned an error. |
#Callbacks
If a transaction was created with a callback_url, the switch delivers the final
result to that URL once — the first time verification finds the transaction
in a settled state (success or failed). Pending checks never fire a callback.
The callback is an HTTP POST with this JSON body:
1{
2 "transaction_id": "9b6c2f1e-2a4d-4c7e-9f3a-1b2c3d4e5f6a",
3 "reference": "lenco_ref_abc123",
4 "status": "success",
5 "amount": 50.0,
6 "currency": "ZMW",
7 "provider": "Lenco"
8}
Notes:
- Delivery is queued and retried (up to 3 attempts with backoff), so make
your endpoint idempotent — key off
transaction_id. - A transaction is notified at most once; repeated verification of an already-settled, already-notified transaction will not re-send the callback.
- Respond with a
2xxstatus to acknowledge receipt.