Hashed at rest.
The code itself is never stored or returned by the API — only a SHA-256 hash lives in the database, and only WhatsApp sees the digits.
WhatsApp OTP — live demo
One-time passcodes delivered where your users already are. Hashed at rest, rate-limited by default, expired in five minutes.
Why it holds up
The code itself is never stored or returned by the API — only a SHA-256 hash lives in the database, and only WhatsApp sees the digits.
Five sends per number per 10 minutes, a 60-second resend cooldown, and five verify attempts per code. Brute force gets bored.
Every code expires 5 minutes after it's sent, and a newer code voids the old one instantly. Nothing lingers.
For developers
This page never touches the microservice directly — a Next.js route handler holds the API key server-side and proxies /otp/send and /otp/verify. The key never reaches the browser.
terminal
$ curl -X POST $BASE/otp/send \
-H "X-API-Key: $KEY" \
-d '{"phoneNumber":"9199…","reference":"login"}'
{ "success": true, "expiresInSeconds": 300 }
$ curl -X POST $BASE/otp/verify \
-H "X-API-Key: $KEY" \
-d '{"phoneNumber":"9199…","code":"4821"}'
{ "verified": true }