# OTP Authentication

> Send verification codes via WhatsApp Authentication templates

WhatsApp Authentication templates provide a secure, high-delivery-rate channel for sending one-time passwords (OTP) and verification codes. This guide covers creating, submitting, and sending OTP messages.

## Overview

Authentication templates are purpose-built for verification codes:

- **High delivery rates** - WhatsApp messages have 98%+ open rates
- **Instant delivery** - Codes arrive in seconds
- **User-friendly** - Copy button or auto-fill on Android
- **Cost-effective** - Lowest messaging rates of all template categories
- **Secure** - End-to-end encrypted delivery

## Prerequisites

Before creating OTP templates, ensure you have:

  - [Meta Business Verification](https://www.zavu.dev/docs/guides/whatsapp/connect-whatsapp): Your Meta Business account must be verified
  - [WhatsApp Connected](https://www.zavu.dev/docs/guides/whatsapp/connect-whatsapp): A sender with WhatsApp Business Account configured
  - **Payment Method**: Valid payment method configured in Meta Business Manager
  - [API Key](https://www.zavu.dev/docs/authentication): A Zavu API key for your project

## Step 1: Create OTP Template

### Via Dashboard

1. Navigate to **Senders** in your dashboard
2. Select the sender with WhatsApp connected
3. Go to the **Templates** tab
4. Click **Create Template**
5. Configure the template:
   - **Name**: Use a descriptive name like `otp_verification`
   - **Channel**: Select WhatsApp only
   - **Category**: Select **AUTHENTICATION**
   - **Language**: Choose your language (e.g., `en`)
6. Configure the OTP button:
   - **Button Type**: Choose `Copy Code` or `One-Tap` (Android only)
7. Optional settings:
   - Enable **Security Recommendation** to add "Do not share this code"
   - Set **Code Expiration** (1-90 minutes)
8. Click **Create**

### Via API

```typescript
import Zavudev from '@zavudev/sdk';

const zavu = new Zavudev({
  apiKey: process.env["ZAVUDEV_API_KEY"],
});

const template = await zavu.templates.create({
  name: 'otp_verification',
  language: 'en',
  body: '{{1}} is your verification code.',
  category: 'AUTHENTICATION',
  buttons: [{
    type: 'otp',
    text: 'Copy code',
    otpType: 'COPY_CODE'
  }],
  addSecurityRecommendation: true,
  codeExpirationMinutes: 10
});

console.log('Template ID:', template.id);
console.log('Status:', template.status); // "draft"
```

```bash
curl -X POST https://api.zavu.dev/v1/templates \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "otp_verification",
    "language": "en",
    "body": "{{1}} is your verification code.",
    "category": "AUTHENTICATION",
    "buttons": [{
      "type": "otp",
      "text": "Copy code",
      "otpType": "COPY_CODE"
    }],
    "addSecurityRecommendation": true,
    "codeExpirationMinutes": 10
  }'
```

> **Info:**
> Meta auto-generates the message body for authentication templates. The format is always: `{{1}} is your verification code.` followed by optional security text and expiration.

## Step 2: Submit for Meta Approval

Authentication templates typically receive fast approval (within hours).

### Via Dashboard

1. Go to **Senders** > Select sender > **Templates** tab
2. Find your template with "Draft" status
3. Click the **...** menu and select **Submit for Approval**

### Via API

```typescript
await zavu.templates.submit({
  templateId: template.id,
  senderId: 'sender_abc123'
});

// Check status
const updated = await zavu.templates.retrieve({
  templateId: template.id
});
console.log('Status:', updated.status); // "pending" -> "approved"
```

```bash
curl -X POST https://api.zavu.dev/v1/templates/tmpl_abc123/submit \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "sender_abc123"
  }'
```

### Expected Approval Time

| Template Type | Typical Approval Time |
|---------------|----------------------|
| AUTHENTICATION | 1-4 hours |
| UTILITY | 24-48 hours |
| MARKETING | 24-72 hours |

> **Tip:**
> Authentication templates are prioritized by Meta and usually approved within hours. If approval takes longer, ensure your Meta Business is fully verified.

## Step 3: Send OTP Messages

Once approved, send verification codes to users:

```typescript
import Zavudev from '@zavudev/sdk';

const zavu = new Zavudev({
  apiKey: process.env["ZAVUDEV_API_KEY"],
});

// Generate your OTP code
const otpCode = '123456';

const message = await zavu.messages.send({
  to: '+14155551234',
  messageType: 'template',
  content: {
    templateId: 'tmpl_abc123',
    templateVariables: {
      '1': otpCode  // The OTP code
    }
  }
});

console.log('Message ID:', message.id);
console.log('Status:', message.status);
```

```bash
curl -X POST https://api.zavu.dev/v1/messages \
  -H "Authorization: Bearer $ZAVUDEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155551234",
    "messageType": "template",
    "content": {
      "templateId": "tmpl_abc123",
      "templateVariables": {
        "1": "123456"
      }
    }
  }'
```

### What the User Sees

The user receives a message like:

```
123456 is your verification code.

For your security, do not share this code.

This code expires in 10 minutes.

[Copy code]
```

## OTP Button Types

### COPY_CODE (Recommended)

The **Copy Code** button allows users to tap and copy the code to their clipboard.

```typescript
buttons: [{
  type: 'otp',
  text: 'Copy code',
  otpType: 'COPY_CODE'
}]
```

**Benefits:**
- Works on all platforms (iOS, Android, Web)
- Simple user experience
- No additional configuration required

### ONE_TAP (Android Only)

The **One-Tap** button enables automatic code filling in your Android app.

```typescript
buttons: [{
  type: 'otp',
  text: 'Copy code',
  otpType: 'ONE_TAP',
  packageName: 'com.yourcompany.app',
  signatureHash: 'K8a+W1234...'
}]
```

**Requirements:**
- Android app only
- Must provide `packageName` (Android package name)
- Must provide `signatureHash` (Android app signature hash)

**How to get your signature hash:**

1. In your Android app, use the SMS Retriever API helper:

```java
AppSignatureHelper helper = new AppSignatureHelper(context);
ArrayList<String> signatures = helper.getAppSignatures();
// Use the first signature
String signatureHash = signatures.get(0);
```

2. The hash is an 11-character string like `K8a+W1234ab`

> **Warning:**
> One-Tap auto-fill only works on Android. iOS users will see a standard copy button. Always ensure your flow works without auto-fill as a fallback.

## Template Options

### Security Recommendation

Add a security disclaimer to your OTP message:

```typescript
addSecurityRecommendation: true
```

This adds: *"For your security, do not share this code."*

### Code Expiration

Display when the code expires:

```typescript
codeExpirationMinutes: 10  // 1-90 minutes
```

This adds: *"This code expires in 10 minutes."*

## Best Practices

  - **Use Short Expiration**: Set expiration to 5-10 minutes for security. Shorter is better.
  - **Enable Security Warning**: Always enable `addSecurityRecommendation` to protect users from phishing.
  - **Generate Secure Codes**: Use cryptographically secure random number generators for OTP codes.
  - **Rate Limit Requests**: Limit OTP requests per user to prevent abuse (e.g., 5 per hour).

### OTP Code Guidelines

- Use 6-digit numeric codes for balance of security and usability
- Generate codes using secure random functions
- Store codes with expiration timestamps
- Invalidate codes after successful verification
- Limit verification attempts (e.g., 3 tries per code)

```typescript
// Example: Generate secure OTP
import crypto from 'crypto';

function generateOTP(): string {
  return crypto.randomInt(100000, 999999).toString();
}
```

## Common Issues

| Issue | Solution |
|-------|----------|
| Template rejected | Ensure category is AUTHENTICATION and content is purely verification-related |
| Code not displaying | Check that variable `{{1}}` is provided in `templateVariables` |
| One-Tap not working | Verify `packageName` and `signatureHash` are correct for your Android app |
| Slow delivery | Check recipient's WhatsApp status and your sender's quality rating |
| Button not showing | Ensure the template has `buttons` configured with OTP type |

## Webhook Events

Track OTP delivery status via webhooks:

```json
{
  "id": "evt_1702000000000_abc123",
  "type": "message.delivered",
  "timestamp": 1702000000000,
  "data": {
    "messageId": "msg_xyz789",
    "to": "+14155551234",
    "channel": "whatsapp",
    "status": "delivered"
  }
}
```

Configure webhooks to receive:
- `message.sent` - OTP accepted by WhatsApp
- `message.delivered` - OTP delivered to device
- `message.failed` - Delivery failed

See [Webhooks Guide](https://www.zavu.dev/docs/guides/receiving-messages/webhooks) for setup instructions.

## Next Steps

  - [Template Approval](https://www.zavu.dev/docs/guides/whatsapp/templates/approval): Learn more about the approval process and common rejection reasons
  - [Configure Webhooks](https://www.zavu.dev/docs/guides/receiving-messages/webhooks): Set up webhooks to track delivery status
  - [Smart Routing](https://www.zavu.dev/docs/guides/sending-messages/smart-routing): Use smart routing to automatically fall back to SMS if WhatsApp fails
  - [Rate Limiting](https://www.zavu.dev/docs/concepts/rate-limiting): Understand API rate limits for high-volume OTP sending
