Skip to main content

Verification SMS

Secure, measurable OTP flows—not just code delivery

A verification message is one step in an authentication system. The application must generate and protect the code, limit requests and guesses, handle resends, verify once, expire safely and measure whether users complete the flow.

Security values below are implementation baselines, not universal guarantees. Tune them to account risk, local rules and user experience.

End-to-end flow

Control every state from request to expiry

Keep the verification transaction separate from the SMS transport record, but link them through internal identifiers for traceability.

1. RequestValidate context and risk
2. IssueGenerate and protect code
3. SendSubmit approved template
4. VerifyCompare in constant time
5. ConsumeInvalidate after success
6. ObserveMeasure outcome and abuse

Recommended baseline

Start restrictive, then tune with evidence

ControlPractical starting pointWhy it matters
Code lengthAt least 6 random digits; use a larger space for higher-risk actions.Reduces success from guessing while remaining usable.
ExpiryOften 2–5 minutes, adjusted for delivery conditions and transaction risk.Limits the window in which a stolen code can be used.
Successful useExactly once; invalidate the transaction atomically.Prevents replay after verification succeeds.
Guess attemptsCommonly 3–5 per transaction before invalidation or step-up.Constrains online brute-force attempts.
Resend cooldownDelay the resend action and increase delay after repeated requests.Reduces duplicate SMS, user confusion and pumping abuse.
Request limitsLimit by phone number, account, IP, device, session and destination.A single identifier is easy for an attacker to rotate.
Code storageStore a hash or keyed verifier with expiry and transaction context.Reduces exposure if a verification data store is accessed.
Response wordingUse the same outward response for existing and unknown accounts.Reduces account and phone-number enumeration.

Application logic

Make issue and verify operations atomic

Provider-neutral pseudocodeSecurity flow, not an API contract
requestOtp(user, phone, context):
        normalize phone to E.164
        enforce limits for user + phone + IP + device + country
        run risk and destination checks
        generate code with a cryptographic random source
        store keyedVerifier(code), expiresAt, attempts = 0
        submit an approved SMS template
        return the same neutral response for every account state

      verifyOtp(transactionId, submittedCode):
        load transaction with a write lock
        reject if expired, consumed or attempts exhausted
        increment attempts atomically
        compare keyedVerifier(submittedCode) in constant time
        if valid: mark consumed and complete the authorized action
        record outcome without logging the plaintext code

Fraud and abuse

Protect cost, accounts and users together

SMS pumping

Watch for rapid requests, low completion, unusual destinations, number ranges and traffic that grows without matching product activity.

Credential attacks

Do not let OTP replace password, session and risk controls. Rate-limit login attempts and use step-up checks for sensitive actions.

Account enumeration

Keep outward response wording and timing consistent so attackers cannot learn whether a phone number or account exists.

SIM-swap risk

For high-value actions, combine SMS with transaction context, device signals, cooldowns or a stronger factor where appropriate.

Resend abuse

Prefer one active transaction, invalidate superseded codes and show a countdown instead of issuing an immediate new SMS.

Destination controls

Allow only markets required by the product, set spend and velocity alerts, and require review before enabling new high-risk destinations.

Delivery engineering

Fast delivery begins before the API request

Template and sender

  • State the product or brand clearly
  • Keep the code prominent and the text concise
  • Do not include unnecessary links in an OTP
  • Use the registered sender required by the destination
  • Keep templates stable enough for carrier review

Number and route

  • Normalize to E.164 before submission
  • Confirm country, carrier and traffic-type support
  • Complete sender or template registration before launch
  • Track delivery reports instead of only API acceptance
  • Escalate latency by country, network and route

Verification metrics

Measure whether people verify—not only whether SMS was sent

MetricDefinitionWhat it helps diagnose
Request-to-acceptanceAccepted API requests ÷ valid verification requests.Client validation, authentication, limits and provider availability.
Final delivery rateDelivered messages ÷ messages with a final delivery outcome.Number quality, carrier rejection, route and template issues.
p50 / p95 delivery latencyMedian and tail time from submission to delivery signal.OTP experience degradation hidden by average latency.
Verification completionSuccessful verifications ÷ verification transactions started.The combined effect of delivery, UX, expiry and fraud controls.
Resend rateTransactions with a resend ÷ transactions started.Delayed SMS, unclear UX, premature retries or user confusion.
Attempt exhaustionTransactions blocked after maximum guesses.Brute force, user error, stale codes or confusing resend behavior.
Cost per completed verificationBillable segments ÷ successful verifications, valued at route cost.Real efficiency across routes, templates and resend policies.

User experience

Security controls should remain understandable and accessible

Explain the next step

Show the masked destination, expiry window and when resend becomes available. Do not imply delivery is instant or ask a user to request repeated codes while the first message is still in flight.

Support real devices

Use a numeric input mode where appropriate, allow password managers and operating-system one-time-code autofill, preserve paste, and keep focus and error messages accessible to assistive technology.

Recover safely

Provide a support or alternative verification path for lost numbers and accessibility needs, but require appropriate identity checks so recovery does not become an easier route around authentication.

Fallback design

A fallback should not weaken the authentication decision

If another channel is available, apply the same transaction identity, expiry, attempt limit and risk policy. Do not issue parallel valid codes across multiple channels without a clear invalidation rule.

Wait intentionally

Use observed p95 delivery latency to set the resend timer instead of encouraging an immediate duplicate request.

Keep one truth

Maintain one active verification transaction and define whether a resend reuses or replaces the code.

Step up risk

For account recovery or high-value actions, require additional proof when device, location or behavior is unusual.

Verification implementation resources

Verification SMS questions

How long should an SMS code remain valid?

A common starting range is two to five minutes, but the correct value depends on transaction risk, observed delivery latency and user accessibility. Shorten high-risk actions and avoid extending validity simply to hide delivery problems.

Should a resend create a new code?

Either model can work if it is explicit. A new code must atomically invalidate the old one; reusing a code must not extend the original risk window indefinitely. Keep only one active verification truth.

Is a six-digit code secure enough?

Only when combined with short expiry, strict attempt limits, request-rate limits, secure generation, protected storage and transaction binding. Higher-risk actions may require a larger code space or stronger factor.

Does an accepted API response mean the user received the OTP?

No. It usually means the request entered processing. Use documented delivery reports and, most importantly, verification completion to evaluate the full user journey.

How can I reduce SMS pumping?

Restrict destinations, rate-limit multiple identifiers, monitor low-completion traffic, set spend and velocity alerts, require product context, and review sudden changes before expanding capacity.

Design the verification system before scaling traffic

Connect secure application logic, route-specific delivery, status tracking and completion metrics in one controlled flow.