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: Bearer YOUR_API_KEY
Content-Type: application/jsonInclude 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
/v2/send-otpGenerate and send OTP to a phone number.
Auth: API Key{
"to": "9198XXXXXXXX",
"template_id": "TPL_12345",
"otp_length": 6,
"otp_type": "numeric",
"expiry": 300
}{
"status": "success",
"message_id": "msg_otp_001",
"to": "9198XXXXXXXX",
"expires_at": "2026-06-15T14:35:00+05:30"
}/v2/verify-otpVerify an OTP entered by the user.
Auth: API Key{
"to": "9198XXXXXXXX",
"otp": "123456"
}{
"status": "success",
"verified": true,
"message": "OTP verified successfully"
}/v2/resend-otpResend OTP to the same number.
Auth: API Key{
"to": "9198XXXXXXXX"
}{
"status": "success",
"message_id": "msg_otp_002",
"resent": true
}/v2/send-otp-voiceSend OTP via voice call (TTS).
Auth: API Key{
"to": "9198XXXXXXXX",
"otp_length": 6,
"language": "en"
}{
"status": "success",
"call_id": "call_001",
"to": "9198XXXXXXXX"
}/v2/otp-status/{message_id}Check OTP delivery status.
Auth: API Key{
"message_id": "msg_otp_001",
"to": "9198XXXXXXXX",
"status": "delivered",
"delivered_at": "2026-06-15T14:30:05+05:30"
}SDK Code Examples
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
}'pip install requestsimport 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())npm install axiosconst 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);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
{
"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
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).