Use case · OTP
OTP SMS in Bangladesh that arrives while your user is still waiting
One OTP SMS API to generate, send and verify login and checkout codes. OTPs travel in their own priority lane with automatic failover, so a campaign never delays a verification code.
The problem
A one-time password is only useful for a few minutes. If the code arrives late, the user taps "resend", gets two codes, types the wrong one and gives up. On a checkout page that is a lost order; on a sign-up page it is a lost customer.
Most OTP problems are not in your code. They come from the SMS route: one upstream provider slows down, or your own marketing blast fills the same queue as your login codes. Building code generation, hashing, expiry, retry limits and abuse protection yourself takes time, and it is easy to get one of them wrong.
How BitSMS solves it
We generate and verify the code
A priority lane for OTP
Failover when a route struggles
Built-in limits against abuse
In your code
Send and verify an OTP in two calls
The first call sends the code and returns an otp_id. The second checks what the user typed. Codes expire after 5 minutes by default; set ttl_seconds anywhere from 1 to 10 minutes.
- Write the SMS in your own words: the template must contain {{code}} and may use {{app_name}} and {{ttl_minutes}}.
- Send an Idempotency-Key so a network retry never sends a second code.
- Bangla templates work too; the message is sent as Unicode automatically.
# 1. Send: BitSMS generates the code and never returns it.
curl https://sms-api.bitcommerz.com/v1/otp \
-H "Authorization: Bearer $BITSMS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: login-7f3a91" \
-d '{"to": "01712345678", "app_name": "MyShop"}'
# → 202 {"otp_id": "…", "message_id": "…", "expires_at": "…"}
# 2. Verify what the user typed.
curl https://sms-api.bitcommerz.com/v1/otp/$OTP_ID/verify \
-H "Authorization: Bearer $BITSMS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"code": "482913"}'
# → 200 {"verified": true}const headers = {
Authorization: `Bearer ${process.env.BITSMS_API_KEY}`,
"Content-Type": "application/json",
};
// 1. Send
const sent = await fetch("https://sms-api.bitcommerz.com/v1/otp", {
method: "POST",
headers: { ...headers, "Idempotency-Key": `login-${sessionId}` },
body: JSON.stringify({ to: "01712345678", app_name: "MyShop" }),
}).then((r) => r.json());
// 2. Verify
const result = await fetch(`https://sms-api.bitcommerz.com/v1/otp/${sent.otp_id}/verify`, {
method: "POST",
headers,
body: JSON.stringify({ code: userInput }),
}).then((r) => r.json());
if (result.verified) { /* sign the user in */ }<?php
function bitsms(string $path, array $body, array $extra = []): array {
$ch = curl_init("https://sms-api.bitcommerz.com/v1" . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array_merge([
"Authorization: Bearer " . getenv("BITSMS_API_KEY"),
"Content-Type: application/json",
], $extra),
CURLOPT_POSTFIELDS => json_encode($body),
]);
return json_decode(curl_exec($ch), true);
}
$otp = bitsms("/otp", ["to" => "01712345678", "app_name" => "MyShop"],
["Idempotency-Key: login-" . session_id()]);
$check = bitsms("/otp/" . $otp["otp_id"] . "/verify", ["code" => $_POST["code"]]);
if ($check["verified"] ?? false) { /* sign the user in */ }auth = {"Authorization": f"Bearer {os.environ['BITSMS_API_KEY']}"}
otp = requests.post(
"https://sms-api.bitcommerz.com/v1/otp",
headers={**auth, "Idempotency-Key": f"login-{session_id}"},
json={"to": "01712345678", "app_name": "MyShop"},
timeout=10,
).json()
check = requests.post(
f"https://sms-api.bitcommerz.com/v1/otp/{otp['otp_id']}/verify",
headers=auth,
json={"code": user_input},
timeout=10,
).json()
if check["verified"]:
... # sign the user intype otp struct {
OtpID string `json:"otp_id"`
}
var sent otp
post("/v1/otp", "login-"+sessionID, map[string]any{"to": "01712345678", "app_name": "MyShop"}, &sent)
var result struct {
Verified bool `json:"verified"`
AttemptsRemaining int `json:"attempts_remaining"`
}
post("/v1/otp/"+sent.OtpID+"/verify", "", map[string]any{"code": userInput}, &result)
// post marshals body, sets Authorization (and Idempotency-Key when non-empty),
// sends to https://sms-api.bitcommerz.com and decodes the JSON response into out.Frequently asked questions
How fast is OTP SMS delivery in Bangladesh?
BitSMS accepts your request and queues the OTP in its own priority lane straight away, ahead of transactional and bulk messages. The final hop depends on the operator, and the message status shows you exactly when it was sent and delivered.
Do I have to generate the OTP code myself?
No. BitSMS generates the code, sends it, stores only a hash and verifies what the user types. You never handle the code. If you prefer your own codes, you can still send them as a normal transactional SMS.
How many OTPs can one number receive?
Up to 3 OTPs per number in 10 minutes and 10 per day, per account. Verification allows 5 wrong attempts; after that the user needs a new code.
Can the OTP SMS be in Bangla?
Yes. Write the template in Bangla and include {{code}}. Bangla SMS hold 70 characters per part, so keep the template short to stay within one part.