LOGIC TELECOM
CommunicationsAugust 3, 20266 min read

SMS OTP delivery: TTL, retries and fraud controls

How to design one-time-code delivery over SMS: expiry, attempt limits, idempotency, resend rules, delivery reports and fallback channels.

Secure delivery of a one-time code through an SMS gateway
Contents

An SMS containing a one-time code is only a transport mechanism. The security of the workflow depends on server-side validation, short expiry, request and verification limits, protected logs and predictable behaviour when delivery is delayed. A reliable SMS gateway cannot compensate for missing controls in the application.

The components of an OTP workflow

A robust design separates four responsibilities:

  1. the business service creates a request to confirm a specific action;
  2. an authentication service issues the one-time code and stores a protected verification value;
  3. a communications platform sends the message to an operator and returns a message identifier;
  4. the authentication service checks the code, expiry, attempt count and its connection to the original action.

The code is not independent proof of identity. Bind it to an operation, user or session. Sensitive actions should add risk assessment and other factors rather than relying on possession of the message alone.

Choosing an expiry time

The time to live must cover normal network delay without turning the code into a long-lived password. There is no universal number: login, payment confirmation and contact-detail changes have different risks and user journeys.

The server must enforce expiry; a countdown in the interface is only a display. A successful verification immediately invalidates the code. Issuing a new code should normally invalidate the previous one for the same operation, otherwise several messages may arrive and the user can enter an older value.

Measure P95 and P99 delivery latency on production traffic, then set expiry with a controlled margin. If tail latency regularly exceeds the window, improve the route or fallback process instead of continually extending the code lifetime.

Safe resend behaviour

The resend button introduces three risks: unnecessary cost, multiple valid codes and the ability to send large volumes to another person’s number. Every resend therefore needs server-side controls.

  • Set a minimum interval between requests.
  • Limit sends by phone number, account, session and network source.
  • Use request identifiers and idempotency so an HTTP retry does not produce another SMS.
  • Do not resend only because the DLR has not arrived; delivery reports can be delayed.
  • When a limit is reached, move the user into a safe recovery process without exposing the precise blocking rule.

If a secondary provider or channel is available, one orchestrator should own the operation state. Independent routes can otherwise deliver different codes at almost the same time.

Verification limits and brute-force resistance

Code length does not replace attempt controls. The server limits incorrect submissions for the individual request and applies wider controls to the user, phone number and request source. Once the attempt limit is reached, the code becomes invalid even if its TTL has not expired.

Do not store or log the code in plain text. A protected derived value and a server-side secret are sufficient for validation. Restrict access to queues, traces and logs, and mask the phone number wherever operators do not need its complete value.

API responses should also avoid revealing whether a number is registered. Consistent outward messages and comparable response timing make account enumeration harder.

Delivery data required from the messaging platform

“Accepted” is not enough for operations. The integration should retain at least:

  • the internal OTP request identifier;
  • the messaging platform’s message identifier;
  • timestamps for creation, platform acceptance, operator submission and final DLR;
  • a normalized status and the original error code;
  • a route or route-group identifier without sensitive data;
  • whether this was a resend and which fallback channel was used.

A message accepted by the platform has not yet reached the device. Our guide to SMS delivery metrics explains status boundaries and quality indicators.

When to use a fallback channel

Fallback works only when its trigger is defined in advance. A different SMS route may be appropriate when the first message is rejected before operator acceptance. If the confirmation window is nearly over, the interface can offer a voice call, push notification or in-app confirmation. Sending through every channel at once creates duplicates and a confusing experience.

The fallback channel must not bypass the primary channel’s security rules. It uses the same operation identifier, shared attempt limits and one decision about whether the code is valid. For high-risk actions, channel availability must not silently lower the assurance level.

An API integration model

Build the contract around a verification resource rather than an individual SMS:

  1. POST /verifications creates the operation and returns an opaque verification_id;
  2. the service asynchronously sends a notification through QuickTel or another communications platform;
  3. a webhook updates transport status but does not decide whether authentication succeeded;
  4. POST /verifications/{id}/check validates the code and atomically closes the operation;
  5. a resend is a separate command with an idempotency key and shared limits.

Keep API secrets outside source code, authenticate webhook calls and process repeated events idempotently. The SMPP versus HTTP API guide covers the main connectivity options.

Metrics for the complete workflow

Delivered-message rate alone is insufficient. Track:

  • the percentage of codes delivered inside the target window;
  • P50, P95 and P99 time from request to DLR;
  • conversion from OTP request to successful verification;
  • resend and fallback-channel rates;
  • incorrect attempts, blocks and over-limit requests;
  • the gap between delivery and successful entry;
  • errors by operator, route, region and template.

A rise in resends with stable delivery status can indicate latency, unclear interface copy or a template problem. High delivery with low verification conversion calls for investigation of the complete journey, not only the SMS provider.

Pre-launch checklist

  • The code is bound to one operation and consumed once.
  • Expiry and limits are enforced on the server.
  • A new code invalidates the previous one according to a defined rule.
  • Limits cover phone, user, session and source.
  • Codes and complete phone numbers stay out of ordinary logs.
  • Idempotency prevents API retries from creating duplicates.
  • A DLR is not treated as proof of identity.
  • Fallback shares operation state and attempt limits.
  • Alerts cover latency, conversion and abuse indicators.
  • Tests include delayed delivery, route failure and repeated webhooks.

Practical conclusion

Secure SMS OTP begins with a state model: one operation, a limited lifetime, a limited number of attempts and an observable delivery path. QuickTel can provide the transport and integration layer for enterprise SMS, while code issuance and verification remain the responsibility of the business application.

Before production, align expected load, throughput, routing, webhook processing and fallback rules. Perform separate threat modelling for critical actions and do not make SMS the only control protecting them.

SMSA2PIntegrationsSecurity

Read also