To send an OTP SMS in Kenya, normalise the number to +254 format, generate a random code, send it through an SMS route that Kenyan networks accept, and verify what the user types within a short window. Each step has details that decide whether codes arrive and whether the flow is secure. This guide walks through them in order, and ends with what to do when the message does not arrive.
The advice is general engineering practice plus public information. Sender ID rules and network behaviour change, so confirm local requirements with your provider and the regulator before launch.
Step 1: normalise the phone number
Kenyan mobile numbers start with the country code +254 followed by nine digits. Users type them in several ways: 0712 345 678, 0112 345 678, 254712345678 or +254712345678. If you send to the wrong format, the message may fail or go to the wrong place.
- Strip spaces, dashes and brackets
- Convert a leading 0 to +254
- Add the + if the number starts with 254
- Check that nine digits follow +254
- Store and send one canonical format, such as E.164
- Reject numbers that do not parse, with a clear message
Doing this before you send saves cost, because you do not pay to attempt numbers that cannot receive a message.
Step 2: decide how you will send
You need an SMS route. The main options are a messaging platform, a local SMS provider, or a verification API.
- A messaging platform or local provider delivers the message, and you write the code logic
- A verification API generates, delivers and checks the code for you
Whichever you choose, ask how it handles Kenyan networks, what sender name recipients will see, and what is billed when a message fails.
Step 3: understand the sender ID
An SMS shows a sender name or number. Secondary sources describe Kenyan traffic as needing a registered sender ID linked to a company, with promotional and transactional traffic handled separately on some networks. Registration can take time and cost money, and rules change, so confirm with your provider and the regulator. With Tambua you send from a shared sender ID, so nothing needs registering. With other setups, plan for registration before your launch date.
Step 4: generate the code properly
How the code is made matters as much as how it is sent.
- Use a secure random source, not a clock or counter
- Use at least six digits. NIST guidance sets six as the minimum for out-of-band codes
- Store only a hash of the code, tied to the number and the purpose
- Make the code single use
- Set a short expiry. NIST allows no more than 10 minutes, and many products use less
Step 5: write the message
Keep the message short and clear. Say what the code is for, include the code, and name your product so people recognise it.
- Put the code near the start so it appears in the notification preview
- Do not include links, which can look like phishing
- Add a short line telling people not to share the code with anyone
- Avoid special characters that increase message length and cost
Step 6: send the code
Make the send request from your server, never from the browser, so that keys stay private. Record the result and the time, and keep a reference you can use later to check the code. If the send fails, return a clear error and offer another channel instead of leaving the user waiting.
Step 7: verify the code
When the user enters the code, check it on your server against the stored hash, the expiry and the number of attempts so far. Respond with the same message for wrong, expired and used codes, so you do not leak information. On success, mark the number as verified and discard the code.
Step 8: add limits
Without limits, an OTP endpoint is an easy target.
- Rate limit sends per number and per IP
- Cap wrong attempts per code and lock the number for a time
- Make sure a resend does not reset the attempt count
- Add a country allowlist and a daily spend cap to limit SMS pumping
- Require a CAPTCHA or other challenge before the first send if you see bots
Step 9: plan for failure
SMS can arrive late or not at all. Design for it from the start.
- Show a countdown and a resend button that waits a short cooldown
- Offer another channel, such as WhatsApp or a voice call that reads the code aloud
- Send the same code on every channel so the user only enters one
- Log every attempt with channel, status and cost so you can see patterns
Using the Tambua API
Tambua handles steps 4 to 9 for you. Call POST /v1/otp/send with the phone number and keep the otp_token from the response. When the user enters the code, call POST /v1/otp/verify with the token and the code. If you leave out the channel, your delivery journey runs, for example SMS, then WhatsApp, then voice. Free test keys return the code in the API response, so you can build and test the whole flow without a phone. SMS OTP in Kenya is KES 0.50, and failed attempts are not billed. See the Tambua docs for request and response details.
Test before launch
- Try real Kenyan numbers on the networks your users have
- Test at peak times, not just during quiet hours
- Check late delivery, resend, expiry, wrong code and lockout
- Test a number with no coverage and confirm the fallback works
- Confirm that logs never contain the code
Frequently asked questions
How long should an OTP last? Short enough to limit risk and long enough for slow delivery. NIST allows up to 10 minutes. Many products use a few minutes.
How many digits should the code be? At least six. Longer codes are harder to guess but harder to type.
Why did my OTP SMS not arrive? Common causes are a wrong number format, a filtered sender ID, a slow route, a phone that is off or out of coverage, or handset filtering. A fallback channel covers most of these.
Can I send an OTP over WhatsApp instead of SMS in Kenya? Yes, if your provider supports it. WhatsApp usually needs an approved message template. Many teams use SMS first and WhatsApp as a fallback.