An OTP SMS is a text message carrying a one-time password — a short code, usually 4 to 6 digits, valid for a few minutes and usable once — that a person types back into your application to prove they hold the phone. It is the most common form of two-factor authentication (2FA) in Zambia because it works on every handset.
Where OTPs are used
- Login verification — a second factor after the password, or a passwordless login where the code is the credential.
- Transaction approval — confirming a transfer, a withdrawal or a change of payout details in banking, microfinance and mobile money.
- Phone number verification — proving a new customer's number is real before an account is activated.
- Sensitive changes — confirming a password reset, a new device, or a change of contact details.
How OTP over SMS works
- Your application generates the code — random, short-lived, stored server-side with the phone number, a timestamp and an attempt counter.
- Your application sends it with one call to the Ontech BulkSMS send API (or a submit over an SMPP bind). The response returns a message ID.
- The gateway delivers it to MTN, Airtel or Zamtel based on the number prefix, from your approved sender ID.
- The user types the code back, and your application compares it with the stored value, checks expiry and attempts, and lets the action proceed.
- The delivery report for the message ID confirms whether the handset received it — useful for support and for deciding when to offer a resend.
Sending an OTP from your code
# Python — send the code you generated
import requests
r = requests.get("https://bulksms.ontech.co.zm/smsservice/httpapi", params={
"api_key": "YOUR_ACCESS_ID",
"phone": "260970000000",
"sender_id": "YOURBRAND",
"msg": "Your YOURBRAND code is 481920. Valid for 5 minutes. Do not share it.",
})
message_id = r.json().get("message_id") # {"status": 100, "message": "Success", "message_id": "…"}
# later — did it arrive?
s = requests.get("https://bulksms.ontech.co.zm/smsservice/status",
params={"api_key": "YOUR_ACCESS_ID", "message_id": message_id})
print(s.json()["delivery_status"]) # delivered | failed | rejected | queued | submitted
Keys are IP-whitelisted, and API requests are limited to 60 per minute per account, so poll status only when you need it — or register a callback URL and let delivery reports come to you. Note the platform's duplicate guard: an identical message to the same number within three minutes is suppressed, so a "resend" must carry a new code (or at least different text) to go out. See the API reference.
Designing a good OTP flow
- Keep the message short and recognisable. Brand name, the code, the validity, a warning not to share. Put the code early so it shows in the notification preview.
- Use a branded sender ID. Customers are rightly suspicious of codes from unknown numbers. Sender IDs are up to 11 characters and are approved on a signed authorization letter.
- Set a short validity — five minutes is typical — and limit attempts to stop guessing.
- Offer a resend, but rate-limit it, and check the delivery report before the user assumes it was lost.
- Handle the failed state. If the report says failed or rejected, tell the user and offer an alternative (a call, another number) rather than an endless spinner.
- Log the message ID against the login or transaction so support can answer "was the code sent?" with evidence.
OTP delivery speed and reliability
An OTP is only useful if it arrives before the user gives up. Ontech BulkSMS submits messages to the carrier within seconds of the API call; from there, delivery time depends on the network and on whether the handset is reachable. Every message returns a delivery report, so you can monitor the delivered rate per network in your dashboard and see problems as they happen rather than from complaints. For continuous authentication traffic, an SMPP transceiver bind gives the lowest latency and returns receipts on the same connection.
OTP in Zambian financial services
Banks, microfinance institutions and mobile money agents are the heaviest OTP senders in Zambia: a code for every login, every transfer above a threshold, every payout change. The banks and MFIs guide covers the wider set of transactional messages those institutions send — balance alerts, repayment reminders, collections — and how they integrate over API or SMPP with audit-ready delivery records.