Verify users
in seconds.
Across every channel.
Send, verify, and expire one-time passwords via SMS or voice — with automatic fallback, tamper-proof tokens, and a one-line verify call.
Verification in progress
Live OTPs
99.7%
Delivery rate
~110ms
Avg. delivery
91.3%
Verify rate
99.7%
Delivery rate
~110ms
Avg. delivery
91.3%
Verify rate
10+
African countries
99.9%
Uptime SLA
2 calls
Send + verify
How it works
Two API calls.
Full verification flow.
Send the OTP
Call sendexa.otp.send() with a phone number and channel. We generate a cryptographically secure code, dispatch it immediately, and return a request ID.
await sendexa.otp.send({
to: "+233551234567",
channel: "sms",
expiry: 300
});User enters the code
Your UI collects the 4–8 digit OTP from the user. No need to store the code server-side — we handle that for you, including expiry and attempt limits.
// Your UI collects: // [ 4 ][ 8 ][ 2 ][ 9 ][ 1 ][ 0 ]
Verify in one call
Pass the request ID and user-entered code to sendexa.otp.verify(). Get a boolean result — verified or rejected. We track failed attempts automatically.
await sendexa.otp.verify({
request_id: "otp_abc123",
code: "482910"
}); // → { valid: true }What's included
Everything you need
to verify with confidence.
SMS OTP
Deliver 4–8 digit codes via SMS in under 200ms. DND-aware routing ensures transactional codes always arrive, even on restricted numbers.
Voice OTP
Fall back to voice calls automatically when SMS fails or for users who prefer audio. Text-to-speech reads the code in the user's local language.
Smart Fallback
Define a channel waterfall: try SMS first, then WhatsApp, then voice. Sendexa retries automatically based on your configured priority order.
Token Management
We handle code generation, expiry, and attempt limits server-side. No token storage in your DB — just request IDs. Tokens are single-use by default.
Fraud Detection
Rate limiting, velocity checks, and disposable number detection prevent OTP abuse before it hits your account balance or your users.
Webhook Events
Receive real-time events for every OTP lifecycle step — sent, delivered, opened, verified, expired, and failed — streamed to your endpoint.
Developer experience
Verify users in
two API calls.
SDKs for Node.js, Python, PHP, and cURL. No token storage on your end — just send a code, then verify it. We handle expiry, retries, and attempt limits.
Call otp.send() with a phone number
User enters the code in your UI
Call otp.verify() — get a boolean back
import Sendexa from "sendexa";
const client = new Sendexa(process.env.SENDEXA_API_KEY);
// 1. Send OTP
const { request_id } = await client.otp.send({
to: "+233 55 123 4567",
channel: "sms", // "sms" | "voice"
expiry: 300, // seconds
length: 6, // digits
brand: "MyApp", // appears in message body
});
// 2. Verify when user submits
const result = await client.otp.verify({
request_id,
code: "482910", // from user input
});
if (result.valid) {
// ✓ authenticated
} else {
// ✗ invalid or expired
console.log(result.reason); // "wrong_code" | "expired" | "too_many_attempts"
}Use cases
Secure every
user touchpoint.
Login & 2FA
- Phone number login
- Step-up authentication
- Account recovery
- Session verification
Payments
- Transaction confirmation
- Card verification
- High-value transfer auth
- Payout confirmation
KYC & Onboarding
- Phone number ownership
- Identity verification
- Consent confirmation
- Age verification
Account Changes
- Email / phone update
- Password reset
- Profile changes
- Device registration
Your first 1,000 OTPs
are on us.
Sign up, get your API key, and send your first OTP in under 5 minutes. No credit card required.