OTP Expiration Time Best Practices & Rate Limiting (2026)

OTP Expiration Time Best Practices & Rate Limiting (2026)

OTP expiration time best practices compared by delivery channel: a 10-minute hard ceiling for codes sent by SMS or voice, no fixed cap for authenticator app codes, and a three-attempt rate limit before lockout

OTP expiration is how long a one-time password stays valid after delivery. OTP rate limiting restricts how many codes a user can request, and how many wrong guesses they get, in a given period. Together they decide whether your verification flow is secure, usable, or an open door.

Get the balance wrong and you either lock out legitimate users or hand an attacker unlimited guesses. This guide covers the OTP expiration time best practices, rate-limiting thresholds and lockout policies that hold up under review, with specific windows for login, payments, fintech KYC and mobile money.

Settle one thing before you pick a number. The maximum expiry allowed depends on how the code reaches the user: NIST SP 800-63B-4 puts a hard 10-minute ceiling on codes sent by SMS or voice, and no fixed ceiling at all on authenticator-app codes.

Quick-Reference: OTP Expiration and Rate Limiting by Use Case

Use caseDelivery channelRecommended expiryMax attemptsCooldown after limit
Login / 2FASMS or voice2 – 5 min3 – 515 min
Payment confirmationSMS or voice3 – 5 min330 min
Account recoverySMS or voice10 min maximum360 min
Account recoveryEmailUp to 24 hours360 min
Device registrationSMS or voice5 – 10 min330 min
Email address verificationEmail15 – 30 min560 min
Mobile money (MoMo)SMS or USSD3 – 5 min330 min
Fintech KYCSMS or voice5 – 10 min360 min
Banking transactionSMS or voice60 – 90 sec2 – 330 min
Authenticator appIn-app (TOTP)No fixed cap; derive it3 – 515 min

Every SMS and voice row sits inside NIST’s 10-minute ceiling for out-of-band authentication. The email rows run longer because NIST treats a code that validates an email address, or one issued for account recovery, as something other than authentication.

Building this rather than reading about it? The OTP section of the developer documentation carries the request parameters, and Phone Number Verification applies these controls for you.

How Long Should an OTP Be Valid?

For a code delivered by SMS or voice, 10 minutes is the outer limit. NIST SP 800-63B-4 states that out-of-band authentication “SHALL be considered invalid unless completed within 10 minutes”, and an SMS or voice OTP is out-of-band authentication.

For a time-based code from an authenticator app there is no fixed maximum. NIST requires the lifetime to be derived from the authenticator’s expected clock drift in either direction, plus an allowance for network delay and the user’s entry of the code.

So the standard OTP expiry time is two answers, not one. Inside the 10-minute ceiling, pick the window that matches what your user is doing between receiving the code and typing it.

Standard Use Cases

Login and 2FA: 2 – 5 minutes. The user is already at the input screen, so a short window costs them nothing.

Payment confirmation: 3 – 5 minutes. They need time to check the amount, the recipient and the account first.

Account recovery: 10 minutes for SMS or voice. NIST caps issued recovery codes at 10 minutes by text message or voice, 24 hours by email, 21 days by post within the contiguous United States and 30 days by post outside it. If recovery needs more slack, move it to email rather than stretching the SMS window.

Device registration and email address verification tolerate longer windows than login or payment. Setup happens once, and confirming an address is not authentication.

Africa-Context OTP Expiration Windows

If you are building for Ghana, Nigeria, Tanzania or South Africa, adjust the standard windows for how people actually complete these flows.

Mobile money (MoMo) OTP: 3 – 5 minutes. Users on MTN MoMo or Telecel Cash often navigate USSD menus before entering a confirmation code. A 60-second window that suits a banking app login times out mid-flow for someone dialling through menu layers.

Fintech KYC: 5 – 10 minutes. Onboarding in Ghana and Nigeria commonly pairs the OTP with an identity document upload, whether that is a Ghana Card, BVN validation or a passport scan. The user is switching between camera, file picker and code entry, and a 2-minute window forces restarts. See our guide to OTP for fintech and banking transaction security.

Banking approval: 60 – 90 seconds. Where the approval happens inside the banking app, with the amount and the recipient already on screen, the user is reading and typing rather than dialling through menus. Nothing pulls them out of the flow, so the tight window costs them little, and it narrows the interval in which an intercepted code is still worth anything.

Build headroom for delivery latency. Latency on some routes into these markets runs materially higher than on well-provisioned European or North American routes, and a 60-second code that arrives late leaves almost no time to read and type it. Measure your own delivery times per route, then set the window from that measurement rather than from an inherited default.

What Does NIST Say About OTP Expiration and Rate Limiting?

More than “no fixed maximum”, which is a summary this guide itself previously carried and one that is only half right. NIST SP 800-63B-4 holds two separate expiry rules, and which one applies depends on how the code is delivered.

RequirementThe figureWhat it applies to
Out-of-band authentication must complete within10 minutesCodes sent by SMS, voice or push over a second channel
Time-based OTP lifetimeNo fixed cap; derive itAuthenticator apps and hardware OTP devices
Consecutive failed attempts on one authenticator100 maximum, then disable itAny verifier applying rate limiting
Rate limiting becomes mandatory below64 bits of code lengthEvery 4 to 8 digit numeric code
Out-of-band secret lengthAt least 6 decimal digits, randomly generatedSMS and voice codes
Issued recovery codes10 min by text or voice; 24 h by emailAccount recovery
Email as an authentication channelProhibitedAuthentication only; address validation and recovery codes are exempt

The confusion sits in the second row. The no-fixed-cap rule is real, and it is the rule for authenticator apps. Read it without its scope and you get “NIST prescribes no maximum”, which is true of a TOTP app and false of the SMS code your users receive.

NIST also names exactly one restricted authenticator in this revision: use of the public switched telephone network for out-of-band authentication, which covers both SMS and voice delivery.

Restricted is not prohibited. It means your organisation has to assess, understand and accept the risk, and weigh risk indicators such as device swap, SIM change and number porting before sending a code over the PSTN. Tight expiry and hard attempt limits are two of the compensating controls that make that acceptance defensible.

On length the standard is specific. Out-of-band authentication secrets must be at least six decimal digits and come from an approved random bit generator. Six digits is a floor, not a convention.

How Many OTP Attempts Should Be Allowed Before Lockout?

Three to five wrong entries per code, then stop accepting that code.

NIST’s ceiling is far higher. It requires verifiers to limit consecutive failed attempts against a single authenticator on one account to no more than 100, then disable that authenticator, and it explains the choice: 100 balances the odds of guessing a six-digit decimal OTP against the cost of pushing legitimate users into account recovery.

That is an upper bound, not a target. A 6-digit OTP gives an attacker 1,000,000 combinations to work through, and a five-attempt limit gives them five.

Rate limiting itself is not a matter of taste. NIST says a verifier should implement a rate-limiting mechanism and SHALL implement one when the authenticator output is shorter than 64 bits. A six-digit decimal code carries roughly 20 bits of entropy, so every numeric OTP lands on the mandatory side of that sentence.

Per-Phone-Number Limits

Limit sends by recipient phone number, not only by user account. This stops an attacker flooding one number with codes, which degrades that person’s experience and inflates your SMS spend.

  • Send limit: 3 – 5 OTPs per phone number per hour
  • Attempt limit: 3 – 5 wrong-code entries per OTP
  • Cooldown: 15 – 30 minutes after the limit is hit

Per-IP Rate Limits

Layer IP-based limits on top to catch automated attacks that rotate phone numbers but originate from one source.

  • Send limit: 10 – 20 OTP requests per IP per hour
  • Burst protection: no more than 3 requests per IP in any 60-second window

Account-Level Lockout

After repeated failures across multiple codes, lock the account and require a different route back in.

  • Threshold: 10 total failed attempts across all OTPs within 24 hours
  • Recovery: identity verification through a secondary channel, such as a support ticket or an in-person check

Should a Resend Send the Same OTP or Generate a New One?

Send the same code and let it keep its original expiry. Generate a new one only once the first has expired or you have explicitly invalidated it. Exactly one code is valid at any moment.

The standard constrains this: a verifier accepts a given authentication secret as valid only once during its validity period, which is what gives one-time passwords their replay resistance. Two live codes for one login doubles the guess surface and buys nothing.

The practical case agrees. When a resend happens because the first SMS was late rather than lost, a fresh code makes it worse: the delayed original lands afterwards, the user types the code in front of them, and it fails on your delivery rather than their mistake. Resending the same code makes late delivery harmless.

Count every resend against the send limit, and put exponential backoff behind the resend button.

OTP Rate Limiting and SMS Pumping Prevention

Rate limiting is your first defence against SMS pumping fraud, the artificially inflated traffic that generates fraudulent SMS charges on your account.

According to the CFCA, telecommunications fraud increased 12% in 2023, equating to an estimated $38.95 billion lost to fraud. That figure covers all telecom fraud rather than SMS pumping alone, and it is the pool an unprotected OTP endpoint pays into.

Without per-number and per-IP limits, an attacker can trigger thousands of OTP sends per minute, each one a chargeable message on your account. If you are weighing providers on what they handle natively, compare OTP API providers on their built-in fraud controls.

OTP Rate Limiting Implementation Patterns

Token bucket gives each user or phone number a fixed number of tokens. Each request consumes one, and tokens refill at a set rate. It handles bursty traffic well: a user who genuinely needs a second code gets it immediately, while sustained abuse runs dry.

Sliding window tracks requests across a rolling period. More predictable, and less forgiving of legitimate retry bursts.

For most OTP implementations, token bucket with exponential backoff on resend gives the best balance of security and usability.

Distinguish Error Types in Your OTP Flow

Your rate-limiting logic needs to tell a wrong code apart from an expired one. A user entering an expired code is not attacking you, and counting that entry against their attempt limit creates friction for nothing.

  • Wrong code: decrement remaining attempts. Show: “That code doesn’t match. You have 2 attempts remaining.”
  • Expired code: send a fresh code within your send limits. Show: “This code has expired. We’ve sent a new one to your phone.”
  • Rate limited: show: “Too many attempts. Please wait 15 minutes before requesting a new code.”

Two Arkesel integration details save a first-call debugging session. OTP calls must be authenticated with your account’s main SMS API key, and the additional API keys will not work for OTP. The message body must contain an %otp_code% placeholder, or the request is rejected. Both are covered in the OTP section of the developer documentation.

Hit errors during integration? Our OTP API troubleshooting guide covers the most common ones.

What Is the Best Fallback Method If an OTP SMS Fails?

Voice first, then USSD. Not email.

NIST SP 800-63B-4 states that email SHALL NOT be used for out-of-band authentication, citing access using only a password, interception in transit or at intermediate mail servers, and rerouting attacks such as DNS spoofing.

The prohibition is narrower than it sounds: codes sent to validate an email address, or issued as recovery codes, are not authentication and are not affected. Email stays correct for confirming an address someone just typed. It is not a fallback for signing in or approving a payment.

That leaves a three-step chain.

  • SMS first, for reach.
  • Voice second, because it reaches users whose SMS is filtered, blocked or delayed, and it works on a feature phone.
  • USSD third, because a USSD session does not depend on SMS delivery at all.

Retry with backoff. If the first SMS has not arrived within 30 seconds, offer a resend button with exponential backoff behind it: first retry at 30 seconds, second at 60, third at 120. If codes to a particular number fail rather than arrive late, your delivery reports will say so — SMS delivery status codes and how to fix failed messages walks through diagnosing them.

Communicate clearly. “Didn’t receive your code? Wait 30 seconds and we’ll send another” is actionable. “An error occurred” is not.

Phone Number Verification runs this chain for you: it retries by voice call automatically when SMS fails, and falls back to USSD when voice is unavailable.

For how the channels compare on reach, cost and user experience, including where email is the right primary channel for verifying an address, see SMS OTP vs authenticator app vs email OTP.

Should You Build OTP Expiry and Rate Limiting, or Configure Them?

Everything above is a decision you can implement yourself. Some of it is also a configuration flag.

Build it yourself when the OTP is one piece of an authentication stack you already run, with your own code generation, storage and throttling, or when the codes travel over a channel you control rather than SMS or voice. If you already enforce rate limiting and lockout at your own API edge, a second limiter on the provider side is one more thing to reason about every time a request comes back refused.

Configure it when the code goes out over SMS or voice and expiry, length and per-number limits are the whole of what you need. Arkesel’s Phone Number Verification takes OTP length and expiry as parameters on each request, so a short banking code and a longer recovery code come out of the same integration with different values. Read the permitted ranges from the OTP section of the API reference rather than from this article, so you are working from the limits that are current when you build.

Rate limiting runs server-side, per phone number, against OTP bombing and brute-force verification attempts. Delivery covers SMS, voice call and USSD behind one API.

The service is available in Ghana, Nigeria, South Africa and Tanzania. A request for a destination outside that coverage returns a dedicated error, code 1006 in the OTP API reference, rather than failing quietly.

OTP Expiration and Rate Limiting Checklist

Use this to confirm your flow follows the OTP expiration time best practices above before you ship:

  • Expiry is set per use case and per delivery channel, with every SMS and voice code inside the 10-minute ceiling
  • Measured delivery latency for your own routes is factored into the window
  • Per-phone-number send limits are in place (3 – 5 per hour)
  • Per-phone-number attempt limits are in place (3 – 5 per OTP), well inside NIST’s 100-attempt ceiling
  • Per-IP rate limiting is layered on top (10 – 20 per hour)
  • Rate limiting is implemented rather than optional, because a numeric code falls under the 64-bit threshold
  • Expired-code and wrong-code errors are handled differently
  • Account-level lockout triggers after 10 cumulative failures in 24 hours
  • Fallback delivery is configured as voice, then USSD, and not email
  • Resend policy is defined, with only one code valid at a time
  • Codes are single-use and invalidated after successful verification

For the broader build, including code generation, hashing, transport encryption and the full send-then-verify flow, see our OTP API integration guide.

FAQ

How long should an OTP be valid? Delivery channel first, use case second. A code sent by SMS or voice must be used within 10 minutes at the outside; inside that, login 2 – 5 minutes, payment 3 – 5 minutes, mobile money 3 – 5 minutes, banking approvals 60 – 90 seconds. An authenticator-app code has no fixed cap.

What does NIST recommend for OTP expiration? For out-of-band authentication, which is how SMS and voice OTPs are delivered, NIST SP 800-63B-4 requires the authentication to complete within 10 minutes. For time-based codes from an authenticator app it sets no fixed cap and instead requires the lifetime to be derived from clock drift, network delay and entry time. The often-repeated claim that the standard prescribes no maximum applies only to the second case.

How many OTP attempts should be allowed before lockout? Three to five wrong entries per code, and account lockout after 10 cumulative failures within 24 hours. NIST’s hard ceiling is 100 consecutive failed attempts against one authenticator, which is an upper bound rather than a recommendation.

Is rate limiting on OTP attempts required? Yes, for any numeric code. NIST makes rate limiting mandatory when the authenticator output is shorter than 64 bits, and a 4 to 8 digit code is far shorter than that.

Should a resend send the same OTP or a new one? Send the same code and keep its original expiry, then issue a fresh one only after the first expires or you invalidate it. Never leave two codes valid at once, and count every resend against the send limit.

How do you handle expired OTPs without frustrating users? Separate expired-code errors from wrong-code errors, and do not count an expired entry against the attempt limit. Send a fresh code within your send limits and say so plainly: “This code has expired. We’ve sent a new one.”

Ship Your First OTP Flow

Take your main SMS API key, pick the expiry and length you want from the table above, check both against the OTP section of the developer documentation before you send, then verify the code with a second call. Finish by running the two paths your users will actually hit, a code that has expired and a code entered wrong, and confirm your flow tells them apart.

Create your Arkesel account and send your first verification code today.

Scroll to Top