Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.photon.codes/docs/llms.txt

Use this file to discover all available pages before exploring further.

Most apps should use Spectrum - it gives you a unified, higher-level API across WhatsApp Business, iMessage, and other platforms. Reach for @photon-ai/whatsapp-business directly only when you need low-level WhatsApp control that Spectrum doesn’t expose.
@photon-ai/whatsapp-business is a TypeScript SDK for the WhatsApp Business API. It connects to our managed gRPC gateway, which fronts Meta’s Cloud API — you get typed message sending, a resumable event stream, and media handling without wiring webhooks yourself.

Installation

npm install @photon-ai/whatsapp-business
Requires Node.js 18+ or Bun.

Credentials

Three values are required. Get them in one of two ways:
Sign up at app.photon.codes, toggle WhatsApp on in your project, finish the guided config, and copy the credentials.Use these directly with createClient, or pass them to spectrum-ts to combine WhatsApp with iMessage and other platforms behind one unified API.

Quick start

import { createClient } from "@photon-ai/whatsapp-business";

const client = createClient({
  accessToken: process.env.WA_ACCESS_TOKEN!,
  phoneNumberId: process.env.WA_PHONE_NUMBER_ID!,
  appSecret: process.env.WA_APP_SECRET!,
});

await client.messages.send({
  to: "+15551234567",
  text: "Hello from the SDK!",
});

for await (const event of client.events.subscribe()) {
  if (event.type === "message") {
    console.log(event.message);
  }
}

createClient

const client = createClient(options: ClientOptions): WhatsAppClient;
OptionTypeDescription
retryboolean | RetryOptionsEnable automatic retry with exponential backoff for retryable errors. Pass true for default settings, or a RetryOptions object to customise the behaviour.
timeoutnumberDefault timeout in milliseconds for unary RPC calls. Sets a deadline on each call unless one is already provided.
The returned WhatsAppClient exposes three resources:
client.messages  // send, markRead
client.events    // subscribe, fetchMissed
client.media     // upload, getUrl, delete

Disposing the client

The client implements Symbol.asyncDispose, so await using handles teardown automatically:
await using client = createClient({
  accessToken: "...",
  phoneNumberId: "...",
  appSecret: "...",
});
// closed automatically when the block exits
Or close it explicitly:
await client.close();

Your first echo bot

import { createClient } from "@photon-ai/whatsapp-business";

const client = createClient({
  accessToken: process.env.WA_ACCESS_TOKEN!,
  phoneNumberId: process.env.WA_PHONE_NUMBER_ID!,
  appSecret: process.env.WA_APP_SECRET!,
});

for await (const event of client.events.subscribe()) {
  if (event.type !== "message") continue;
  if (event.message.content.type !== "text") continue;

  await client.messages.send({
    to: event.message.from,
    text: event.message.content.body,
  });
}
  • event.type is narrowed to "message" or "status" — only messages get a .message field.
  • InboundContent is a discriminated union; switch on content.type before reading fields.
  • event.message.from is the WhatsApp ID of the sender — pass it straight to send.to.

Reconnection and missed events

The stream reconnects automatically when the connection drops, and fetches any events buffered in the meantime. See Events for cursor management and Error handling for when to retry.