For OTP in Zambia, send codes from a registered alphanumeric sender ID that carries your app's name, keep the brand in the message text, and use a managed verification API so code generation, expiry and resend limits are handled for you. eSMS Verify does this with two calls, start and check, and the same account sends payment receipts and alerts through the SMS API. This guide covers sender IDs, routing, fallbacks and a working code sample.

Last reviewed: 27 October 2026

What makes OTP different in Zambia

Zambian fintech apps sit on top of a mobile money market where Airtel Money, MTN MoMo and Zamtel Kwacha are household names. Your customers are used to receiving instant SMS from their wallet provider, so a code that takes a minute to arrive, or arrives from an unknown number, looks suspicious. Three local factors drive that experience.

  • Sender ID rules. Networks do not support numeric senders, reject generic names such as OTP or VERIFY, and MTN is widely reported to check message content against the approved use. An unregistered sender may be replaced with a number.
  • Three networks. Your users are spread across Airtel, MTN and Zamtel, and many carry more than one SIM. Delivery needs to work on all three.
  • Regulation of e-money. The Bank of Zambia supervises e-money issuers, issued e-money directives in 2023, and in September 2024 directed issuers to stop charging for wallet deposits, balance enquiries, failed transactions and some other items. Receipts and notices must not suggest those charges apply.

Sender IDs for fintech OTP

Register your app or company name, up to 11 characters, before launch. Register the OTP and alert use case with sample messages, and if you also plan marketing, register a second sender ID for it. Our article on MTN Zambia sender ID whitelisting explains why mixing promotions into an OTP sender causes problems. The Zambia sender ID page lists the steps and fee. While approval is in progress you can build and test on the eSMS default sender.

Write the OTP for humans and filters

Your KwachaPay code is 482913. It expires in 5 minutes. KwachaPay staff will never ask for this code.

  • Brand first, so the user and the network see who it is from.
  • Code early in the message, so it shows in the notification preview.
  • A warning against sharing, because social engineering is the most common way codes are stolen.
  • No links and no marketing in OTP messages.

Routing and delivery

eSMS Africa has direct routes to the main Zambian networks and returns delivery reports (DLRs) for every message by webhook and in the dashboard. For OTP, watch three things:

  1. Time to deliver. Log when you requested the code and when the DLR says it was delivered. Spikes on one network tell you where to look.
  2. Failure codes. A number that is switched off, out of coverage or not in service fails differently from a sender ID problem. See how to receive delivery reports.
  3. Conversion. The share of started verifications that are checked successfully is the number that matters to your business.

Integration: eSMS Verify plus receipts

Verify generates the code, sends it, enforces expiry and rate limits, and checks what the user types. You never store codes. Use the SMS API for receipts and alerts on your own sender ID. Test keys (esms_test_...) simulate sends without charge.

cURL

curl -X POST https://sms.esmsafrica.io/v1/verify/start \
  -H "Authorization: Bearer esms_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to": "+260971234567", "app_id": "vera_YOUR_APP"}'

# response contains a verification_id; then:
curl -X POST https://sms.esmsafrica.io/v1/verify/check \
  -H "Authorization: Bearer esms_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"verification_id": "VERIFICATION_ID", "code": "482913"}' 

Node.js

const API = 'https://sms.esmsafrica.io';
const headers = {
  Authorization: `Bearer ${process.env.ESMS_KEY}`,
  'Content-Type': 'application/json'
};

// 1. Start a verification when the user enters their number
export async function startOtp(phone) {
  const res = await fetch(`${API}/v1/verify/start`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ to: phone, app_id: process.env.ESMS_APP_ID })
  });
  if (!res.ok) throw new Error(`verify start failed: ${res.status}`);
  return res.json(); // keep verification_id in the user's session
}

// 2. Check the code the user typed
export async function checkOtp(verificationId, code) {
  const res = await fetch(`${API}/v1/verify/check`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ verification_id: verificationId, code })
  });
  return res.json();
}

// 3. Payment receipt on your own sender ID
export async function sendReceipt(phone, amount, ref) {
  await fetch(`${API}/api/messages/send`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      to: phone,
      sender_id: 'KwachaPay',
      text: `KwachaPay: You paid ZMW ${amount}. Ref ${ref}. No fee charged.`
    })
  });
}

Full parameters are in the Verify documentation and the send OTP SMS guide.

Fallbacks that keep sign-ups moving

No channel delivers every time. Plan for the user who does not get the code.

SituationFallback
No code after 30 to 60 secondsShow a resend button; Verify rate-limits repeat requests
User has two SIMsShow the number the code was sent to and offer "change number"
Repeated failures on one numberOffer email verification or a support contact
High-value action on a new deviceRequire OTP plus a second factor such as a PIN or device check

Security: SIM swap and pumping

  • SIM swap. An SMS code proves control of a number, not of the person. For withdrawals, limit changes and new devices, combine OTP with device binding or a PIN, and send an alert to the old device when a new one is added.
  • SMS pumping. Fraudsters trigger thousands of OTPs to numbers they profit from. Verify's per-number rate limits help; also add a CAPTCHA or a device check before starting verification, and alert on unusual volumes.
  • Logs and data. Phone numbers and verification logs are personal data under the Data Protection Act No. 3 of 2021. Keep them only as long as fraud checks require and register with the Data Protection Commissioner if you are in scope.

Cost

An OTP is billed like any SMS to a Zambian number, from ZMW 0.2101 ($0.0104) on pay as you go, with lower rates on volume tiers. Fewer wasted resends, thanks to rate limits, matter more to your bill than the unit price. Live rates are on the pricing page.

Go-live checklist

  1. Sender ID approved on all three networks, with sample OTP and receipt messages that match what you send.
  2. Live key stored as a secret, never in the mobile app itself. Calls to Verify should come from your backend.
  3. Delivery report webhook connected and logged, with alerts when failure rates jump on one network.
  4. Resend button with a visible countdown, and a fallback path for users who still do not receive a code.
  5. CAPTCHA or device check in front of the start call to limit pumping.
  6. Receipt templates reviewed against Bank of Zambia guidance on charges, so no message suggests a fee that is not allowed.
  7. Data retention period set for phone numbers and verification logs.

Run the whole flow with a test key first, then switch the key and send a handful of live codes to staff phones on Airtel, MTN and Zamtel before launch.

Frequently asked questions

Can I use OTP or VERIFY as my sender ID in Zambia?

No. Zambian networks reject generic sender IDs because anyone could use them. Register your app or company name, up to 11 characters, and put the brand in the message text as well.

Do I need eSMS Verify or can I use the SMS API for codes?

Either works. The SMS API is fine if you already generate and check codes yourself. Verify saves you building expiry, rate limiting and checking, and keeps codes out of your database.

Do OTP messages follow the 20:00 to 07:00 promotional limit?

No. The 2011 ZICTA directive covered promotional SMS. OTPs and transaction alerts are transactional and should be sent immediately at any hour.

How do I test without paying for messages?

Use a test key beginning with esms_test_. It simulates sends and delivery reports without charge, so you can build the whole flow before switching to a live key.

Sources

See more fintech flows on our mobile money and fintech page for Zambia, the OTP SMS Zambia page and the SMS API for Zambia. Create a free account and get your test key in minutes.