SMS
SecureOTP delivers OTP codes over SMS through a global carrier network. This is the simplest channel to set up — no additional configuration is required beyond an active API key and sufficient credits.
Send an OTP
POST /api/v1/otp/sms/send
Sends a 6-character OTP to the specified phone number via SMS.
Request
curl -X POST https://otp.applicanity.com/api/v1/otp/sms/send \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "phone": "+628123456789" }'Body parameters
| Parameter | Type | Required | Description | | --- | --- | --- | --- | | phone | string | Yes | Recipient phone number in E.164 format (e.g. +628123456789) |
Response
{
"message": "OTP sent successfully",
"expiresAt": "2026-06-09T10:05:00.000Z"
}| Field | Type | Description | | --- | --- | --- | | message | string | Confirmation message | | expiresAt | string (ISO 8601) | When the code expires. Use this to drive countdown timers in your UI |
Error responses
| Status | Error | Description | | --- | --- | --- | | 400 | Phone number is required | phone field missing from request body | | 402 | Insufficient balance | Account balance is below the SMS cost (499 credits) | | 500 | Failed to send OTP | Carrier error or internal failure |
Verify an OTP
POST /api/v1/otp/sms/verify
Checks whether a code submitted by the user is valid for the given phone number.
Request
curl -X POST https://otp.applicanity.com/api/v1/otp/sms/verify \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "phone": "+628123456789", "code": "A3K9PZ" }'Body parameters
| Parameter | Type | Required | Description | | --- | --- | --- | --- | | phone | string | Yes | The phone number that received the OTP | | code | string | Yes | The code entered by the user |
Response — success
{
"success": true,
"message": "OTP verified successfully",
"phone": "+628123456789"
}Response — failure
{
"success": false,
"message": "Invalid or expired OTP"
}| Field | Type | Description | | --- | --- | --- | | success | boolean | true if the code matched and was valid | | message | string | Human-readable outcome | | phone | string | Echoed phone number (only on success) |
A failed verification returns HTTP 400. Once a code is verified successfully it is consumed — the same code cannot be verified again.
JavaScript Example
// 1. Send OTP
const sendRes = await fetch('/api/v1/otp/sms/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SECUREOTP_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ phone: '+628123456789' }),
})
const { expiresAt } = await sendRes.json()
// 2. Later — verify code entered by user
const verifyRes = await fetch('/api/v1/otp/sms/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SECUREOTP_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ phone: '+628123456789', code: userInput }),
})
const { success } = await verifyRes.json()
if (success) {
// proceed with authenticated action
}Notes
- Phone numbers must include the country code in E.164 format (e.g.
+62for Indonesia,+1for the US). - Sending a new OTP to the same number automatically invalidates any previous unused code for that number.
- The OTP message includes your account name, the code, and the TTL. See OTP API for message format details.