OTP API Integration Guide: SMS Verification for Developers (2026)

SMS OTP API integration is the most common security feature developers ship — and the one most often shipped wrong. A weak implementation leaks money through SMS pumping. A brittle one drops users at checkout. A rigid one fails the moment your delivery channel goes down.
This guide walks you through OTP integration end to end, written for developers who want to ship phone verification that holds up in production — with an Africa-first view on delivery, because that is where most OTP flows quietly fail.
What is an OTP API and how does it work?
An OTP API is the service your application calls to generate, deliver, and verify a one-time code that proves a user controls a phone number or inbox. You hand it a destination and a request; it returns a result you can act on. An OTP SMS API is the same capability with SMS as the delivery channel — the most universal way to reach a phone.
That means you never store or generate codes yourself. The provider handles generation, hashing, expiry, and delivery. You handle the user experience and two API calls.
A quick vocabulary note for the search you probably ran to get here: an “SMS verification API” and an OTP API are not two products. An SMS verification API is the OTP API viewed from the phone-verification angle — generate a code, send it over SMS, validate the input. Same flow, same integration. If you want the conceptual groundwork before the code, our guide on how OTPs work covers the fundamentals.
Why bother with a second factor at all? Because the password alone keeps failing. According to Verizon’s 2026 Data Breach Investigations Report, human-targeted attacks — phishing and social engineering, increasingly aimed at mobile devices — remain a leading cause of breaches worldwide. A one-time code sent to a device the attacker does not hold closes the gap a leaked password opens.
How OTP verification works end-to-end
Every OTP system follows the same two-phase pattern: send, then verify.
Phase 1 — Send. Your application calls the provider with a phone number. The provider generates a random code, stores it as a hash server-side, sets an expiry, and delivers it over SMS, voice, WhatsApp, or USSD.
Phase 2 — Verify. The user enters the code. Your backend sends the code and the phone number to the provider’s verify step. A match within the time window authenticates the user. A mismatch or an expired code fails closed.
The practical payoff of this split: your application never touches the raw code. The provider owns generation, delivery, storage, and expiry. You own the interface and the API calls — which is exactly why a managed OTP API saves the substantial effort a from-scratch build would cost in code generation, hashing, expiry logic, and delivery infrastructure.
What is the difference between an OTP API gateway and direct integration?

Direct integration calls a single provider’s REST endpoint straight from your backend. A gateway adds a routing layer between your app and one or more providers, switching by channel, region, or provider health. Direct is faster to build but creates a single point of failure; a gateway adds reliability through redundancy and channel fallback. Three architecture patterns cover almost every OTP integration.
Direct API integration
The most streamlined pattern. Your application makes REST calls directly to one provider.
Your App -> OTP Provider API -> SMS / Voice / USSD Gateway -> UserBest for: early-stage products, low volume, a first verification flow.
Trade-off: zero abstraction overhead and fast to ship — but if the provider or a carrier route fails, your entire OTP flow stops. No fallback.
Gateway aggregator pattern
A routing layer sits between your application and one or more providers, directing each request by channel, region, or health.
Your App -> OTP Gateway Layer -> Provider A (SMS)
-> Provider B (Voice)
-> Provider C (WhatsApp)Best for: production apps with real reliability requirements, multi-channel delivery, regional optimisation.
Trade-off: more upfront engineering for the routing layer, repaid in channel flexibility and provider independence. A platform that delivers SMS, Voice, and USSD from one API collapses most of that complexity into a single integration.
Failover chain architecture
A primary provider handles every request. On failure or timeout, the system routes to a secondary, then a tertiary.
Your App -> Primary (SMS, short timeout)
-> Secondary (Voice, longer timeout)
-> Tertiary (WhatsApp / USSD)Best for: mission-critical flows — fintech, checkout, banking authentication.
Key mechanics: set per-channel delivery timeouts and trigger failover when no confirmation arrives; track provider error rates with a circuit breaker so a failing provider drops out of the chain; poll status endpoints so you detect an outage before your users do. When a failover fires repeatedly, treat it as a symptom — our guide on common OTP API integration errors shows you how to tell a client-side fault from a provider one.
Which OTP delivery channel should you use?
SMS is the right default for OTP delivery: it reaches virtually every mobile device and arrives in seconds. Add voice as a fallback for failed SMS and accessibility, reserve WhatsApp for smartphone users on data, and lean on USSD where data is scarce — it works on any handset and stores nothing on the device.
| Channel | Delivery speed | Device reach | Security profile | Best use |
|---|---|---|---|---|
| SMS | Seconds | Almost every mobile device | SIM-swap and interception risk | Default, universal reach |
| Voice | Slower than SMS | Any phone with voice | Call interception, voicemail risk | Fallback, accessibility |
| Fast | App + internet required | End-to-end encrypted, device-bound | Smartphone users on data | |
| USSD | Near-instant | Any mobile device, no data | Session-based, nothing stored | Feature phones, low-data markets |
Channel choice shifts in African markets. Feature-phone prevalence and intermittent data mean SMS and USSD carry most OTP traffic. USSD is the standout: it reaches every handset, needs no data, and leaves no code stored after the session — a natural fit for mobile money and banking, where USSD is already the primary interface. For a deeper trade-off analysis, see our comparison of SMS, authenticator app, and email OTP.
How do you integrate an OTP SMS API into your application?
Integrate an SMS OTP API in five steps: secure your API key, set up your environment, generate and send the code, handle the response, then verify the user’s input. It is the same flow whether you came here looking for an API for OTP verification or an API for verifying users by SMS — one call to generate and send the code, one to verify it. The walkthrough below uses Arkesel’s live OTP endpoints — a Generate call and a Verify call. Confirm the current contract in the Arkesel developer documentation before you ship, since request details can change.
Step 1: Get and secure your API key
Create an Arkesel account, open the API settings, and copy your key. Store it in an environment variable or a secret manager — never hard-code it, and never commit it to version control. A leaked OTP key is a direct line to your messaging budget.
One gotcha trips up almost every first integration: OTP works only with your Main SMS API Key — it will not work with any of your Multiple (sub) API keys. OTP usage also draws on your account’s Main Balance, so top it up before you go live and check the current Arkesel pricing for rates.
Step 2: Set up your development environment
Both OTP endpoints are plain REST on https://sms.arkesel.com, authenticated with an api-key request header and a JSON body — so you only need an HTTP client:
- Python: install
requests(orhttpx). - Node.js: use the built-in
fetch, oraxios. - PHP: enable the cURL extension.
Arkesel publishes copy-paste samples in cURL, Python, Node.js, and PHP; these are code samples rather than maintained SDK client libraries, so you call the REST endpoint directly.
Step 3: Generate and send the OTP
Generate the code with a single POST to https://sms.arkesel.com/api/otp/generate. The request carries the destination number, the delivery channel, an expiry window, a code length, and a message template that holds the code. Arkesel generates the one-time password within about two seconds and delivers it over SMS or voice.
curl -X POST https://sms.arkesel.com/api/otp/generate \
-H "api-key: $ARKESEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expiry": 5,
"length": 6,
"medium": "sms",
"message": "This is OTP from Arkesel, %otp_code%",
"number": "233544919953",
"sender_id": "Arkesel",
"type": "numeric"
}'The parameters map to real constraints you code against:
expiry— integer, 1 to 10 minutes.length— integer, 6 to 15 digits or characters.medium—smsorvoice.message— your template; it must contain the%otp_code%slot where the code is injected (add the optional%expiry%slot to tell the user how long they have).number— the destination phone number in international format.sender_id— 1 to 11 characters.type—numericoralphanumeric.
A successful call returns code 1000:
{
"code": "1000",
"ussd_code": "*928*01#",
"message": "Successful, OTP is being processed for delivery"
}Notice the ussd_code in the response. If an SMS is slow to arrive — common on congested African routes — the user can dial that USSD string to pull the code on any handset, with no data. It is an Africa-first retrieval fallback most global providers do not offer.
Here is the same call in Python:
import os, requests
def generate_otp(number):
res = requests.post(
"https://sms.arkesel.com/api/otp/generate",
headers={
"api-key": os.environ["ARKESEL_API_KEY"],
"Content-Type": "application/json",
},
json={
"expiry": 5,
"length": 6,
"medium": "sms",
"message": "This is OTP from Arkesel, %otp_code%",
"number": number,
"sender_id": "Arkesel",
"type": "numeric",
},
)
data = res.json()
if data.get("code") == "1000":
return {"success": True, "message": data.get("message")}
return {"success": False, "code": data.get("code"), "message": data.get("message")}Step 4: Handle the response and error codes
Do not assume success on a 200. Read the code in the response body, branch on it, and map each code to a clear user-facing message. Authentication and transport problems surface as HTTP status codes — 401 for a missing or invalid key, 422 for a validation error, 500 for an internal error — while the application outcome lives in the code field. The full list of generate and verify codes is in the table below.
For delivery outcomes that arrive after the initial response, register a webhook. A delivery callback lets you trigger a fallback channel, watch delivery rates, and catch the anomalies that signal abuse.
Step 5: Verify the user’s code
This is the call that verifies a user by SMS: prompt for the code they received, then POST it with their phone number to https://sms.arkesel.com/api/otp/verify. Validate server-side — never in the browser.
curl -X POST https://sms.arkesel.com/api/otp/verify \
-H "api-key: $ARKESEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "173882",
"number": "233544919953"
}'A successful verification returns code 1100:
{
"code": "1100",
"message": "Successful"
}In Python:
def verify_otp(number, code):
res = requests.post(
"https://sms.arkesel.com/api/otp/verify",
headers={
"api-key": os.environ["ARKESEL_API_KEY"],
"Content-Type": "application/json",
},
json={"code": code, "number": number},
)
data = res.json()
if data.get("code") == "1100":
return {"verified": True}
return {"verified": False, "code": data.get("code"), "reason": data.get("message")}An invalid code returns 1104; an expired one returns 1105. Surface those to the user as distinct, actionable messages — “that code is incorrect” and “that code has expired, request a new one” — rather than a single generic failure.
See how Arkesel’s SMS Platform delivers OTPs over direct mobile-network connections with real-time delivery tracking — explore the Arkesel SMS Platform.
OTP API response and error codes
Every OTP response carries a code. Branch on it, log it, and map it to a user-facing message. Here is the full set — generate, verify, and the HTTP-level codes.
Generate OTP codes
| Code | Meaning | How to handle |
|---|---|---|
| 1000 | Successful — OTP is processing for delivery | Store the attempt, prompt the user for the code |
| 1001 | Validation error — a required field is missing | Fix the request body |
| 1002 | Message is missing the %otp_code% slot | Add %otp_code% to your template |
| 1003 | Sender ID blocked by administrator | Use an approved sender ID |
| 1004 | SMS gateway not active or credential not found | Confirm your account and Main API key |
| 1005 | Invalid phone number | Validate and format the number before sending |
| 1006 | OTP not allowed in your country | Restrict sends to the markets you serve (delivery is geo-gated) |
| 1007 / 1008 | Insufficient balance | Top up your Main Balance |
| 1009 | Voice message over 500 characters | Shorten the voice template |
| 1011 | Internal error | Retry with backoff; escalate if it persists |
Verify OTP codes
| Code | Meaning | How to handle |
|---|---|---|
| 1100 | Successful — the code is valid | Authenticate the user |
| 1101 | Validation error | Fix the request body |
| 1102 / 1103 | Invalid phone number | Verify the number matches the one you sent to |
| 1104 | Invalid code | Tell the user the code is incorrect; count the attempt |
| 1105 | Code has expired | Prompt the user to request a new code |
| 1106 | Internal error | Retry with backoff; escalate if it persists |
HTTP status codes
| Status | Meaning | What you do |
|---|---|---|
| 401 | Authentication failed — missing or invalid key | Check the api-key header |
| 422 | Validation error | Fix the payload |
| 500 | Internal error | Retry with backoff or fail over |
Codes 1006 (country not allowed) and 1005 (invalid number) are your two most common delivery blocks — validate numbers and restrict destinations up front, and you eliminate most failed sends before they cost you anything.
Advanced OTP generation and validation
Once the core flow works, the depth lives in how codes are generated and how strictly they are validated. This is where a verification system moves from functional to resilient.
What is the difference between TOTP and HOTP?
TOTP and HOTP are the two standard ways to generate codes. According to OneLogin’s explainer on OTP, TOTP, and HOTP, both derive a code from a shared secret seed plus a moving factor; HOTP increments that factor with each request (counter-based), while TOTP derives it from the current time (time-based), which is why time-based codes expire after a short window. For most app-delivered SMS verification you are not implementing the algorithm yourself — your provider does — but knowing which model is in play tells you how expiry and resynchronisation behave.
Code length, expiry, and attempt limits
Three settings carry most of the security weight — and with Arkesel you set the first two directly in the generate call:
- Length and character set. Six numeric digits balance entry friction against guessability for SMS; set
lengthhigher (up to 15) or switchtypetoalphanumericfor higher-risk actions. - Expiry window. Short-lived codes shrink the window an intercepted code is useful. Set
expirybetween 1 and 10 minutes — keep it tight, and tighter still for sensitive operations. Our guide on OTP expiration and rate-limiting best practices goes deep on choosing the window. - Attempt limits and single use. Cap verification attempts per code, lock out after repeated failures, and enforce one-time use so a code cannot be replayed across sessions.
Stronger validation patterns
Beyond the essentials, several industry techniques harden validation. These are options you can build into your own flow — not features any single provider switches on for you:
- Adaptive verification raises code strength or step-up requirements when risk signals appear (unusual velocity, a new device).
- Device and IP fingerprinting flags a code entered from an unfamiliar device or location for extra checks.
- Encrypted transmission over HTTPS/TLS keeps the code from being intercepted in transit.
- One-time URLs pair a code with a short-lived link tied to a single session.
- Anomaly detection, including machine-learning models, can flag suspicious request patterns at scale.
The constant tension is user experience against security: every extra factor adds friction, so reserve the heavier patterns for high-risk actions and keep the common path fast.
How do you protect OTP endpoints from abuse?
Protect OTP endpoints with rate limiting on both send and verify, abuse detection on the send-to-verify ratio, HTTPS-only transmission, and intelligent retries. OTP endpoints are attack magnets: left open, a single bad actor can drain your messaging budget overnight.
Rate limiting. Apply separate limits to send and verify — they have different abuse patterns. Cap sends per user and per IP over a short window; cap verify attempts per code with lockout after repeated failures. Use distinct namespaces so an exhausted send limit does not block verification of codes already in flight.
SMS pumping protection. SMS pumping is the costliest attack on OTP systems — bots trigger floods of sends to premium-rate ranges and profit from carrier revenue share while you pay for every message. The clearest signal is a send-to-verify ratio that collapses: sends spike, verifications flatline. Add a CAPTCHA or challenge before the send endpoint, run a carrier lookup to filter non-mobile numbers, and restrict sends to the countries you actually serve. Our guide on SMS pumping fraud prevention breaks down detection and response in detail.
Retry intelligently. On a transient failure, retry with exponential backoff and an idempotency key so the user does not receive duplicate codes. Never retry permanent failures such as an invalid number or a blocked sender.
These measures are the front line of OTP security; for the broader checklist, see our guide on securing transactions with OTP APIs, which matters most in high-stakes flows like OTP for fintech and banking.
How do you test an OTP API before production?
Test an OTP API across four layers: mock the provider for unit tests, run the full send-deliver-verify cycle as integration tests against a sandbox, load-test the endpoints to peak traffic, and run a security checklist. OTP touches authentication, third-party APIs, delivery, and money — test each layer before it reaches users.
Mock and sandbox. Arkesel’s messaging APIs provide a sandbox environment for testing without affecting your balance, so you can run the full flow and send unlimited test messages before a single real code goes out. Mock the provider at the interface level for unit tests so your business logic is isolated from provider behaviour, then swap in the sandbox for integration tests.
Integration tests should cover the real cases: generate returns code 1000; verify succeeds with code 1100; verify fails on a wrong code with 1104; verify fails after expiry with 1105; a used code cannot be reused; and rate limiting triggers at the threshold.
Load tests ramp from your baseline to several times projected peak and watch the degradation curve. The endpoint should fail gracefully — returning 429 or 503 — rather than timing out silently. Tools such as k6, Artillery, or Locust point cleanly at a staging environment with sandbox endpoints enabled.
Security checklist: confirm codes expire on schedule, codes are single-use, brute-force lockout fires after repeated failures, codes are stored hashed rather than in plaintext, transmission is HTTPS-only, and verification uses constant-time comparison so response timing leaks nothing.
How do you choose an OTP API provider?
Choose an OTP API provider on five dimensions: API and documentation quality, multi-channel support, a real sandbox, geographic delivery coverage, and compliance. For users in Africa, delivery coverage is decisive — a provider with direct carrier connections lands codes faster and more reliably than one routing through international aggregators.
- API and docs quality. RESTful endpoints, consistent error codes, webhook support, and working code samples in your language — not just a bare spec.
- Multi-channel support. SMS is the floor; production needs at least voice fallback. SMS plus voice plus one more channel reduces the integrations you maintain.
- A real sandbox. Test numbers and a sandbox mode so you are not spending real money during development.
- Geographic delivery coverage. For African users, verify direct carrier connections in your target countries — direct routes mean faster delivery and higher success rates.
- Compliance. Data-handling practices, residency options, and audit logging for regulated industries.
Arkesel connects directly to MTN, Telecel, and AirtelTigo, and delivers OTPs over SMS, Voice, and USSD from a single REST API — USSD reaches every handset with no data, a channel global providers rarely offer. For an objective side-by-side, see our OTP API provider comparison. Pricing changes too often to trust a figure in a blog post — check the current Arkesel pricing page.
OTP integration production readiness checklist
Before you ship, confirm every item.
Security
- Codes expire on a short window; shorter for high-risk actions
- Codes stored as hashes, never plaintext
- Rate limiting on both send and verify endpoints
- HTTPS enforced on every OTP endpoint
- Brute-force lockout after repeated failed attempts
- CAPTCHA or challenge ahead of the send endpoint
Reliability
- Multi-channel fallback configured (at minimum SMS plus voice)
- Delivery-status monitoring via webhooks
- Alerting when the delivery rate drops below your threshold
- Circuit breaker for provider failover
- Retry with exponential backoff and idempotency keys
Compliance
- Data-retention policy defined for OTP records
- User consent captured before sending
- Regional telecom and data regulations reviewed
- Audit logging for every OTP event
Operations
- Structured logging with request IDs for tracing
- A metrics dashboard: send volume, delivery rate, verification rate, latency
- Cost monitoring with budget alerts
- Abuse alerts on the send-to-verify ratio and geographic anomalies
This guide anchors a wider library of OTP resources — security, errors, expiry and rate limiting, providers, fraud, fintech, delivery channels, and the fundamentals of how OTPs work. Work through them as your integration matures.
Frequently asked questions
Is an SMS verification API the same as an OTP API?
Yes. They describe one capability from two angles. An OTP API generates and validates one-time codes across channels; an “SMS verification API” names the case where the code is delivered over SMS to verify a phone number. The integration, code, and testing are identical.
How do you verify a user by SMS with the API?
Send the code the user entered, with their phone number, to Arkesel’s verify endpoint (/api/otp/verify) from your backend. A match returns code 1100 and you authenticate the user; an invalid code returns 1104 and an expired one returns 1105. Always validate server-side, never in the browser.
What expiry window and attempt limits should you set?
Keep the expiry window short so an intercepted code is useful for as little time as possible, and shorten it further for sensitive actions. Cap verification attempts per code, lock out after repeated failures, and enforce single use so a code cannot be replayed.
How long should an OTP stay valid?
Long enough for a user to receive and type the code, short enough that an intercepted code is quickly useless. Arkesel lets you set the expiry between 1 and 10 minutes per request; five minutes is a sensible default, and you should shorten it for high-value actions.
What if the OTP does not arrive?
First check the generate response code: 1005 means the number was invalid, 1006 means delivery is not allowed in that country, and 1007 or 1008 mean insufficient balance. If the code is 1000 but the SMS is slow on a congested route, the user can dial the ussd_code from the response to retrieve it with no data, or you can fall back to voice by setting medium to voice.
What does a failed OTP verification return?
The verify endpoint returns 1104 for an incorrect code and 1105 for a code that has expired. Treat them differently: prompt a retry on 1104 and count it toward your lockout limit, and offer a fresh code on 1105.
Can I send the OTP by voice instead of SMS?
Yes. Set medium to voice in the generate request and Arkesel reads the code to the user over a call instead of sending an SMS — a useful fallback when SMS delivery fails, and for accessibility. Keep voice message templates under 500 characters, or the request returns 1009.
How do you prevent SMS pumping on OTP endpoints?
Monitor the send-to-verify ratio in real time — pumping shows sends spiking while verifications flatline. Add a CAPTCHA or challenge before the send endpoint, run carrier lookups to block non-mobile numbers, and restrict sends to the countries you serve.
Does Arkesel offer a single OTP endpoint?
Arkesel exposes two OTP endpoints, both on https://sms.arkesel.com and authenticated with an api-key header: a Generate call (/api/otp/generate) that creates and delivers the code, and a Verify call (/api/otp/verify) that checks the code the user entered. Build against the Arkesel developer documentation for the current contract.
Start building
You now have a complete SMS OTP API integration — the architecture, the real generate and verify contract, the full response-code table, and the production checklist to ship OTP verification that holds up under real traffic. The distance between a tutorial-grade flow and a production-grade one is everything after the first successful call: rate limiting, abuse protection, fallback channels, and monitoring.
Ship phone verification that holds up in production. Start with Arkesel Phone Number Verification, explore the Arkesel developer documentation to see how SMS and voice verification work from one API, then create an Arkesel account and start testing in minutes. Check current rates on the pricing page.
Explore the Series
- OTP API Errors: 10 Common Issues and How to Fix Them (2026)
- OTP API Security: Best Practices for Secure Transactions (2026)
- SMS Pumping Fraud Prevention: How to Detect and Stop Artificially Inflated Traffic
- OTP Expiration Time Best Practices & Rate Limiting (2026)
- OTP API Provider Comparison 2026: Africa-Rated Guide
- OTP for Fintech Banking: Secure Transactions at Scale
- SMS vs Authenticator App vs Email OTP: Choosing the Right Delivery Channel
- What Is an OTP? How One-Time Passwords Work (2026 Guide)





