Building SMS Verification in Node.js Using Twilio
Secure user accounts with Twilio's Verify API in Node.js! Learn to send SMS verification codes, validate them, and manage phone updates efficiently. A step-by-step guide to building robust verification for your app. 🚀

Phone number verification is vital for securing user accounts and maintaining trustworthy user interactions. Twilio’s Verify API makes it straightforward to implement this in your Node.js application. In this post, I’ll walk you through a complete solution for SMS verification, covering sending codes, verifying them, and handling phone number updates.
Why Use Twilio for SMS Verification?
Twilio is a robust platform for communication APIs. Its Verify service handles SMS delivery, code generation, and expiration, ensuring reliable and secure verifications without building everything from scratch.
Key Features of Our Implementation
- Send Verification Codes: Allow users to receive a verification code via SMS.
- Verify Codes: Authenticate users by validating their codes.
Implementation
I’ve split the functionality into three main parts for clarity:
- Twilio Configuration
- Utility Functions
- Express Controllers
1. Twilio Configuration
Centralize your Twilio setup to ensure reusability:
import twilio from "twilio";
const twilioConfig = {
accountSid: process.env.TWILIO_ACCOUNT_SID,
authToken: process.env.TWILIO_AUTH_TOKEN,
serviceSid: process.env.TWILIO_SERVICE_SID,
};
const twilioClient = twilio(twilioConfig.accountSid, twilioConfig.authToken);
export { twilioClient, twilioConfig };
- Environment Variables: Store sensitive data like
TWILIO_ACCOUNT_SID
securely in environment variables. - Modular Design: Export the client and configuration for reuse in utility functions.
You can get all these Variables from your Twilio Dashboard. You can easily create a Twilio account. And then login to the account dashboard.

From this page, you can get your Account SID and Auth Token. For the Service SID you have to go to
Explore Products -> User Authentication & Identity -> Verify -> Create New

You will get this popup, here enter a Friendly Name { This will be displayed in the SMS or Other channels }. Then, make sure to enable the SMS feature from here.

You can enable this, don't know the exact use of this yet. But yeah, it seems promising. Then you can customize your SMS template that will be sent to your users here and also the Service_SID

You can do a lot more in the customization. But, we will be going with the default one. You can play around with this.
2. Utility Functions
We’ll create utility functions to send and verify codes using Twilio’s Verify API:
export const sendVerificationCode = async (phoneNumber: string): Promise<void> => {
try {
await twilioClient.verify.v2
.services(twilioConfig.serviceSid!)
.verifications.create({ to: phoneNumber, channel: "sms" });
console.log(`Verification code sent to ${phoneNumber}`);
} catch (error) {
console.error("Error sending verification code:", error);
throw new Error("Failed to send verification code.");
}
};
sendVerificationCode Utility Function
export const verifyCode = async (phoneNumber: string, code: string): Promise<boolean> => {
try {
const verificationCheck = await twilioClient.verify.v2
.services(twilioConfig.serviceSid!)
.verificationChecks.create({ to: phoneNumber, code });
console.log(`Verification status: ${verificationCheck.status}`);
return verificationCheck.status === "approved";
} catch (error) {
console.error("Error verifying code:", error);
throw new Error("Failed to verify code.");
}
};
verifyCode Utility Function
These functions provide a clean abstraction for SMS operations, ensuring easy testing and reuse.
3. Express Controllers
We’ll now create endpoints to handle user actions like initiating verification and confirming phone number changes.
export const initiatePhoneVerification = async (req, res) => {
try {
const { phoneNumber } = req.body;
if (!phoneNumber) {
return res.status(400).json({ success: false, message: "Phone number is required." });
}
await sendVerificationCode(phoneNumber);
res.status(200).json({ success: true, message: "Verification code sent." });
} catch (error) {
res.status(500).json({ success: false, message: "Failed to send verification code." });
}
};
initiateVerification Controller
This controller sends the verification code to the user by taking their phone number.
One more thing to note here is in Twilio's trial version, you can only send SMS to the phone numbers you have verified in Twilio's Dashboard.
You can add a phone number to Twilio by going to
Develop -> Phone Numbers -> Manage -> Verified Caller IDs
Here you can add and manage your phone numbers. This is great while you are developing your system, and then you can upgrade your Twilio Account for production.

You can add a new Caller ID here and you can send SMS to those phone numbers only.
export const verifyPhoneNumber = async (req, res) => {
try {
const { phoneNumber, code } = req.body;
if (!phoneNumber || !code) {
return res.status(400).json({ success: false, message: "Phone number and code are required." });
}
const isVerified = await verifyCode(phoneNumber, code);
if (!isVerified) {
return res.status(400).json({ success: false, message: "Invalid or expired verification code." });
}
// Example: Update the phone number in the database
const userId = req.user.userId; // Assuming userId is available from middleware
const user = await UserModel.findByIdAndUpdate(userId, { phone: phoneNumber, mobile_verified: true });
res.status(200).json({ success: true, message: "Phone number verified and updated.", user });
} catch (error) {
res.status(500).json({ success: false, message: "Failed to verify phone number." });
}
};
verifyPhoneNumber Controller
This is how you can verify if the code sent and entered by the user is correct. Based on this fact, you can update states and properties in your application, for example, enabling the user to use certain features after verification.
Best Practices
- Input Validation: Validate phone numbers and codes to prevent invalid requests. Libraries like
validator.js
orJoi
middleware is helpful here. - Security: Protect your environment variables and avoid hardcoding sensitive information.
- Rate Limiting: Implement rate limiting to prevent abuse, using middleware like
express-rate-limit
.
With Twilio's Verify API and the above implementation, you can easily add secure and scalable SMS verification to your Node.js application. This setup ensures a seamless experience for users while securing their accounts.
Feel free to extend this solution to support additional features like email verification or multi-channel notifications. 🚀
That's it for this article! See ya 👋