One-time passcodes (OTP)
Send and verify one-time codes by SMS without writing OTP logic. We generate the code, send it as a regular SMS from an approved sender name and check it. The code itself is never stored — only a keyed hash — and never returned to you.
Send
bash
curl -X POST https://smsprovider-web.vercel.app/api/v1/otp/send \
-H "Authorization: Bearer $BATLER_API_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"to": "0501234567", "app_id": "login", "valid_minutes": 5, "text": "Your MyBrand login code: [code]"}'| Field | Default | Notes |
|---|---|---|
to | — | Israeli mobile only |
app_id | default | Separates flows (login, payment approval…). Each app_id has its own active code |
valid_minutes | 5 | 1–15 |
max_tries | 3 | 3–5 wrong attempts, then the code is invalidated |
code_length | 6 | 4–8 digits |
text | Hebrew default with [code] | Must contain [code] exactly once |
from | default sender | An approved sender name (if none: the platform's OTP sender name) |
Response: { "session_id", "expires_at" }. Cost: by message segments (usually one credit); verification is free. The message appears in your message history with its delivery report, with the code masked.
Verify
ts
const { verified, tries_left } = await sms.otp.verify({ to: "0501234567", code: userInput, app_id: "login" });
if (!verified) showError(`Wrong code, ${tries_left} attempts left`);Limits and protections
- Up to 3 codes per phone per 10 minutes and 10 per hour per account. Exceeding returns 429
otp_rate_limited. - Do not auto-retry
verify— every call counts as an attempt. - Webhook events:
otp.verified,otp.failed. - Channel: SMS only.