This page gathers the operational best practices to verify the status of LigdiCash transactions reliably, without overloading the API or leaving orphan transactions behind.
Recommended polling interval
The optimal interval depends on the type of transaction:
| Flow | Recommended interval | Reason |
|---|
| Payin (hosted or direct) | 3 to 5 seconds | Operator confirmation often arrives within seconds after the customer’s action |
| Payout | 30 to 60 seconds | Payouts are processed in batches by the operator — polling too fast is pointless |
Do not go below 3 seconds between two confirm calls. Overly aggressive polling can trigger rate limits on the LigdiCash side and degrade the reliability of your integrations.
Timeouts — when to stop polling
Set a maximum number of attempts rather than an absolute delay: this gives you precise control over the number of API calls generated.
| Flow | Recommended max attempts | Approx. total duration |
|---|
| Payin | 10 to 15 | 40 to 75 seconds |
| Payout | 10 | 5 to 10 minutes |
After the timeout, the transaction technically remains pending on the LigdiCash side — it is not cancelled. The callback may still arrive. Apply the following logic:
- Mark the transaction as
expired in your database (application-level status, not LigdiCash).
- Inform the user that the processing is in progress and that they will be notified.
- Keep listening for the callback — if it arrives, re-verify with
confirm and update.
Hybrid strategy — primary callback + fallback polling
1. Create the transaction → store the token and status = "pending"
2. Configure a callback_url reachable from the internet
3. On callback receipt:
→ Call confirm with the creation token
→ Update your database
4. If the callback does not arrive after 2 minutes:
→ Trigger a fallback polling (async job)
→ 10 attempts, every 5 seconds
5. If polling timeout:
→ Mark "expired" in the database
→ Keep processing the callback if it arrives late
Trigger the fallback polling from a background job (cron, queue worker) — not from the initial HTTP request thread. This avoids blocking the user during the wait.
Handling pending transactions
A transaction stays pending until the operator has made its final decision. Several situations explain a prolonged pending:
- Approval mode (Moov Africa) — the customer must confirm on their mobile app, which can take several minutes.
- Expired OTP — the customer did not enter the OTP in time. The transaction will stay
pending then move to notcompleted after expiration.
- Operator network congestion — rare but possible during traffic spikes.
- Payout awaiting funds — if the merchant account balance is insufficient at the moment of initiation.
For every transaction still pending after your polling timeout, keep the token in the database and schedule a deferred re-verification (e.g. +30 min, +2h, +24h) before considering it definitively lost.
JavaScript — deferred re-verification
async function reCheckExpiredTransaction(token) {
const res = await fetch(
`https://app.ligdicash.com/pay/v01/redirect/checkout-invoice/confirm?token=${token}`,
{
headers: {
Apikey: process.env.LIGDICASH_API_KEY,
Authorization: `Bearer ${process.env.LIGDICASH_API_TOKEN}`,
Accept: "application/json",
},
}
);
const data = await res.json();
if (data.status === "completed") {
await updateOrder(token, "paid");
} else if (data.status === "notcompleted") {
await updateOrder(token, "failed");
}
// If still "pending", leave the scheduled job for the next check
}
Related pages