Send OTP
Send one-time passwords (OTPs) via Email, SMS, or WhatsApp for user verification, 2FA, and authentication workflows.
Endpointโ
POST /api/v1/otp/send
Headersโ
X-API-Key: sk_live_your_api_key
Content-Type: application/json
Why Use This Endpoint?โ
- ๐ Multi-Channel - Send OTP via Email, SMS, WhatsApp, or all three simultaneously
- โก Instant Delivery - Fast OTP generation and delivery across all channels
- ๐ฏ Flexible Configuration - Customize OTP length, expiry time, and attempt limits
- ๐งช Sandbox Testing - Test without sending real messages or charges
- ๐ Session Management - Built-in tracking, rate limiting, and security
- ๐ Auto-Contact Sync - Optionally create contacts when they verify
Core Conceptโ
An OTP session is created when you send an OTP. The session manages:
- OTP codes for each channel (hashed for security)
- Verification status for each channel
- Security settings (expiry, max attempts, rate limiting)
- Custom metadata for your application logic
After sending, you receive a session token that you'll use to verify the OTP later.
Request Structureโ
Required Fieldsโ
| Field | Type | Description |
|---|---|---|
channels | array | Array of channels: "email", "sms", "whatsapp" |
recipients | object | Recipient contact for each channel |
Recipients Objectโ
| Field | Type | Required When | Description |
|---|---|---|---|
recipients.email | string | channels includes "email" | Valid email address |
recipients.sms | string | channels includes "sms" | Phone number in E.164 format (+1234567890) |
recipients.whatsapp | string | channels includes "whatsapp" | WhatsApp number in E.164 format |
Optional Fieldsโ
| Field | Type | Default | Description |
|---|---|---|---|
config | object | See below | OTP configuration settings |
metadata | object | {} | Custom data to store with session |
add_contact | boolean | false | Create contact after successful verification |
sandbox_mode | boolean | false | Test mode - returns OTPs, doesn't send messages |
Configuration Object (config)โ
| Field | Type | Default | Description |
|---|---|---|---|
otp_length | number | 6 | OTP code length (4-8 digits) |
expiry_minutes | number | 10 | Session expiry time |
max_attempts | number | 3 | Maximum verification attempts |
Use Case Examplesโ
Example 1: Email Verificationโ
Send OTP to verify a user's email address during registration.
curl -X POST https://api.sendmator.com/api/v1/otp/send \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channels": ["email"],
"recipients": {
"email": "newuser@example.com"
},
"config": {
"otp_length": 6,
"expiry_minutes": 10
},
"metadata": {
"purpose": "email_verification",
"user_id": "user_12345"
},
"add_contact": true
}'
Response:
{
"session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"channels_sent": {
"email": {
"success": true,
"message_id": "msg_550e8400e29b41d4a716446655440000"
}
},
"expires_at": "2024-01-15T10:45:00.000Z",
"verification_mode": "any"
}
Example 2: Phone Verification (SMS + WhatsApp)โ
Send OTP to both SMS and WhatsApp, allowing the user to verify via either channel.
curl -X POST https://api.sendmator.com/api/v1/otp/send \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channels": ["sms", "whatsapp"],
"recipients": {
"sms": "+1234567890",
"whatsapp": "+1234567890"
},
"config": {
"otp_length": 6,
"expiry_minutes": 5
},
"metadata": {
"purpose": "phone_verification",
"user_id": "user_67890"
}
}'
Response:
{
"session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"channels_sent": {
"sms": {
"success": true,
"message_id": "msg_660f9511f30c52e5b827557766551111"
},
"whatsapp": {
"success": true,
"message_id": "msg_660f9511f30c52e5b827557766552222"
}
},
"expires_at": "2024-01-15T10:40:00.000Z",
"verification_mode": "any"
}
Example 3: Two-Factor Authentication (2FA)โ
Send a short-lived OTP for 2FA during login.
curl -X POST https://api.sendmator.com/api/v1/otp/send \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channels": ["sms"],
"recipients": {
"sms": "+1234567890"
},
"config": {
"otp_length": 6,
"expiry_minutes": 5,
"max_attempts": 3
},
"metadata": {
"purpose": "2fa_login",
"user_id": "user_12345",
"ip_address": "192.168.1.1"
}
}'
Response:
{
"session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"channels_sent": {
"sms": {
"success": true,
"message_id": "msg_770g0622g41d63f6c938668877662222"
}
},
"expires_at": "2024-01-15T10:40:00.000Z",
"verification_mode": "any"
}
Example 4: Multi-Channel Verificationโ
Send OTP to all three channels for maximum delivery success.
curl -X POST https://api.sendmator.com/api/v1/otp/send \
-H "X-API-Key: sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channels": ["email", "sms", "whatsapp"],
"recipients": {
"email": "user@example.com",
"sms": "+1234567890",
"whatsapp": "+1234567890"
},
"config": {
"otp_length": 6,
"expiry_minutes": 10
},
"metadata": {
"purpose": "account_verification"
}
}'
Response:
{
"session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"channels_sent": {
"email": {
"success": true,
"message_id": "msg_880h1733h52e74g7d049779988773333"
},
"sms": {
"success": true,
"message_id": "msg_880h1733h52e74g7d049779988774444"
},
"whatsapp": {
"success": true,
"message_id": "msg_880h1733h52e74g7d049779988775555"
}
},
"expires_at": "2024-01-15T10:45:00.000Z",
"verification_mode": "any"
}
Example 5: Sandbox Mode (Testing)โ
Test OTP flow without sending real messages or incurring charges.
curl -X POST https://api.sendmator.com/api/v1/otp/send \
-H "X-API-Key: sk_test_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"channels": ["email", "sms"],
"recipients": {
"email": "test@example.com",
"sms": "+1234567890"
},
"sandbox_mode": true
}'
Response (Sandbox Mode):
{
"session_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"channels_sent": {
"email": {
"success": true,
"message_id": "msg_sandbox_990i2844i63f85h8e150880099884444"
},
"sms": {
"success": true,
"message_id": "msg_sandbox_990i2844i63f85h8e150880099885555"
}
},
"sandbox_otps": {
"email": "123456",
"sms": "123456"
},
"expires_at": "2024-01-15T10:45:00.000Z",
"verification_mode": "any"
}
Response Fieldsโ
Success Responseโ
| Field | Type | Description |
|---|---|---|
session_token | string | JWT token for verifying OTP later |
channels_sent | object | Status of each channel send attempt |
expires_at | string | ISO 8601 timestamp when session expires |
verification_mode | string | Verification mode: "any" or "all" |
sandbox_otps | object | OTP codes (only in sandbox mode) |
Channels Sent Objectโ
Each channel in channels_sent contains:
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the OTP was sent successfully |
message_id | string | Unique message identifier for tracking |
Error Responseโ
{
"statusCode": 400,
"message": "Invalid recipient email address",
"error": "Bad Request"
}
Common Error Responsesโ
| Status Code | Error | Cause |
|---|---|---|
| 400 | Invalid recipient | Email/phone format is incorrect |
| 400 | Invalid channel | Channel not supported |
| 400 | Missing recipients | Recipients object missing required fields |
| 401 | Invalid API key | API key is missing or incorrect |
| 402 | Insufficient balance | Not enough wallet credits |
| 429 | Rate limit exceeded | Too many OTP requests |
Recipient Format Validationโ
Emailโ
- Must be a valid email address
- Example:
user@example.com
Phone Number (SMS/WhatsApp)โ
- Must be in E.164 format
- Include country code with
+prefix - No spaces, dashes, or parentheses
- Examples:
- โ
+1234567890(US) - โ
+919876543210(India) - โ
+442071234567(UK) - โ
1234567890(missing + and country code) - โ
+1 (234) 567-8900(contains formatting)
- โ
Best Practicesโ
1. Securityโ
- Store the token securely on the client side
- Never log or expose OTP codes in production
- Use short expiry times (5-10 minutes) for sensitive operations
- Implement rate limiting on your application side
- Monitor failed attempts and block suspicious activity
2. User Experienceโ
- Clear instructions - Tell users where to find the OTP
- Multiple channels - Offer SMS + WhatsApp for better deliverability
- Resend option - Allow users to request a new OTP
- Show expiry time - Display countdown timer
- Error handling - Provide helpful error messages
3. Configurationโ
- OTP length: Use 6 digits for balance of security and usability
- Expiry time:
- 5 minutes for 2FA/login
- 10 minutes for verification workflows
- 15 minutes for password resets
- Max attempts: 3 attempts is recommended
4. Metadata Usageโ
Store context for later retrieval:
{
"metadata": {
"user_id": "user_12345",
"purpose": "email_verification",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"app_version": "2.1.0"
}
}
5. Auto-Contact Creationโ
Enable add_contact: true to automatically add verified users to your contacts:
{
"add_contact": true
}
This creates a contact record when the user successfully verifies any channel.
Rate Limitsโ
To prevent abuse:
- 5 OTP sends per 5 minutes per user
- 20 OTP sends per hour per IP address
- 100 active sessions per user
Sandbox vs Productionโ
| Feature | Sandbox Mode | Production Mode |
|---|---|---|
| Messages Sent | โ No | โ Yes |
| OTPs Returned | โ Yes | โ No |
| Wallet Charged | โ No | โ Yes |
| Use Case | Testing | Live users |
Next Stepsโ
- Verify OTP - Learn how to verify OTP codes
- OTP Overview - Understand OTP concepts
- Authentication - Set up API keys