Skip to main content

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:

  1. Template Check: Before sending, the system looks for templates with the reserved template keys
  2. Smart Routing:
    • Custom template found → Uses your template with your configured identities
    • No custom template → Uses Sendmator's default templates
  3. Cost Calculation: Charges are calculated based on the routing method (explained below)

Pricing Model

The OTP API uses a dual-charge model:

Cost ComponentDescriptionWhen Charged
Verification FeeInfrastructure fee for OTP session management, security, rate limiting, and verificationAlways charged upfront
Delivery CostCost to send the actual message (email/SMS/WhatsApp)Depends on routing method

Routing-Based Charging:

RouteDelivery CostVerification FeeTotal Upfront Charge
Custom TemplateCharged when message is sent✅ Charged upfrontVerification fee only
Default Template✅ Charged upfront✅ Charged upfrontDelivery + 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:

ChannelReserved Template KeyTemplate Type
Emailverify-api-otp-emailEmail Template
SMSverify-api-otp-smsSMS Template
WhatsAppverify-api-otp-whatsappWhatsApp Template
Critical: Exact Template Key Required

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:

VariableTypeDescriptionExample Value
otp_codestringThe verification code to display123456
expiry_minutesstringHow 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:

VariableTypeDescription
first_namestringRecipient's first name (if provided)
last_namestringRecipient'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:

  1. Template Key: MUST be exactly verify-api-otp-email
  2. Active Status: Set template as active
  3. Email Identity: Link to your verified email sender
  4. 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:

  1. Template Key: MUST be exactly verify-api-otp-sms
  2. Active Status: Set template as active
  3. Country Code: Configure for specific countries or use wildcard
  4. SMS Sender: Link to your registered phone number
SMS Template Country Matching

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:

  1. Template Key: MUST be exactly verify-api-otp-whatsapp
  2. Active Status: Set template as active
  3. WhatsApp Account: Link to your WhatsApp Business account
  4. 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:

  1. Template key mismatch

    • ❌ Wrong: verify-api-otp-Email (incorrect case)
    • ✅ Correct: verify-api-otp-email
  2. Template not active

    • Check: is_active must be true
  3. No sender configured

    • Email: Requires verified email sender
    • SMS: Requires registered phone number
    • WhatsApp: Requires WhatsApp Business account
  4. Template not found for country (SMS only)

    • SMS templates are country-specific
    • Create template for target country or use wildcard
  5. 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:

  1. Ensure variables use double curly braces: {{variable_name}}
  2. Check for typos in variable names (must match exactly: otp_code, expiry_minutes)
  3. 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:

  1. Custom template: Only verification fee charged upfront, delivery cost charged when message is sent
  2. 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_minutes variable
  • 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_minutes low (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_template in 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:

  1. 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
  2. Include required variables: {{otp_code}} and {{expiry_minutes}}

  3. Set template as active and link to your identity

  4. 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:

  1. Template check fails → Logs warning, uses default templates
  2. Template not active → Uses default templates
  3. Sender not configured → Uses default templates
  4. 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
Custom Template Keys

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