Authentication
All requests to the WhatsApp Cloud API require authentication via an access token. This guide covers how to configure credentials, manage tokens securely, and handle token rotation.
Required Credentials
To use the SDK, you need three pieces of information from the Meta for Developers dashboard:
| Credential | Description | Where to find |
|---|---|---|
| Access Token | Bearer token for API authentication | App Dashboard > WhatsApp > API Setup |
| Phone Number ID | Numeric ID of your WhatsApp business phone number | App Dashboard > WhatsApp > API Setup |
| Business Account ID | Your WhatsApp Business Account (WABA) ID | App Dashboard > WhatsApp > API Setup |
Basic Configuration
Pass credentials directly when creating the client:
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!,});Environment Variables
The SDK automatically reads from environment variables when constructor arguments are omitted. Set these in your .env file:
CLOUD_API_ACCESS_TOKEN=EAABx...your-tokenWA_PHONE_NUMBER_ID=123456789012345WA_BUSINESS_ACCOUNT_ID=987654321098765Then instantiate without arguments:
import WhatsApp from 'meta-cloud-api';
// Reads from environment variables automaticallyconst client = new WhatsApp();Full Configuration Options
The SDK supports additional environment variables for advanced use cases:
# RequiredCLOUD_API_ACCESS_TOKEN=EAABx...WA_PHONE_NUMBER_ID=123456789012345WA_BUSINESS_ACCOUNT_ID=987654321098765
# OptionalCLOUD_API_VERSION=v21.0 # API version (default: latest stable)WA_LISTENER_PORT=3000 # Webhook listener portWEBHOOK_ENDPOINT=/webhook # Webhook endpoint pathWEBHOOK_VERIFICATION_TOKEN=my-secret # Webhook verification tokenREQUEST_TIMEOUT=10000 # Request timeout in msDEBUG=true # Enable verbose loggingToken Types
Meta provides two types of access tokens:
Temporary Tokens
Generated from the App Dashboard. These are useful for development and testing but expire after 24 hours.
const client = new WhatsApp({ accessToken: 'EAABx...temporary-token', phoneNumberId: Number(process.env.WA_PHONE_NUMBER_ID), businessAcctId: process.env.WA_BUSINESS_ACCOUNT_ID,});System User Tokens
For production, create a System User in Meta Business Suite and generate a permanent token. These do not expire and are suitable for server-to-server communication.
- Go to Meta Business Suite
- Create a System User with the Admin role
- Click Generate New Token
- Select your app and grant the
whatsapp_business_messagingandwhatsapp_business_managementpermissions - Copy the token and store it securely
Token Rotation
The SDK supports runtime token updates, which is essential for rotating tokens without restarting your application:
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,});
// Later, rotate the token without creating a new clientclient.updateAccessToken('new-access-token');Automated Token Refresh
For temporary tokens, you can implement automatic refresh using Meta’s OAuth endpoint:
async function refreshAccessToken( appId: string, appSecret: string, existingToken: string,): Promise<string> { const response = await fetch( `https://graph.facebook.com/oauth/access_token` + `?grant_type=fb_exchange_token` + `&client_id=${appId}` + `&client_secret=${appSecret}` + `&fb_exchange_token=${existingToken}` );
const data = await response.json(); return data.access_token;}
// Refresh on a schedulesetInterval(async () => { const newToken = await refreshAccessToken( process.env.APP_ID!, process.env.APP_SECRET!, currentToken, ); client.updateAccessToken(newToken); currentToken = newToken;}, 60 * 60 * 1000); // Every hourMulti-Tenant Setup
If your application manages multiple WhatsApp Business Accounts, you can create separate client instances or switch credentials at runtime:
// Option 1: Separate clients per tenantconst clients = new Map<string, WhatsApp>();
function getClient(tenantId: string, token: string, phoneNumberId: number) { if (!clients.has(tenantId)) { clients.set(tenantId, new WhatsApp({ accessToken: token, phoneNumberId, businessAcctId: tenantId, })); } return clients.get(tenantId)!;}
// Option 2: Switch sender on a single clientclient.updateAccessToken(tenantToken);client.updateSenderNumberId(tenantPhoneNumberId);Security Best Practices
-
Never commit tokens to source control. Use
.envfiles (added to.gitignore) or a secrets manager. -
Use System User tokens in production. Temporary tokens expire and will cause outages.
-
Restrict token permissions. Only grant
whatsapp_business_messagingandwhatsapp_business_management— nothing more. -
Rotate tokens periodically. Even permanent tokens should be rotated as part of your security policy.
-
Use environment-specific tokens. Separate tokens for development, staging, and production.
-
Store tokens in a secrets manager. Use AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, or similar services instead of plain environment variables in production.
// Example: Loading token from AWS Secrets Managerimport { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const secretsClient = new SecretsManagerClient({ region: 'us-east-1' });
async function getAccessToken(): Promise<string> { const command = new GetSecretValueCommand({ SecretId: 'whatsapp/access-token', }); const response = await secretsClient.send(command); return response.SecretString!;}
const token = await getAccessToken();const client = new WhatsApp({ accessToken: token, phoneNumberId: Number(process.env.WA_PHONE_NUMBER_ID), businessAcctId: process.env.WA_BUSINESS_ACCOUNT_ID,});Webhook Verification
In addition to API authentication, webhook endpoints require a separate verification token to confirm ownership:
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, webhookVerificationToken: process.env.WEBHOOK_VERIFICATION_TOKEN,});This token is used during the webhook subscription handshake. Meta sends a GET request with a hub.verify_token parameter, and your server must respond with the hub.challenge value only if the token matches. See the Webhooks guide for full setup details.