OTP integration and testing checklist
Keep API credentials server-side, validate phone numbers, throttle retries, expire OTPs, protect user data, check delivery statuses and match approved sender headers and templates. Test invalid requests and failed deliveries before production.
OTP SMS API Documentation for Developers
Integrate an OTP SMS API for developers into PHP, Node.js, Python or Laravel. Follow the examples for SMS API authentication, OTP requests and delivery statuses. Keep keys server-side and test approved templates, errors and retry behavior before production.
{
"status": "success",
"job_id": "job_94a8e2b19f03",
"phone": "919876543210",
"units_deducted": 1,
"balance_remaining": "₹482.40",
"operator_route": "AIRTEL_PRIORITY",
"dispatched_at": "2026-10-13T10:14:02.418Z"
}
OTP SMS REST API integration examples for popular backend stacks
Pick your language below and start verifying users in production within minutes.
<?php
declare(strict_types=1);
$apiKey = 'YOUR_NIZORA_API_KEY';
$payload = json_encode([
'phone' => '919876543210',
'otp' => '482910',
'template_id' => 'TPL_LOGIN_VERIFY'
]);
$ch = curl_init('https://nizorasms.com/api/v1/otp/send');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
],
CURLOPT_TIMEOUT => 5
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode((string)$response, true);
if ($httpCode === 200 && ($result['status'] ?? '') === 'success') {
echo "OTP Sent Successfully! Job ID: " . $result['job_id'];
} else {
echo "Failed to send OTP: " . ($result['message'] ?? 'Unknown error');
}
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
class OtpService
{
public function sendOtp(string $phone, string $otp): bool
{
$response = Http::withToken(config('services.nizorasms.api_key'))
->post('https://nizorasms.com/api/v1/otp/send', [
'phone' => $phone,
'otp' => $otp,
'template_id' => 'TPL_LOGIN_VERIFY',
]);
return $response->successful() && $response->json('status') === 'success';
}
}
const axios = require('axios');
async function dispatchOtp(phone, otpCode) {
try {
const response = await axios.post(
'https://nizorasms.com/api/v1/otp/send',
{
phone: phone,
otp: otpCode,
template_id: 'TPL_LOGIN_VERIFY'
},
{
headers: {
'Authorization': `Bearer ${process.env.NIZORA_API_KEY}`,
'Content-Type': 'application/json'
},
timeout: 5000
}
);
return response.data;
} catch (error) {
console.error('NizoraSMS Error:', error.response?.data || error.message);
throw error;
}
}
module.exports = { dispatchOtp };
import requests
def send_otp(phone: str, otp_code: str) -> dict:
url = "https://nizorasms.com/api/v1/otp/send"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
payload = {
"phone": phone,
"otp": otp_code,
"template_id": "TPL_LOGIN_VERIFY"
}
response = requests.post(url, json=payload, headers=headers, timeout=5)
response.raise_for_status()
return response.json()
# Example usage
# res = send_otp("919876543210", "591024")
# print("Job:", res.get("job_id"))
import 'dart:convert';
import 'package:http/http.dart' as http;
// Your own authenticated backend proxies SMS requests and stores the secret API key.
class NizoraSmsService {
static const String _backend = 'https://YOUR_APP_DOMAIN/api/send-otp';
static Future<bool> requestOtp(String phone) async {
final response = await http.post(
Uri.parse(_backend),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'phone': phone}),
);
return response.statusCode == 200;
}
}
// Protect this endpoint with authentication, rate limiting and anti-abuse checks.
// Do not put NizoraSMS API credentials or raw OTP verification logic in client code.
import okhttp3.*;
import java.io.IOException;
public class NizoraClient {
private static final OkHttpClient client = new OkHttpClient();
public static void sendOtp(String phone, String otp) throws IOException {
MediaType JSON = MediaType.get("application/json; charset=utf-8");
String json = "{\"phone\":\"" + phone + "\",\"otp\":\"" + otp + "\",\"template_id\":\"TPL_LOGIN_VERIFY\"}";
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https://nizorasms.com/api/v1/otp/send")
.header("Authorization", "Bearer YOUR_API_KEY")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}
curl -X POST https://nizorasms.com/api/v1/otp/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "919876543210",
"otp": "839120",
"template_id": "TPL_LOGIN_VERIFY"
}'
Standard API Response & Error Codes
Predictable JSON status codes for effortless error handling in your backend.
| HTTP Code | Status Code | Description | Recommended Action |
|---|---|---|---|
| 200 OK | success |
OTP accepted & pushed to carrier pipe | Store job_id for delivery receipt reconciliation |
| 400 Bad Request | ERR_INVALID_PHONE |
Mobile number format invalid or missing country code | Validate 10-digit Indian number before request |
| 401 Unauthorized | ERR_INVALID_KEY |
Bearer token missing, expired, or invalid | Verify your API key in the NizoraSMS panel |
| 402 Payment Required | ERR_LOW_BALANCE |
Purchased plan entitlement or available sending quota is insufficient | Check your active plan and usage in the dashboard |
| 429 Rate Limited | ERR_RATE_LIMIT |
Too many requests within sliding window | Respect throttle headers or request quota increase |
Frequently Asked Questions — Developer API Integration
Everything Indian developers need to know about API quotas, libraries, and carrier delivery.
How long does it take to integrate NizoraSMS OTP API?
Integration time varies by your backend, credentials, approved message templates and testing. Review the request, authentication and error-handling documentation before launching.
Which programming languages and frameworks are supported?
A server-side REST client can typically be built in PHP, Node.js, Python, Laravel, Java or other languages. Verify endpoint parameters and credentials in the current documentation.
How do I handle OTP delivery webhooks (DLR callbacks)?
Configure a callback URL if delivery webhooks are enabled for your account. Confirm the callback format, authentication and delivery-event behavior during integration testing; delivery timing varies by provider and network.
What is the API response time and delivery latency?
API response time and handset delivery time depend on network conditions, template approval, traffic and carrier routing. Measure both separately using test traffic and delivery reports; no fixed delivery-time guarantee is implied.
How do I integrate an OTP SMS API with PHP, Laravel or Node.js?
Make an authenticated HTTPS request from your backend, supply the mobile number and the account-approved OTP template, store the request ID for delivery status and validate the OTP on your own server. The API examples below illustrate these steps; confirm exact fields in your account.
Should I put OTP SMS API credentials in a Flutter or Android app?
No. A mobile app or browser should call your own backend. Keep the messaging API key on the server and set rate limits, authentication and OTP expiration in the application.