Two-Step Verification API
Set up and manage two-step verification (2SV) for WhatsApp Business phone numbers to add an extra layer of security.
Official Documentation: WhatsApp Two-Step Verification API
Overview
Two-step verification adds security to your WhatsApp Business phone number by requiring a 6-digit PIN for registration and re-registration.
- Set PIN: Configure a 6-digit security PIN
- Update PIN: Change existing PIN
- Security: Prevent unauthorized phone number registration
Endpoints
POST /{PHONE_NUMBER_ID}Important Notes
Quick Start
import WhatsApp from 'meta-cloud-api';
const client = new WhatsApp({ accessToken: process.env.CLOUD_API_ACCESS_TOKEN!, phoneNumberId: Number(process.env.WA_PHONE_NUMBER_ID), businessAcctId: process.env.WA_BUSINESS_ACCOUNT_ID!,});
// Set two-step verification PINawait client.twoStepVerification.setTwoStepVerificationCode('123456');Set Two-Step Verification
Configure or update the two-step verification PIN.
Basic Setup
const pin = '123456'; // 6-digit numeric stringawait client.twoStepVerification.setTwoStepVerificationCode(pin);
console.log('Two-step verification enabled');Setup After Registration
// Complete phone setup with 2SVasync function setupPhoneNumberSecurity(pin: string) { // Register phone number await client.registration.register(pin);
// Enable two-step verification with same PIN await client.twoStepVerification.setTwoStepVerificationCode(pin);
console.log('Phone number secured with two-step verification');}
await setupPhoneNumberSecurity('123456');Update PIN
Change an existing two-step verification PIN.
// Update to new PINconst newPin = '654321';await client.twoStepVerification.setTwoStepVerificationCode(newPin);
console.log('Two-step verification PIN updated');Complete Security Setup
Example of comprehensive phone number security configuration:
import WhatsApp from 'meta-cloud-api';
async function setupPhoneNumberWithSecurity() { const client = new WhatsApp({ accessToken: process.env.CLOUD_API_ACCESS_TOKEN!, phoneNumberId: Number(process.env.WA_PHONE_NUMBER_ID), businessAcctId: process.env.WA_BUSINESS_ACCOUNT_ID!, });
// Generate secure PIN const pin = generateSecurePIN();
try { // Step 1: Register phone number console.log('Registering phone number...'); await client.registration.register(pin);
// Step 2: Request verification console.log('Requesting verification code...'); await client.phoneNumbers.requestVerificationCode({ code_method: 'SMS', language: 'en_US', });
// Step 3: Verify (user provides code) const verificationCode = await promptUserForCode(); await client.phoneNumbers.verifyCode(verificationCode);
// Step 4: Enable two-step verification console.log('Enabling two-step verification...'); await client.twoStepVerification.setTwoStepVerificationCode(pin);
// Step 5: Store PIN securely await storeSecurely('WA_2SV_PIN', pin);
console.log('Phone number setup complete with two-step verification'); } catch (error) { console.error('Setup failed:', error.message); throw error; }}
function generateSecurePIN(): string { // Generate cryptographically secure 6-digit PIN const crypto = require('crypto'); const randomNum = crypto.randomInt(100000, 1000000); return randomNum.toString();}Response Format
Success Response
{ success: true}Error Handling
try { await client.twoStepVerification.setTwoStepVerificationCode('123456');} catch (error) { if (error.response) { const { code, message } = error.response.data.error;
switch (code) { case 133016: console.error('Invalid PIN format - must be 6 digits'); break; case 133000: console.error('Two-step verification cannot be set'); break; default: console.error(`Error ${code}: ${message}`); } }}Best Practices
-
Store PIN Securely: Use proper secrets management
import { SecretsManager } from 'aws-sdk';async function storePINSecurely(pin: string) {const secretsManager = new SecretsManager();await secretsManager.putSecretValue({SecretId: 'whatsapp/2sv-pin',SecretString: pin,}).promise();}// Set 2SV after storing PINawait storePINSecurely('123456');await client.twoStepVerification.setTwoStepVerificationCode('123456'); -
Validate PIN Format: Ensure correct format before setting
function validatePIN(pin: string): boolean {// Must be exactly 6 digitsreturn /^\d{6}$/.test(pin);}const pin = '123456';if (!validatePIN(pin)) {throw new Error('PIN must be 6 digits');}await client.twoStepVerification.setTwoStepVerificationCode(pin); -
Use Same PIN for Registration: Simplify management
const pin = '123456';// Use same PIN for both operationsawait client.registration.register(pin);await client.twoStepVerification.setTwoStepVerificationCode(pin); -
Implement PIN Rotation: Change PIN periodically
async function rotatePIN() {// Generate new PINconst newPIN = generateSecurePIN();// Update two-step verificationawait client.twoStepVerification.setTwoStepVerificationCode(newPIN);// Store new PIN securelyawait storeSecurely('WA_2SV_PIN', newPIN);// Log rotationconsole.log('PIN rotated successfully');}// Rotate every 90 dayssetInterval(rotatePIN, 90 * 24 * 60 * 60 * 1000); -
Document PIN Requirements: Create clear documentation
/*** Sets two-step verification PIN for WhatsApp Business number.** Requirements:* - Must be exactly 6 digits* - Must be numeric only (0-9)* - Must be stored securely* - Cannot be recovered if lost** @param pin - 6-digit numeric PIN* @throws Error if PIN format is invalid*/async function setTwoStepVerification(pin: string) {if (!validatePIN(pin)) {throw new Error('Invalid PIN format');}await client.twoStepVerification.setTwoStepVerificationCode(pin);} -
Backup PIN Information: Maintain secure records
interface PINRecord {phoneNumberId: string;pin: string;createdAt: Date;lastRotated: Date;}async function recordPIN(pin: string): Promise<PINRecord> {const record: PINRecord = {phoneNumberId: process.env.WA_PHONE_NUMBER_ID!,pin: pin,createdAt: new Date(),lastRotated: new Date(),};// Store in secure database or secrets managerawait secureStorage.save('wa-pin-record', record);return record;} -
Monitor PIN Status: Track verification status
async function checkSecurityStatus() {const phoneInfo = await client.phoneNumbers.getPhoneNumberById(['code_verification_status',]);if (phoneInfo.code_verification_status !== 'VERIFIED') {console.warn('Phone number not verified - 2SV may not be active');}}
PIN Requirements
Format Requirements
- Length: Exactly 6 digits
- Characters: Numeric only (0-9)
- No special characters: No letters, spaces, or symbols
Security Recommendations
- Don’t use obvious patterns (123456, 111111, etc.)
- Don’t use birthday or personal information
- Generate randomly when possible
- Rotate periodically (every 90 days recommended)
- Never share or commit to version control
- Store in secure secrets management system
// Good PINs (random)'847592' ✅'103948' ✅'652847' ✅
// Weak PINs (avoid)'123456' ⚠️ (sequential)'111111' ⚠️ (repetitive)'121212' ⚠️ (pattern)'102030' ⚠️ (pattern)PIN Generation Best Practices
import crypto from 'crypto';
// Generate secure random PINfunction generateSecurePIN(): string { const randomNum = crypto.randomInt(100000, 1000000); return randomNum.toString();}
// Validate PIN strengthfunction isPINSecure(pin: string): boolean { // Check format if (!/^\d{6}$/.test(pin)) return false;
// Avoid sequential patterns if (/012345|123456|234567|345678|456789|567890/.test(pin)) return false;
// Avoid repetitive patterns if (/(\d)\1{5}/.test(pin)) return false; // All same digit if (/(\d{2})\1{2}/.test(pin)) return false; // Repeating pairs
return true;}
// Usagelet pin: string;do { pin = generateSecurePIN();} while (!isPINSecure(pin));
await client.twoStepVerification.setTwoStepVerificationCode(pin);Troubleshooting
Lost PIN
If you lose your two-step verification PIN:
- Contact WhatsApp Business API support
- Provide business verification documents
- Follow the account recovery process
Prevention: Always store PINs in a secure secrets manager.
PIN Not Working
async function troubleshootPIN(pin: string) { // Check format if (!validatePIN(pin)) { console.error('PIN format invalid'); return; }
// Try setting PIN try { await client.twoStepVerification.setTwoStepVerificationCode(pin); console.log('PIN set successfully'); } catch (error) { console.error('Failed to set PIN:', error.message);
// Check phone number status const phoneInfo = await client.phoneNumbers.getPhoneNumberById([ 'code_verification_status', ]);
if (phoneInfo.code_verification_status !== 'VERIFIED') { console.error('Phone number must be verified first'); } }}Security Considerations
-
Never Hardcode PINs
// ❌ Badawait client.twoStepVerification.setTwoStepVerificationCode('123456');// ✅ Goodconst pin = process.env.WA_2SV_PIN;await client.twoStepVerification.setTwoStepVerificationCode(pin); -
Use Environment Variables or Secrets Manager
// .env file (never commit to git)WA_2SV_PIN=123456// In codeconst pin = process.env.WA_2SV_PIN!; -
Implement Access Controls
// Only allow authorized users to set PINasync function setTwoStepVerificationSecure(pin: string,userId: string) {if (!isAuthorized(userId, 'set:2sv-pin')) {throw new Error('Unauthorized');}await client.twoStepVerification.setTwoStepVerificationCode(pin);}
Related Documentation
- Registration API - Register phone numbers
- Phone Numbers API - Verify phone numbers
- Security Best Practices - Comprehensive security guide
- WABA API - Manage business accounts
Source Code
View the source code on GitHub: TwoStepVerificationApi.ts