SMS OTP in Node.js
Adding phone number verification to a Node.js app typically requires:
1. An SMS provider (Twilio, Vonage, etc.) 2. OTP code generation logic 3. A database or cache to store codes with expiry 4. Rate limiting to prevent abuse 5. Verification endpoint to check codes
With LANGR, steps 2-4 are handled by the API. You just call two endpoints.
Installation
npm install @langr/sdk
Express.js Example
import express from "express";
import { LangrClient } from "@langr/sdk";const app = express();
app.use(express.json());
const langr = new LangrClient({
apiKey: process.env.LANGR_API_KEY!,
});
// POST /send-otp — Send OTP to phone number
app.post("/send-otp", async (req, res) => {
const { phone } = req.body;
if (!phone || !phone.startsWith("+")) {
return res.status(400).json({ error: "Valid phone number required (E.164 format)" });
}
try {
await langr.sms.sendOtp({ to: phone });
res.json({ ok: true, message: "OTP sent" });
} catch (err) {
res.status(500).json({ error: "Failed to send OTP" });
}
});
// POST /verify-otp — Verify the code
app.post("/verify-otp", async (req, res) => {
const { phone, code } = req.body;
if (!phone || !code) {
return res.status(400).json({ error: "Phone and code required" });
}
try {
const result = await langr.sms.verifyOtp({ to: phone, code });
res.json({ ok: result.ok, verified: result.ok });
} catch (err) {
res.status(400).json({ error: "Invalid or expired code" });
}
});
app.listen(3000);
With Session Tokens (Auth API)
If you need a session token after verification, use the Auth API instead:
// POST /auth/start — Send OTP with session support
app.post("/auth/start", async (req, res) => {
const { target } = req.body; // email or phone const result = await langr.auth.sendOtp({ target });
res.json({ ok: true, channel: result.channel }); // "email" or "sms"
});
// POST /auth/verify — Verify and get session token
app.post("/auth/verify", async (req, res) => {
const { target, code } = req.body;
const session = await langr.auth.verifyOtp({ target, code });
// session.session_token = "las_..." (30-day TTL)
// session.expires_at = ISO date string
// Set as HTTP-only cookie
res.cookie("session", session.session_token, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 30 24 60 60 1000, // 30 days
});
res.json({ ok: true });
});
// Middleware: validate session on protected routes
async function requireAuth(req, res, next) {
const token = req.cookies.session;
if (!token) return res.status(401).json({ error: "Not authenticated" });
try {
const result = await langr.auth.validateSession({
session_token: token,
});
req.user = result;
next();
} catch {
res.status(401).json({ error: "Invalid session" });
}
}
Phone Number Format
LANGR expects E.164 format: + followed by country code and number.
Examples:
- Denmark:
+4512345678 - US:
+14155551234 - UK:
+447911123456 - Germany:
+4915112345678 - Rate limiting: Built-in per-key rate limiting prevents abuse
- Code expiry: OTP codes expire automatically (5-minute TTL)
- Single use: Each code can only be verified once
- Brute force protection: Failed attempts are tracked
- Limit OTP send requests per phone number (e.g., max 3/hour)
- Log verification attempts for audit trails
- Use HTTPS for all API communication
- Free: 100 requests/day ($0)
- Pro: 10,000 requests/day ($49/month)
- Enterprise: Unlimited (custom)
Security Considerations
LANGR handles several security aspects for you:
For additional security in your app:
Pricing
SMS OTP is part of the LANGR API free tier:
Get Started
1. Get a free API key
2. npm install @langr/sdk
3. SMS API docs | Auth API docs