REST API

OTP API — Secure Authentication & Verification | BulkSMS.ca

REST API for generating and verifying OTP (One-Time Password) messages. Sub-5-second delivery, retry logic, voice fallback, and fraud detection.

Base URL: https://api.bulksms.ca

How does the BulkSMS.ca OTP API work?

The BulkSMS.ca OTP API generates and delivers one-time passwords via SMS with sub-5-second delivery. It includes automatic retry logic, voice call fallback for failed SMS deliveries, fraud detection, and configurable OTP expiry. The API supports custom OTP length (4-8 digits), alphanumeric codes, and bulk verification. Authentication uses API keys with TLS 1.3 encryption.

Authentication

Authorization Header
Authorization: Bearer YOUR_API_KEY Content-Type: application/json

Include your API key in the Authorization header of every request. API keys are available in your BulkSMS.ca dashboard under Settings > API Keys.

API Endpoints

POST/v2/send-otp

Generate and send OTP to a phone number.

Auth: API Key
Request Body
{ "to": "9198XXXXXXXX", "template_id": "TPL_12345", "otp_length": 6, "otp_type": "numeric", "expiry": 300 }
Response (200 OK)
{ "status": "success", "message_id": "msg_otp_001", "to": "9198XXXXXXXX", "expires_at": "2026-06-15T14:35:00+05:30" }
POST/v2/verify-otp

Verify an OTP entered by the user.

Auth: API Key
Request Body
{ "to": "9198XXXXXXXX", "otp": "123456" }
Response (200 OK)
{ "status": "success", "verified": true, "message": "OTP verified successfully" }
POST/v2/resend-otp

Resend OTP to the same number.

Auth: API Key
Request Body
{ "to": "9198XXXXXXXX" }
Response (200 OK)
{ "status": "success", "message_id": "msg_otp_002", "resent": true }
POST/v2/send-otp-voice

Send OTP via voice call (TTS).

Auth: API Key
Request Body
{ "to": "9198XXXXXXXX", "otp_length": 6, "language": "en" }
Response (200 OK)
{ "status": "success", "call_id": "call_001", "to": "9198XXXXXXXX" }
GET/v2/otp-status/{message_id}

Check OTP delivery status.

Auth: API Key
Response (200 OK)
{ "message_id": "msg_otp_001", "to": "9198XXXXXXXX", "status": "delivered", "delivered_at": "2026-06-15T14:30:05+05:30" }

SDK Code Examples

cURL
curl (built-in)
curl -X POST https://api.bulksms.ca/v2/send-otp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "9198XXXXXXXX",
    "template_id": "TPL_12345",
    "otp_length": 6
  }'
Python
pip install requests
import requests

response = requests.post("https://api.bulksms.ca/v2/send-otp",
  headers={"Authorization": "Bearer YOUR_API_KEY"},
  json={"to": "9198XXXXXXXX", "template_id": "TPL_12345", "otp_length": 6}
)
print(response.json())
Node.js
npm install axios
const axios = require('axios');

// Send OTP
const send = await axios.post('https://api.bulksms.ca/v2/send-otp',
  { to: '9198XXXXXXXX', template_id: 'TPL_12345', otp_length: 6 },
  { headers: { Authorization: 'Bearer YOUR_API_KEY' }}
);

// Verify OTP
const verify = await axios.post('https://api.bulksms.ca/v2/verify-otp',
  { to: '9198XXXXXXXX', otp: '123456' },
  { headers: { Authorization: 'Bearer YOUR_API_KEY' }}
);
console.log(verify.data.verified);
PHP
composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client();

// Send OTP
$res = $client->post('https://api.bulksms.ca/v2/send-otp', [
  'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'],
  'json' => ['to' => '9198XXXXXXXX', 'template_id' => 'TPL_12345']
]);
$data = json_decode($res->getBody(), true);

Webhooks

Configure webhooks in your dashboard to receive real-time event notifications.

Supported Events

otp.deliveredotp.failedotp.expiredotp.verifiedvoice.otp.delivered
Webhook Payload Example
{
  "event": "otp.delivered",
  "message_id": "msg_otp_001",
  "to": "9198XXXXXXXX",
  "status": "delivered",
  "delivery_time_ms": 3200,
  "timestamp": "2026-06-15T14:30:05+05:30"
}

Error Codes

Code
Description
200
Success — OTP sent or verified
400
Bad Request — Invalid phone or template
401
Unauthorized — Invalid API key
403
Forbidden — Template not approved
410
Expired — OTP has expired
422
Invalid OTP — Incorrect OTP entered
429
Too Many Attempts — Rate limited

FAQs

How fast is OTP delivery?

OTP messages are delivered in under 5 seconds on average. Our priority routing ensures instant delivery across all Indian telecom operators.

What happens if OTP SMS fails?

If SMS delivery fails, the API automatically retries once. If still undelivered, a voice call OTP is sent as fallback (if enabled in your settings).

Can I set custom OTP expiry?

Yes, OTP expiry is configurable from 1 minute to 24 hours. Default expiry is 5 minutes.

Is the OTP API secure?

Yes, all OTP traffic is encrypted with TLS 1.3. OTPs are not stored on our servers after expiry. We also support fraud detection to block suspicious requests.

Can I send alphanumeric OTPs?

Yes, set otp_type to "alphanumeric" in the request. Default is numeric (6 digits).

Ready to Integrate?

Get your API key and start building.

All APIs