Skip to main content
This checklist covers the critical items to validate before opening your integration to end customers. Go through it in order — each section builds on the previous one.

Security

The Apikey and Auth Token must not appear in browser JavaScript, in a mobile app, or in a public Git repository.
  • Server-side environment variables only (process.env, .env not committed)
  • .gitignore includes the .env file
  • No key in application logs
  • No key in API responses returned to the frontend
Never trust the payload received in the callback — it can be forged. Always call /confirm with the token stored at creation.
  • The callback handler calls /checkout-invoice/confirm before any business action
  • The token used for confirm is the one stored at creation (not the callback token)
  • A malformed payload or one with an unknown transaction_id is silently ignored
  • See Callback security
LigdiCash must be able to reach your callback endpoint from the internet.
  • URL reachable from an external IP (not localhost or a private IP)
  • HTTPS recommended (HTTP accepted by LigdiCash but discouraged in production)
  • No firewall rule blocking LigdiCash IPs
  • If whitelisting is required: contact LigdiCash support for the IPs to allow (max 3 IPs per project)
A sequential transaction_id (1, 2, 3, etc.) lets an attacker enumerate your transactions.

Technical

  • customer is empty ("") in every hosted payin example
  • cancel_url points to the cancellation page, return_url to the success page (not swapped)
  • The payment URL opens in the same tab, a new tab, or a popup — never in an iframe
  • The frontend verifies the real status via the backend after returning to return_url (the redirect is not proof of payment)
  • external_id and otp are empty ("") in requests where they are not used
  • The authentication mode (USSD OTP / SMS / Approval) is correctly documented in the UX for each operator
  • For SMS OTP mode: the initial request is submitted with otp: "", then resubmitted with the received OTP
  • For Approval mode (Moov): the callback is the only confirmation — no insufficient polling
  • The handler is idempotent (two calls with the same transaction_id only execute the business logic once)
  • Both callback formats are handled (application/json and application/x-www-form-urlencoded)
  • See Callback idempotency and Parse custom_data
  • The transaction is created in the database before the LigdiCash call
  • The LigdiCash token is stored as soon as the invoice is created
  • Inbound and outbound logs (LigdiCash requests + received callbacks) are kept
  • See Recommended architecture
  • A periodic job checks transactions stuck in pending for more than a few minutes
  • Polling stops after a reasonable delay (e.g. 24h) — transactions never automatically flip to notcompleted
  • Polling uses the token stored at creation, not a token from the callback

Payout (if applicable)

  • The recipient has a LigdiCash account (required for /withdrawal/create)
  • The semantics of top_up_wallet are correctly implemented: 1 = funds in the wallet, 0 = automatic transfer to the linked mobile money account
  • The phone number is in 22670XXXXXXX format (no +, no spaces)
  • The /straight/payout endpoint is used (not /withdrawal/create) for recipients without a LigdiCash account

Business and operations

  • The LigdiCash merchant account is active and verified (KYC completed)
  • The API project is in production mode (not a test account)
  • The operators you need are enabled on the API project (check in the dashboard)
  • Visa enabled separately if you need it (specific contract)
  • Every LigdiCash error code is mapped to a user-readable message
  • The user is clearly informed if their payment fails, with an invitation to retry
  • See Common errors
  • Your callback_url has been tested under real conditions
  • You have a LigdiCash integration Microsoft Teams group for production emergencies
  • If IP whitelisting is required: your server IPs have been sent to LigdiCash technical support

Pre-production testing

Before going live, run at least one end-to-end test for each flow you’re integrating.
LigdiCash does not have a separate sandbox environment. Tests are performed with a real test account provided by the LigdiCash team during the integration period. Contact developper@ligdicash.com to obtain test access.