OTP Custom Templates
Customize your OTP messages by creating templates with reserved template keys. When you have custom templates configured, Sendmator automatically uses them instead of the default system templates.
Overview
By default, the OTP API uses Sendmator's built-in templates to send verification codes. However, you can create custom templates with specific reserved template keys to:
- Brand your OTPs with your company's logo, colors, and messaging
- Customize the content and layout of OTP messages
- Use your own identities (verified email addresses, SMS senders, WhatsApp Business accounts)
- Control delivery costs through your own messaging infrastructure
How It Works
Automatic Template Detection
When you call the OTP API, Sendmator automatically checks if you have custom templates configured:
- Template Check: Before sending, the system looks for templates with the reserved template keys
- Smart Routing:
- ✅ Custom template found → Uses your template with your configured identities
- ❌ No custom template → Uses Sendmator's default templates
- Cost Calculation: Charges are calculated based on the routing method (explained below)
Pricing Model
The OTP API uses a dual-charge model:
| Cost Component | Description | When Charged |
|---|---|---|
| Verification Fee | Infrastructure fee for OTP session management, security, rate limiting, and verification | Always charged upfront |
| Delivery Cost | Cost to send the actual message (email/SMS/WhatsApp) | Depends on routing method |
Routing-Based Charging:
| Route | Delivery Cost | Verification Fee | Total Upfront Charge |
|---|---|---|---|
| Custom Template | Charged when message is sent | ✅ Charged upfront | Verification fee only |
| Default Template | ✅ Charged upfront | ✅ Charged upfront | Delivery + Verification |
Example:
Email OTP with custom template:
- Upfront charge: $0.0005 (verification fee only)
- Delivery charge: $0.001 (charged when email is sent)
- Total cost: $0.0015
Email OTP with default template:
- Upfront charge: $0.0015 (delivery + verification)
- Delivery charge: $0 (already charged)
- Total cost: $0.0015
The total cost is the same, but the timing differs based on whether you use custom templates.
Reserved Template Keys
To enable custom OTP templates, create templates with these exact template keys:
| Channel | Reserved Template Key | Template Type |
|---|---|---|
verify-api-otp-email | Email Template | |
| SMS | verify-api-otp-sms | SMS Template |
verify-api-otp-whatsapp | WhatsApp Template |
The template key MUST match exactly (case-sensitive):
- ✅ Correct:
verify-api-otp-email - ❌ Wrong:
verify-api-otp-Email(wrong case) - ❌ Wrong:
verify_api_otp_email(underscore instead of dash) - ❌ Wrong:
verify-api-otp(missing channel)
If the template key doesn't match exactly, the system will use default templates instead.
Template Variables
Your custom templates MUST include these variables to display the OTP information:
| Variable | Type | Description | Example Value |
|---|---|---|---|
otp_code | string | The verification code to display | 123456 |
expiry_minutes | string | How long the OTP is valid (in minutes) | 10 |
Usage in templates: Wrap variable names in double curly braces: {{otp_code}} and {{expiry_minutes}}
Additional Variables (Optional)
You can also use standard recipient variables if available:
| Variable | Type | Description |
|---|---|---|
first_name | string | Recipient's first name (if provided) |
last_name | string | Recipient's last name (if provided) |
Setting Up Custom Templates
Step 1: Create Email Template
Create an email template with the reserved key verify-api-otp-email.
Example Email Template:
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.otp-code {
font-size: 32px;
font-weight: bold;
color: #2563eb;
letter-spacing: 8px;
text-align: center;
padding: 20px;
background: #f3f4f6;
border-radius: 8px;
margin: 20px 0;
}
.expiry { color: #6b7280; font-size: 14px; }
</style>
</head>
<body>
<div class="container">
<h1>Your Verification Code</h1>
<p>Hello{{#if first_name}} {{first_name}}{{/if}},</p>
<p>Use the following code to verify your account:</p>
<div class="otp-code">{{otp_code}}</div>
<p class="expiry">
This code will expire in <strong>{{expiry_minutes}} minutes</strong>.
</p>
<p>If you didn't request this code, please ignore this email.</p>
<hr>
<p style="color: #9ca3af; font-size: 12px;">
This is an automated message from YourCompany. Please do not reply.
</p>
</div>
</body>
</html>
Important Configuration:
- Template Key: MUST be exactly
verify-api-otp-email - Active Status: Set template as active
- Email Identity: Link to your verified email sender
- Subject Line: Example: "Your Verification Code"
Step 2: Create SMS Template
Create an SMS template with the reserved key verify-api-otp-sms.
Example SMS Template:
Your verification code is: {{otp_code}}
This code will expire in {{expiry_minutes}} minutes.
- YourCompany
Important Configuration:
- Template Key: MUST be exactly
verify-api-otp-sms - Active Status: Set template as active
- Country Code: Configure for specific countries or use wildcard
- SMS Sender: Link to your registered phone number
SMS templates are matched by country code. For example:
- Template with country
US→ Used for US phone numbers - Template with country
IN→ Used for Indian phone numbers - Create multiple templates for different countries if needed
Step 3: Create WhatsApp Template
Create a WhatsApp template with the reserved key verify-api-otp-whatsapp.
Example WhatsApp Template:
🔐 *Verification Code*
Your code: *{{otp_code}}*
Valid for {{expiry_minutes}} minutes.
If you didn't request this, please ignore.
- YourCompany
Important Configuration:
- Template Key: MUST be exactly
verify-api-otp-whatsapp - Active Status: Set template as active
- WhatsApp Account: Link to your WhatsApp Business account
- Template Approval: Ensure template is approved (if required by your provider)
Testing Your Custom Templates
1. Verify Template Configuration
Before testing, ensure:
- ✅ Template key matches exactly (case-sensitive)
- ✅ Template is marked as active (
is_active: true) - ✅ Template includes required variables (otp_code, expiry_minutes)
- ✅ Template is linked to your sender identity (email sender, phone number, or WhatsApp account)
2. Test with Sandbox Mode
Use sandbox mode to test without sending real messages:
POST /api/v1/otp/send
{
"channels": ["email"],
"recipients": {
"email": "test@example.com"
},
"sandbox_mode": true
}
Sandbox Response:
{
"success": true,
"session_id": "otp_abc123...",
"token": "eyJhbGc...",
"channels_sent": ["email"],
"channels_results": {
"email": {
"success": true,
"trigger_id": "trigger_xyz789",
"execution_id": "exec_def456",
"used_custom_template": true // ✅ Confirms custom template was used
}
},
"sandbox_otps": {
"email": "123456" // OTP code for testing
}
}
3. Check Template Usage
Look for the used_custom_template field in the response:
true→ Your custom template was used ✅false→ Using default templates (check template configuration) ⚠️
Common Issues and Troubleshooting
Issue: Custom Template Not Being Used
Symptoms: used_custom_template: false in API response
Possible Causes:
-
Template key mismatch
- ❌ Wrong:
verify-api-otp-Email(incorrect case) - ✅ Correct:
verify-api-otp-email
- ❌ Wrong:
-
Template not active
- Check:
is_activemust betrue
- Check:
-
No sender configured
- Email: Requires verified email sender
- SMS: Requires registered phone number
- WhatsApp: Requires WhatsApp Business account
-
Template not found for country (SMS only)
- SMS templates are country-specific
- Create template for target country or use wildcard
-
Template database query error
- Check application logs for errors
- Verify database connectivity
Debugging Steps:
# 1. Check if template exists
GET /api/v1/templates?template_key=verify-api-otp-email
# 2. Verify template is active
# Look for: "is_active": true
# 3. Check sender configuration
# Verify your email sender, phone number, or WhatsApp account is configured
# 4. Test with sandbox mode
POST /api/v1/otp/send
{
"sandbox_mode": true,
"channels": ["email"],
"recipients": { "email": "test@example.com" }
}
# 5. Check the response field
# "used_custom_template": true/false
Issue: Variables Not Rendering
Symptoms: Template shows variable names literally instead of actual values
Solution:
- Ensure variables use double curly braces:
{{variable_name}} - Check for typos in variable names (must match exactly:
otp_code,expiry_minutes) - For email templates, verify HTML escaping isn't breaking the variable syntax
Issue: Charged Twice for Delivery
Symptoms: Wallet charged more than expected
Explanation: This should NOT happen with the current implementation. If you see double charging:
- Custom template: Only verification fee charged upfront, delivery cost charged when message is sent
- Default template: Delivery + verification charged upfront, no additional charges later
If you experience double charging, please contact support.
Best Practices
1. Template Design
- Keep it simple: OTP messages should be quick to read
- Highlight the code: Make the OTP code visually prominent
- Show expiry time: Always display the expiry time using the
expiry_minutesvariable - Security note: Remind users not to share the code
- Brand consistency: Match your application's design
2. Security
- Don't log OTPs: Never log the actual OTP code values in your application logs
- Use HTTPS: Always use secure connections for email links
- Short expiry: Keep
expiry_minuteslow (5-10 minutes) - Clear instructions: Tell users what action this OTP is for
3. Testing
- Test all channels: Verify email, SMS, and WhatsApp templates
- Test variables: Ensure OTP code and expiry time display correctly in sent messages
- Test countries: For SMS, test templates for different countries
- Use sandbox mode: Test without sending real messages during development
4. Monitoring
- Track template usage: Monitor
used_custom_templatein responses - Watch delivery rates: Check trigger execution status
- Monitor costs: Review wallet charges for delivery vs verification
- Alert on failures: Set up alerts if templates fail to load
Quick Setup Summary
To use custom OTP templates:
-
Create templates in your Sendmator dashboard with the exact reserved template keys:
- Email:
verify-api-otp-email - SMS:
verify-api-otp-sms - WhatsApp:
verify-api-otp-whatsapp
- Email:
-
Include required variables:
{{otp_code}}and{{expiry_minutes}} -
Set template as active and link to your identity
-
That's it! When you call
/api/v1/otp/send, your custom templates will be used automatically
Fallback Behavior
If custom templates are not found or fail to load, the system automatically uses default templates:
- Template check fails → Logs warning, uses default templates
- Template not active → Uses default templates
- Sender not configured → Uses default templates
- Template load error → Logs error, uses default templates
You don't need to do anything - the fallback is automatic and transparent.
Environment Variables (Optional)
You can customize the reserved template keys using environment variables (advanced use case):
# Default values (you don't need to set these)
OTP_EMAIL_TEMPLATE_KEY=verify-api-otp-email
OTP_SMS_TEMPLATE_KEY=verify-api-otp-sms
OTP_WHATSAPP_TEMPLATE_KEY=verify-api-otp-whatsapp
Only change these if you have a specific reason. Changing template keys means you must create templates with the new keys for custom templates to work.
Next Steps
- Send OTP - Learn how to send OTPs with custom templates
- Verify OTP - Learn how to verify OTPs
- OTP API Overview - Back to OTP API documentation