Getting started

Configuration

Everything the Whatsapp constructor accepts, runtime token management, rate limit monitoring, and multi-tenant setup.

whatsapp.ts
import { Whatsapp } from "wapi-cloud";

const whatsapp = new Whatsapp({
  accessToken: process.env.WA_TOKEN!,
  phoneNumberId: process.env.WA_PHONE_ID!,
  businessAccountId: process.env.WA_WABA_ID,
  appId: process.env.WA_APP_ID,
  appSecret: process.env.WA_APP_SECRET,
  businessId: process.env.WA_BUSINESS_ID,
  apiVersion: "v21.0",
  maxRetries: 3,
  timeoutMs: 15000,
  onRequest: ({ method, url }) => {
    console.log("[WA API]", method, url);
  },
  onResponse: ({ method, url, status }) => {
    console.log("[WA API]", method, url, "→", status);
  },
});

Constructor options

ParameterTypeDescription
accessToken*stringPermanent or System User access token with whatsapp_business_messaging and whatsapp_business_management permissions.
phoneNumberId*stringDefault Phone Number ID used for sending messages and uploading media.
businessAccountIdstringWhatsApp Business Account (WABA) ID. Required for templates, flows, qrCodes, analytics, and phoneNumbers.list().
appSecretstringMeta App Secret. Required for webhook signature verification (X-Hub-Signature-256) and Embedded Signup code exchange.
appIdstringMeta App ID. Required for Embedded Signup code exchange and script generation.
businessIdstringMeta Business Manager ID. Required only for whatsapp.catalogs.list(). Distinct from businessAccountId.
apiVersionstringGraph API version to target (e.g. "v21.0"). Defaults to a pinned stable version.
baseUrlstringBase Graph API URL. Defaults to "https://graph.facebook.com". Useful for mocking or proxying requests.
fetchtypeof fetchCustom fetch implementation (e.g. undici, node-fetch, or a testing stub).
maxRetriesnumberMaximum automatic retries with exponential backoff and jitter for 429 rate limits and 5xx server errors. Default: 3.
timeoutMsnumberPer-request timeout in milliseconds before failing with a TimeoutError. Default: 15000.
onRequest(info) => voidOptional callback invoked before each HTTP request for logging/tracing.
onResponse(info) => voidOptional callback invoked after each HTTP response for metrics/logging.

Runtime token management

If you rotate or refresh access tokens dynamically (e.g. using short-lived tokens), you can swap in a new token on an existing client instance without creating a new object:

whatsapp.setAccessToken(token: string): void
// Update token on the fly
whatsapp.setAccessToken(freshlyRefreshedToken);

Rate limit monitoring

The Graph API returns business use-case usage headers on responses. You can inspect the last seen header value at any time:

whatsapp.getRateLimitStatus(): string | null
const usageHeader = whatsapp.getRateLimitStatus();
if (usageHeader) {
  console.log("Current rate limit header:", usageHeader);
}

Partial configuration is supported

You don't need every option to start using wapi-cloud — only the modules you call check their corresponding config parameters. If you call a module that requires a missing value, it will not throw an exception; it returns a typed configuration error:

const whatsapp = new Whatsapp({
  accessToken: process.env.WA_TOKEN!,
  phoneNumberId: process.env.WA_PHONE_ID!,
  // businessAccountId omitted
});

const { data, error } = await whatsapp.templates.list();
// data === null
// error.type === "ConfigError"
// error.message === "businessAccountId is required in the Whatsapp client config to use whatsapp.templates.*"
Always store accessToken and appSecret in secure environment variables or a secrets manager. Never expose them to client-side code.

Multi-tenant applications

Because configuration is scoped per instance, you can safely create multiple Whatsapp instances in multi-tenant or agency setups:

tenantClient.ts
export function getTenantClient(tenant: {
  token: string;
  phoneId: string;
  wabaId: string;
}) {
  return new Whatsapp({
    accessToken: tenant.token,
    phoneNumberId: tenant.phoneId,
    businessAccountId: tenant.wabaId,
  });
}