ZendOTP

Secure one-time password (OTP) verification service for SMS and WhatsApp channels.

Quick Start

1. Send OTP

POST /otp/send
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "phone_number": "+233201234567",
  "app": "my_ecommerce_app",
  "channel": "sms",
  "expiry": 10,
  "length": 6
}

Response:

{
  "id": "otp_64f8a1b2c3d4e5f6",
  "phone_number": "+233201234567",
  "app": "my_ecommerce_app",
  "channel": "sms",
  "expiry_minutes": 10,
  "length": 6,
  "status": "sent",
  "created_at": "2024-01-15T10:20:00Z",
  "expires_at": "2024-01-15T10:30:00Z"
}

2. Check Status

GET /otp/{id}/status
x-api-key: YOUR_API_KEY

Response:

{
  "id": "otp_64f8a1b2c3d4e5f6",
  "phone_number": "+233201234567",
  "app": "my_ecommerce_app",
  "channel": "sms",
  "status": "pending",
  "attempts": 0,
  "max_attempts": 3,
  "created_at": "2024-01-15T10:20:00Z",
  "expires_at": "2024-01-15T10:30:00Z",
  "verified_at": null
}

3. Verify OTP

POST /otp/{id}/verify
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "code": "123456"
}

Response:

{
  "success": true,
  "message": "OTP verified successfully",
  "verified_at": "2024-01-15T10:25:00Z",
  "attempts_remaining": 2
}

API Endpoints

Send OTP

POST /otp/send

Send a one-time password to a phone number.

Request Body:

{
  "phone_number": "+233201234567",
  "app": "my_ecommerce_app",
  "channel": "sms",
  "expiry": 10,
  "length": 6
}

Parameters:

FieldTypeRequiredDescription
phone_numberstringPhone number in international format
appstringApplication identifier
channelstringsms or whatsapp
expirynumberExpiry time in minutes (default: 10)
lengthnumberOTP length (default: 6)

Get OTP Status

GET /otp/{id}/status

Check the status of an OTP.

Verify OTP

POST /otp/{id}/verify

Verify an OTP code.

Request Body:

{
  "code": "123456"
}

Get Analytics

GET /otp/analytics

Get OTP analytics and statistics.

Query Parameters:

  • app (optional): Filter by application
  • days (optional): Number of days to analyze (default: 30)

Status Values

StatusDescription
sentOTP sent successfully
pendingWaiting for verification
verifiedSuccessfully verified
expiredOTP expired
failedVerification failed

Error Responses

{
  "success": false,
  "message": "Invalid OTP code",
  "attempts_remaining": 2
}

Example Usage

// Send OTP
const response = await fetch('https://api.tryzend.com/otp/send', {
  method: 'POST',
  headers: {
    'x-api-key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phone_number: '+233201234567',
    app: 'my_ecommerce_app',
    channel: 'sms',
    expiry: 10,
    length: 6
  })
});

const { id } = await response.json();

// Verify OTP
const verifyResponse = await fetch(`https://api.tryzend.com/otp/${id}/verify`, {
  method: 'POST',
  headers: {
    'x-api-key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ code: '123456' })
});

const result = await verifyResponse.json();
console.log(result.success); // true if verified

Features

  • SMS & WhatsApp Support - Send OTPs via SMS or WhatsApp
  • Flexible Configuration - Customizable expiry time and OTP length
  • App Categorization - Track OTPs by application
  • Security Features - Rate limiting, attempt limits, automatic expiry
  • Analytics & Reporting - Detailed analytics and cost tracking
  • Real-time Status - Check OTP status and verification attempts
  • Auto Cleanup - Automatic cleanup of expired OTPs

Best Practices

  1. Set Appropriate Expiry - Use shorter expiry times for security (5-15 minutes)
  2. Monitor Analytics - Track verification rates and optimize your flow
  3. Handle Errors - Implement proper error handling for failed verifications
  4. Rate Limiting - Respect rate limits to avoid service disruption
  5. Secure Storage - Don't store OTP codes in client-side storage