Webhook Parsing API Reference
Detailed information on flattening Meta's deeply nested webhook payloads into clean, strongly-typed events.
Meta's webhooks natively look like this: entry[0].changes[0].value.messages[0]. This package provides parseWebhook() to flatten this into a strongly-typed WebhookEvent[] array.
Base Properties
Every message-based event (Text, Image, Location, etc.) includes these base properties:
| Property | Type | Description |
|---|---|---|
| type | string | The event type (e.g. "text", "image", "status"). |
| from | string | The WhatsApp ID (phone number) of the user who sent the message. |
| displayPhoneNumber | string | The display phone number of the business account receiving the message. |
| phoneNumberId | string | The WhatsApp Business Phone Number ID. |
| messageId | string | The unique wamid for this message. |
| timestamp | Date | A standard JavaScript Date object when the message was sent. |
Event-Specific Properties
TextEvent (type: "text")
| text | string | The text body sent by the user. |
Media Events ("image", "video", "document")
| imageId / videoId / documentId | string | The ID of the media. Pass this to client.getMediaUrl(id) to download. |
| mimeType | string | The MIME type of the media file. |
| caption | string? | Optional text caption sent with the media. |
StatusEvent (Delivery Receipts) (type: "status")
Note: Status events do not have a from property; they have a recipientId instead.
| status | "sent" | "delivered" | "read" | "failed" | The current status of your outbound message. |
| recipientId | string | The phone number of the user who received/read the message. |
| errors | Array? | If status is "failed", this contains the error details (code, title, message). |
Webhook Verification
When you first set up your webhook in the Meta App Dashboard, Meta sends a GET request with a challenge string to verify your endpoint. You can use verifyWebhook to handle this validation automatically.
First, ensure you have added your custom VERIFY_TOKEN (which you set in the Meta App Dashboard) to your .env file:
VERIFY_TOKEN=my_super_secret_verify_tokenimport { verifyWebhook } from "whatsapp-cloud-ts";
// Handle the GET request for initial verification
app.get("/webhook", (req, res) => {
// Pass req.query and your secret verify token from Meta App Dashboard
const challenge = verifyWebhook(req.query, process.env.VERIFY_TOKEN!);
if (challenge) {
res.send(challenge); // Validation successful
} else {
res.sendStatus(403); // Validation failed
}
});Express.js Example (Parsing)
import { parseWebhook, verifyWebhook } from "whatsapp-cloud-ts";
import express from "express";
const app = express();
app.use(express.json());
app.post("/webhook", (req, res) => {
const events = parseWebhook(req.body);
for (const event of events) {
if (event.type === "text") {
console.log(`Text from ${event.from}: ${event.text}`);
} else if (event.type === "status") {
console.log(`Message ${event.messageId} to ${event.recipientId} is ${event.status}`);
}
}
res.sendStatus(200);
});