All posts

The Sailup team · · 11 min read

SMS OTP vs Authenticator Apps vs Email Codes: Which Should a Ghanaian App Use?

SMS codes reach every phone in Ghana and cost ₵0.02 each. Authenticator apps resist SIM swaps but need a smartphone. Email codes suit address checks and recovery, not sign-in. How to pick per action.

There is no universal winner. The right verification channel depends on two things: how much damage a wrong approval does, and which phone the person on the other end is actually holding. For most Ghanaian apps that works out as SMS codes by default, because they reach every handset on MTN, Telecel and AirtelTigo with nothing to install and no data bundle; an authenticator app for staff and for customers who opt in; and email kept for confirming addresses and recovering accounts. Below is the honest case for each channel, and a matrix you can apply action by action.

The four channels at a glance

Sailup only sends SMS, so we have a stake in one row of this table. We have tried to be fair to the other three.

ChannelDevice neededWorks with data offPhishing resistanceSIM-swap resistanceFriction for the userGhana reachCost per verification
SMS codeAny phone with a SIMYesModerateNoneLowEvery active SIM₵0.02
Authenticator app (TOTP)Smartphone with the app installedYes, once enrolledModerateStrongHigh at setup, low afterSmartphone users who finish setup₵0
Email codeAnything with an inboxNoLow to moderateStrongMediumUsers who check email on their phoneYour email provider's rate
Passkey or push approvalRecent smartphone with your app, or a passkey-capable browserPush no, passkey yesStrongStrongVery low after enrolmentUsers with your app on a recent phone₵0

Two clarifications on the table. TOTP resists SIM swap because the secret lives on the handset rather than on the number, but a real-time phishing page can still relay a code inside its 30-second window, which is why it scores the same as SMS on phishing. Only passkeys bind the credential to your domain, so a lookalike site gets nothing.

SMS codes: the widest reach, one real weakness

An SMS code works on the feature phone Adwoa keeps in her apron at Kejetia market and on the flagship Kwame carries in East Legon. There is nothing to install and no data required, and the user already knows what to do with it because their bank and their MoMo wallet have been sending them codes for years.

It is also more effective than its reputation. Google's 2019 account-hijacking research found that a code sent by SMS blocked 100% of automated bots, 96% of bulk phishing attacks and 76% of targeted attacks. For ₵0.02 a message, that is a great deal of protection.

The weakness is SIM swap. If an attacker persuades a carrier agent, or pays one, to move your customer's number onto a new SIM, every code you send now lands in the attacker's hand. That is an expensive, targeted attack, so it is aimed at accounts worth the effort: a wallet with a large balance, an admin login, a business account. It is the reason SMS should not be the only lock on a high-value action. Two lesser weaknesses are worth knowing. The code travels over a network you do not control, so delivery can lag on a congested cell or fail outright on a phone that has been off for days. And malware on a rooted Android can read incoming SMS, though that is rare next to SIM swap.

On cost, OTP messages are single-segment by design, so 10,000 verifications a month is ₵200 on Sailup, plus resends. The developer OTP guide covers message copy, sender IDs and delivery handling, so we will not repeat it here.

Authenticator apps: the strongest code, the highest setup cost

A TOTP app (Google Authenticator, or the one built into a password manager) holds a secret you gave it once through a QR code and derives a six-digit code from that secret and the current time. Nothing travels over the network when a code is generated, so there is no SIM to swap and no message to intercept, and the code costs you nothing.

The costs are all at the edges. The user needs a smartphone and needs to install an app, then scan a QR code, then type the first code back to prove it worked. Each of those steps loses people, and the ones it loses are disproportionately the customers on cheaper phones. Then there is recovery. When the phone is lost or wiped, the secret goes with it, so you need backup codes the user was supposed to write down, or a fallback channel. The fallback is nearly always SMS or email, which means an account protected by TOTP is, at recovery time, only as strong as the fallback. Design the recovery path before you ship the app step, not after the first locked-out customer emails you.

Where TOTP fits without argument: staff logins, the merchant back-office, your own developer dashboard, and any customer who asks for it in settings.

Email codes: right for addresses and recovery, wrong for sign-in

An email code proves that someone can read a given inbox. That is exactly what you want when confirming an address at signup, when sending a password reset, or when a desktop web app wants to log someone in who is already sitting in their inbox.

It is the wrong choice for signing into a phone-first product in Ghana. Email delivery is measured in seconds on a good day and minutes on a bad one, and the message often lands in a Promotions tab or a spam folder the user never opens. It proves nothing about the phone, which matters when the phone number is the account. And for a large share of users the number is the identity they actually maintain; the email address on file was typed once at signup and may not be checked from that phone at all. There is also a circular problem: most email accounts are themselves recovered by an SMS to a phone, so the chain of trust ends at the SIM anyway.

Sailup does not send email. If your recovery flow needs it, use your email provider for that leg and keep SMS for the phone leg.

Passkeys and push approval: excellent when your app is installed

Push approval means your app receives a notification and the user taps Approve on the device that is already logged in. A passkey is a WebAuthn credential bound to your domain; the browser or phone only answers a challenge from the site that created it, so a lookalike domain gets nothing. Both are as strong as it gets for the everyday case, and both cost you nothing per use.

The limits are practical. Push needs data at the moment of login. Passkeys need a recent phone or browser and a user who understood the enrolment prompt. Both die with the device, so the recovery flow, once again, comes back to SMS or email. In Ghana that makes them a step-up for your engaged smartphone users rather than a replacement for the channel that reaches everyone.

The Ghana reality

NCA figures for Q4 2025 put mobile voice subscriptions at 42.87 million, split 72.92% MTN, 20.17% Telecel and 6.91% AT. Every one of those SIMs can receive a text. Not all of them sit in a smartphone, and plenty of the ones that do spend the working day with data switched off to make a bundle last. A verification channel that needs an app or a live data connection reaches a subset; SMS reaches the whole set.

Mobile money settles the argument for a whole class of products. A MoMo wallet is a phone number. If your app tops up or cashes out a MoMo wallet, the number is both the identity you are checking and the channel you check it on, and the customer expects the code to arrive as a text because that is how every other wallet interaction works. Sailup reaches all three networks through one endpoint at the same ₵0.02 flat rate, with no per-carrier contract; the pricing page has the detail.

Which channel for which action

The matrix below is how we would set it up for a Ghanaian product. The expiry column is Sailup's recommendation, not a standard, and all of it sits well inside the 10-minute ceiling that NIST SP 800-63B sets for codes sent out of band.

ActionWhat a wrong approval costsPrimary channelStep-up or fallbackCode expiry
Mobile money or wallet action (top up, cash out, link a number)Money leaves the accountSMS to the registered numberPasskey, push or TOTP above a value you choose3 min
E-commerce checkout, pay on deliveryA rider sent to a wrong numberSMSResend after a cooldown, then a phone call from your team5 min
Consumer app or SaaS signupFake accounts and spamSMS for a phone-first product; email code for an email-first oneConfirm the other identity later, not at signup10 min
Admin or back-office loginYour whole customer baseTOTP or passkey, requiredBackup codes; SMS only with a second person approving30 s (TOTP window)
High-value transfer, or changing the registered phone numberAccount takeoverPasskey, push or TOTPSMS plus a cooling-off delay and a notice to the old number3 min
Account recoveryAttacker gets everythingEmail code and SMS to the registered number, bothManual review with ID10 min

The pattern in the table: the more an action is worth to an attacker, the less you should rely on a channel that depends on the phone number alone, and the more you should ask for something bound to the device.

Layering without over-building

Three rules keep this from turning into a project.

  1. SMS is the default for every customer-facing action. It is the one channel you can be confident reaches the user, so it is the base layer everything else sits on.
  2. TOTP is opt-in for customers and required for staff. Do not force enrolment on the whole base. Every mandatory QR-code step costs you customers who were happy with a text.
  3. Email does email things. Address confirmation and password resets. Not sign-in on a phone-first product.

And one principle: step up, do not stack. Asking for an SMS code and an email code on the same login doubles the chance the user abandons and doubles what you pay, without making the login meaningfully harder to break. Ask for the stronger channel when the action gets riskier, not for two weak ones at once.

Implementation notes for the SMS leg

Sailup gives you the send. The verification logic is yours: we have no built-in OTP or verification service, no code generation, and no rate limiting on your behalf. Here is what belongs in your code.

  • Expiry. Five minutes for sign-in, three for anything that moves money. Enforce it on the server from a stored timestamp; a countdown in the UI is decoration.
  • Limits. Cap wrong guesses per code, resends per number and requests per IP, and invalidate the code the moment it verifies. An open OTP endpoint is a way for someone else to spend your balance, so a cooldown of 30 to 60 seconds between resends, a cap of a few sends per number per hour and five wrong guesses per code are the minimum.
  • Message. Code first, brand name, expiry, no link, one GSM-7 segment. The OTP guide has the template.
  • Sender ID. Register your brand name weeks before launch; carriers take one to three business days and reject generic names. The sender ID post lists the rules.
  • Delivery. Sailup fires delivery webhooks on terminal outcomes only: delivered, failed, expired, rejected. When you receive a failure, offer the fallback then, rather than leaving the user tapping resend against a phone that is off.
  • Fallback. Sailup does not offer voice codes or email, so the fallback for a failed SMS is a resend after the cooldown, then whichever second channel you have built: TOTP if the user enrolled, or an email code through your email provider.

If you are deciding today, start with SMS for everything customer-facing, add TOTP for staff, and keep email for recovery. The OTP guide has the send call and the message template, and an account is free.

Frequently asked questions

Is SMS OTP still secure enough to use in 2026?

For most consumer actions, yes. Google's 2019 research found an SMS code blocked 100% of automated bots, 96% of bulk phishing and 76% of targeted attacks. Its known weakness is SIM swap, which is a targeted and expensive attack. Use SMS as the default and add a device-bound factor such as a passkey or an authenticator app for high-value actions like large transfers or changing the registered number.

Why do banks and mobile money services in Ghana still send SMS codes?

Because SMS is the only channel that reaches every active SIM. NCA figures for Q4 2025 count 42.87 million mobile subscriptions across MTN, Telecel and AT, many of them on feature phones or on smartphones with data switched off. A mobile money wallet is also a phone number, so the number is both the identity being checked and the channel that checks it.

Should my app use an authenticator app instead of SMS?

Use both, in different places. Require an authenticator app (TOTP) for staff and admin logins and offer it as an opt-in for customers. Keep SMS as the default for customer sign-in, because TOTP needs a smartphone, an app install and a QR-code step that loses users, and because a lost phone takes the secret with it and pushes recovery back onto SMS or email anyway.

Can I use an email code for login instead of SMS?

You can, but on a phone-first product it is the weaker choice. Email is slower, often lands in spam or a Promotions tab, and proves nothing about the phone. Email codes are the right tool for confirming an address at signup and for account recovery. If the product is email-first and mostly used on a desktop, an email code or magic link for login is reasonable.

How much does SMS OTP cost in Ghana?

On Sailup an SMS costs ₵0.02 to any Ghanaian network, billed per 160-character segment, with no monthly fee. A one-time code fits in one segment, so 10,000 verifications cost ₵200. Budget on total sends rather than unique users, since every OTP flow has resends. Authenticator apps and passkeys cost nothing per code but need a smartphone and an enrolment step.

What should happen when the SMS code does not arrive?

Let the user request a resend after a cooldown of 30 to 60 seconds, and listen for the delivery webhook so you know when the carrier has actually failed the message. Then offer whatever second channel you have built, such as an authenticator app the user enrolled in or an email code through your email provider. Sailup sends SMS only, so the fallback lives in your code.

Send your first SMS in five minutes.

No setup fees, no contracts — pay only for what you send, and volume discounts when you scale.