Errors
There are two different kinds of “error” to handle: the API call itself failing, and a transaction completing with a non-success status. They look nothing alike, and only the first one is a bug in your integration.
The error response
Section titled “The error response”Failed requests return a JSON body with this shape:
{ "timestamp": "2026-09-01T10:32:14.000+00:00", "message": "Currency code should be provided", "description": null, "status": "400"}| Field | Type | Description |
|---|---|---|
timestamp | string | When the error occurred |
message | string | What went wrong. This is the field to log and show your team |
description | string | Extra detail. Usually null; carries the per-field list for validation failures |
status | string | The HTTP status code, as a string |
HTTP statuses
Section titled “HTTP statuses”| Status | What it means | Example message | What to do |
|---|---|---|---|
400 | The request was rejected — bad field, failed validation, or a payload that decrypted into something that isn’t valid JSON | Payload was decrypted but did not produced a valid json representation; Currency code should be provided; Invalid Ecocash phone number supplied | Fix the request. These are integration bugs, not transient failures — don’t retry unchanged |
401 | Authentication failed | Invalid username or password | Check the credentials you’re using |
403 | Your integration key was rejected, or no payment method is available | Integration key for the application is not valid (Not active or disabled); No payment method that supports {currency} is available at the moment | Confirm the key is for the right environment and still active — see API keys |
404 | The record you asked for doesn’t exist | Lookup misses, e.g. an unknown referenceNumber | Check the reference number you’re sending |
406 | The operation isn’t allowed in the transaction’s current state | — | Re-check the transaction’s status before retrying the operation |
500 | Something failed server-side, including decryption failures and downstream service errors | Failed to decrypt your data | If it mentions decryption, check your encryption key and IV rule. Otherwise retry once, and contact support with the referenceNumber if it persists |
Validation errors
Section titled “Validation errors”Field validation failures come back as 400, and multiple problems are
joined into a single message separated by ; — so parse the whole
string rather than assuming one error per response. Real examples:
Invalid Visa Card Number length, its either 13, 16, 19 numbers.;Invalid Credit card expiry date providedEach payment method validates its own fields. See the failure-modes table on the relevant payment method page for what each one rejects.
Transaction-level outcomes
Section titled “Transaction-level outcomes”A request can succeed at the API level — HTTP 200, valid encrypted response
— while the payment itself fails. A declined card and an EcoCash timeout
are both HTTP 200. Read transactionStatus in the decrypted response, not
the HTTP status:
SUCCESSis the only status that means you were paid.DECLINED,INSUFFICIENT_FUNDS,AUTHORIZATION_FAILED,TIME_OUT, andCANCELLEDare normal, expected outcomes your UI should handle gracefully.- Non-terminal statuses (
PENDING,PROCESSING,PARTIALLY_PAID) mean the payment is still in flight — keep checking.
See Transaction statuses for the full list with numeric codes.
transactionStatusDescription on a failed transaction often carries text
straight from the payment provider (EcoCash, the card issuer, and so on).
It’s useful to log and sometimes useful to show the customer, but it isn’t
a stable value to branch on.