Engineering 3 min read

How OTP Verification Works: A Practical Guide for Product Teams

A clear, end-to-end look at one-time passwords — how they're generated, delivered over SMS and WhatsApp, verified, and secured — plus the mistakes that quietly hurt conversion.

O

OTPIQ Team

Share

A one-time password (OTP) is the most common proof that a person controls a phone number. It's also one of the easiest flows to get subtly wrong. This guide walks through how OTP verification works, what to build, and what to avoid.

What is an OTP?

An OTP is a short, single-use code — usually four to six digits — that you send to a user and ask them to type back. If they can, you know they have access to the phone number (or device) you sent it to.

The goal isn't to be clever. It's to be fast, reliable and hard to abuse.

You'll typically use OTPs for:

  • Sign-up verification — confirming a real number before creating an account.
  • Login and 2FA — adding a second factor to passwords.
  • Transaction confirmation — approving payments, deliveries or sensitive changes.

The OTP lifecycle

Every verification follows the same four steps.

  1. Generate a random code on your server.
  2. Store a hash of it with an expiry and an attempt counter.
  3. Deliver it over SMS or WhatsApp.
  4. Verify the code the user submits, then invalidate it.

Generating a secure code

Use a cryptographically secure random source — never Math.random().

js
import { randomInt } from "node:crypto";

export function generateOtp(length = 6) {
  return String(randomInt(0, 10 ** length)).padStart(length, "0");
}

Sending it with OTPIQ

Delivery is a single API call. OTPIQ handles carrier routing and automatic fallback for you.

bash
curl -X POST "https://api.otpiq.com/api/sms" \
  -H "Authorization: Bearer $OTPIQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "9647501234567",
    "smsType": "verification",
    "provider": "auto"
  }'

Let routing do the work

Using provider: "auto" lets the platform pick the best channel for each number and retry on failure — so one blocked route doesn't mean a lost user.

SMS vs. WhatsApp

Both channels work; they just trade off differently.

SMSWhatsApp
ReachAny phone with signalUsers with WhatsApp installed
CostHigher per messageTypically lower
Delivery speedSeconds, carrier-dependentNear-instant over data
Best forUniversal fallbackCost-sensitive, high-volume flows

Security checklist

Don't skip these

An unprotected OTP endpoint is an invitation for SMS-pumping fraud and brute-force attacks.

  • Expire codes after 5 minutes or less.
  • Limit verification to 3–5 attempts per code.
  • Rate-limit sends per phone number and per IP.
  • Store a hash of the code, not the code itself.
  • Make codes single-use — invalidate on success.

Mistakes that hurt conversion

Most failed verifications aren't attacks — they're friction. Watch for:

  • Slow delivery with no feedback. Show a countdown and a clear "Resend" option.
  • Codes that expire too quickly on congested networks.
  • No autofill. Format the message so the OS can offer the code automatically.
  • No fallback channel. If SMS fails, offer WhatsApp.

Final thoughts

Great OTP flows feel invisible: the code arrives in seconds, autofills, and works the first time. Get the lifecycle right, protect the endpoints, and measure delivery — everything else is polish.

  • #otp
  • #authentication
  • #sms
  • #whatsapp
  • #security
  • #iraq