Home SMS OTP Pricing Blog Log in Get started

How to Add OTP Verification to Your App in Eswatini

Two API calls, real phone numbers, no SDK. Working code for verifying a user in minutes.

If your app needs to confirm a user actually controls the phone number they signed up with, a one-time password (OTP) sent by SMS is the standard way to do it. This is the complete, working path: send a code, verify the code, know your user is real.

No SDK to install. Two REST calls, JSON in and out.

1. Send the code

Call /otp/send with the recipient's phone number. Lunyazi generates a 6-digit code, stores it, and delivers it by SMS.

// Step 1: send a code to the user's phone const sendResult = await fetch("https://api.lunyazi.com/otp/send", { method: "POST", headers: { "X-Api-Key": process.env.LUNYAZI_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ channel: "sms", recipient: "+26876001234", app_name: "MyApp" }) }).then(r => r.json()); // { "success": true, "otp_id": "otp_7f3a...", "expires_in": 300 } const { otp_id } = sendResult;

Save otp_id. You'll need it for the next call, and it's how Lunyazi knows which code your user is trying to enter. expires_in is in seconds; codes are valid for 5 minutes.

2. Verify what the user types in

Once your user enters the code they received, send it along with the otp_id to /otp/verify:

// Step 2: verify the code the user typed in const verifyResult = await fetch("https://api.lunyazi.com/otp/verify", { method: "POST", headers: { "X-Api-Key": process.env.LUNYAZI_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ otp_id, code: userInput }) }).then(r => r.json()); if (verifyResult.verified) { // user is authenticated -- log them in, approve the transaction, etc. } else { // wrong code -- verifyResult.attempts_remaining tells you how many tries are left }

The detail that trips people up

A wrong code is not an error. The request still returns 200 with {"success": true, "verified": false, "attempts_remaining": N}: success means the check ran, verified is the actual answer. Checking response.ok alone and assuming a 200 means the user is verified is the single most common mistake in a first integration.

3. Handle the real failure cases

Beyond a simply wrong code, four other outcomes are real and worth handling explicitly rather than showing a generic error:

StatusMeaningWhat to show the user
404OTP not found or already expired from the record entirely"Request a new code"
410 (OTP expired)The 5-minute window passed"Code expired, request a new one"
410 (OTP already used)This code already verified successfully onceShouldn't normally happen in a correct flow; treat as a bug if it does
429Too many wrong attempts on this code"Too many tries, request a new code"
const res = await fetch("https://api.lunyazi.com/otp/verify", { /* ... */ }); const data = await res.json(); if (!res.ok) { // 404, 410, or 429 -- data.error has the specific reason return showError(data.error); } if (!data.verified) { // wrong code, not a request failure return showWrongCode(data.attempts_remaining); } // data.verified === true from here on

Production considerations

Why OTP, and why it matters for compliance

Under Eswatini's Data Protection Act 2022, Section 14 requires businesses to implement appropriate technical measures to protect personal data. OTP verification is one of the most direct ways to satisfy that requirement for anything involving account access, password resets, or confirming a transaction actually came from the account holder.

Frequently Asked Questions

How long is an OTP code valid for?

5 minutes from when /otp/send is called, returned in the response as expires_in (in seconds).

What happens if the user enters the wrong code?

The request still returns 200 with verified: false and an attempts_remaining count. It's not an error status. Check the verified field specifically, not just whether the request succeeded.

Can I send the OTP by email instead of SMS?

Yes. Set channel: "email" and recipient to an email address in the /otp/send call. The rest of the flow is identical.

Do I need a separate SDK for OTP versus regular SMS?

No. Both use the same plain REST API: /otp/send and /otp/verify are just two more endpoints on the same account and API key as SMS sending.

How many attempts does a user get to enter the correct code?

A limited number before the OTP is locked out with a 429 response. At that point the correct flow is to have the user request a fresh code, not keep retrying the old one.

Ready to add OTP to your app?

Free to start, no credit card required. Get an API key and send your first verification code in the next five minutes.

Get your API key →