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 HTTP 200 (verification reached the provider and the payment was declined). An error means the request itself failed. Don't treat error as 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 — record transaction_id and reference; 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/json header so error and validation responses are returned as JSON.