How do I send OTP and verification codes by SMS in Uganda?

Updated

Short answer

Generate the code on your server, then send it with one call to the Bulk SMS Uganda API (POST /api/v1/send-sms). Keep the message short and in plain text so it fits in a single 160-character SMS — one credit, UGX 25–40 — and check the delivery status if a user says the code never arrived.

How an SMS OTP flow works

  • The user enters their phone number in your app.
  • Your server generates a random code, stores a hash of it with a short expiry, and sends it by SMS.
  • The user types the code back; your server compares it, then deletes it.

Example in Node.js

// Server side only — never expose your API key in a browser or app bundle.
import crypto from "node:crypto";

export async function sendOtp(phone) {
  const code = crypto.randomInt(100000, 1000000).toString(); // 6 digits
  // Store a hash of `code` with a short expiry (e.g. 5 minutes) before sending.

  const res = await fetch("https://app.bulksmsug.com/api/v1/send-sms", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BULKSMSUG_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      number: phone,
      message: `Your verification code is ${code}. It expires in 5 minutes. Do not share it.`,
    }),
  });

  const data = await res.json();
  if (!res.ok) throw new Error(data.data); // e.g. "Insufficient credits"
  return data.id; // keep this to check delivery status later
}

Every send returns a message ID — keep it so you can check delivery if a user reports a missing code. See the SMS API guide for the full request and response.

Keep OTP codes secure

  • Generate codes with a cryptographically secure random function on the server.
  • Expire codes after a few minutes and allow only a handful of attempts.
  • Limit how often a code can be resent to the same number.
  • Store a hash of the code rather than the code itself.
  • Keep your API key on the server, never in the app.

Make sure codes arrive

  • Validate numbers before sending — a Ugandan mobile number has 9 digits after +256.
  • Keep the message in plain text; emoji switch it to Unicode and can split it.
  • If a code doesn't arrive, check its status: Buffered usually means the phone is off or out of coverage; Rejected means the network refused it.

Related questions

How much does an OTP SMS cost in Uganda?

A plain-text OTP under 160 characters uses one credit, which costs UGX 25–40 on Bulk SMS Uganda depending on your top-up size.

Can OTP messages show my company name as the sender?

Custom sender IDs are arranged through support. Call or WhatsApp 0774310842 to discuss one for your business.

How fast are OTP messages delivered?

Messages are handed to the mobile network as soon as the API call is made. Final delivery depends on the recipient's phone being on and in coverage, and you can confirm it with the status endpoint.

Try it free with 5 SMS credits

Pay-as-you-go, credits never expire, and no credit card is needed to start.

Create a free account