Module whatsapp.business
ballerinax/whatsapp.business Ballerina library
Ballerina WhatsApp Business Cloud connector
WhatsApp Business Cloud API is Meta's hosted API for sending and receiving WhatsApp messages, managing business phone numbers, message templates, and more, over the Meta Graph API.
The ballerinax/whatsapp.business package provides both:
- A client (
whatsapp:Client) for sending text/media/location/contacts messages and message templates, and for uploading, retrieving, and deleting media. - A webhook listener (
whatsapp:Listener) for all ten WhatsApp Business Cloud webhook event types (inbound messages and status updates, account/template/phone-number lifecycle changes, and security events), with built-inX-Hub-Signature-256(HMAC-SHA256) verification.
The client and listener are based on Meta's Cloud API reference and validated against Meta's official whatsapp-business-nodejs-sdk definitions.
Setup guide
Step 1: Create a Meta app
- Go to Meta for Developers and create a new app of type Business.
- Add the WhatsApp product to the app.
Step 2: Get the messaging credentials (client)
From WhatsApp → API Setup:
- Phone number ID — the test or production business phone number ID.
- Access token — a temporary token is shown for testing. For production, create a System User in Meta Business Settings and generate a permanent token with the
whatsapp_business_messagingandwhatsapp_business_managementpermissions.
Use this as the token in whatsapp:ConnectionConfig.auth — the client attaches it to every request automatically.
Step 3: Configure webhooks (listener)
From WhatsApp → Configuration → Webhooks:
- Set the Callback URL to your listener's public URL (e.g. via a tunnel during development).
- Set a Verify token — this must match the
verifyTokenyou pass towhatsapp:Listener. - Subscribe to the fields you want notifications for. Each maps 1:1 to one
WhatsAppServicehandler:messages(onMessages— inbound messages and status updates both arrive here, as two mutually exclusive payload shapes; narrow theMessagesNotificationparameter withnotification is Messages),account_review_update(onAccountReviewUpdate),account_update(onAccountUpdate),business_capability_update(onBusinessCapabilityUpdate),message_template_quality_update(onMessageTemplateQualityUpdate),message_template_status_update(onMessageTemplateStatusUpdate),phone_number_name_update(onPhoneNumberNameUpdate),phone_number_quality_update(onPhoneNumberQualityUpdate),security(onSecurity),template_category_update(onTemplateCategoryUpdate). A field outside this set is logged and dropped. - Copy the app's App secret (App Settings → Basic) and pass it as the listener's
appSecretso inbound notifications are authenticated viaX-Hub-Signature-256.
Both verifyToken and appSecret are required fields on whatsapp:Listener — there is no way to start it without them.
Meta will call your callback URL with a GET handshake (echoing hub.challenge) when you save the configuration, then deliver notifications via POST.
Quickstart
The connector has two independent entry points — a client for calling the Cloud API and a listener for handling webhook events. Follow the track that matches your use case.
Client
Use this if your app only needs to send messages/templates or manage media (no event handling).
Step 1: Import the module
import ballerina/io; import ballerinax/whatsapp.business as whatsapp;
Step 2: Initialize a WhatsApp client
configurable string accessToken = ?; configurable string phoneNumberId = ?; whatsapp:Client whatsappClient = check new ({auth: {token: accessToken}});
Step 3: Invoke connector operations
whatsapp:TextMessage message = { to: "1XXXXXXXXXX", text: {body: "Hello from Ballerina!"} }; whatsapp:MessageResponsePayload response = check whatsappClient->sendMessage(phoneNumberId, message); io:println(response);
Send a template, or upload/retrieve/delete media the same way:
whatsapp:MessageResponsePayload templateResponse = check whatsappClient->sendTemplateMessage( phoneNumberId, {to: "1XXXXXXXXXX", template: {name: "hello_world", language: {code: "en_US"}}}); whatsapp:MediaUploadResponse uploaded = check whatsappClient->uploadMedia(phoneNumberId, { fileContent: check io:fileReadBytes("image.jpg"), fileName: "image.jpg", mimeType: "image/jpeg" }); byte[] mediaBytes = check whatsappClient->downloadMedia(uploaded.id); whatsapp:MediaDeleteResponse deleted = check whatsappClient->deleteMedia(uploaded.id);
Step 4: Run the Ballerina application
bal run
Listener
Use this if your app needs to handle inbound messages, status updates, or other webhook events from WhatsApp Business Cloud.
Step 1: Import the module
import ballerinax/whatsapp.business as whatsapp;
Step 2: Initialize a WhatsApp listener
listener whatsapp:Listener whatsappListener = new ( 8090, verifyToken = "my-verify-token", appSecret = "my-app-secret");
Step 3: Implement the service
whatsapp:WhatsAppService has ten possible handlers, one per WhatsApp Business Cloud webhook field — but unlike most Ballerina service types, none of them are required. Declare only the ones you care about; a field whose handler you did not declare (or a field outside this closed set) is logged and dropped rather than delivered anywhere. A compiler plugin validates every handler you do declare: its name must be one of the ten, its parameter must match the documented event type, and it must return error?.
service whatsapp:WhatsAppService on whatsappListener { remote function onMessages(whatsapp:MessagesNotification notification) returns error? { if notification is whatsapp:Messages { // handle inbound messages: notification.messages } else { // handle status updates: notification.statuses } } remote function onSecurity(whatsapp:Security security) returns error? { // handle a PIN change/reset event } }
See examples/send-message for a reference implementation of all ten handlers.
Step 4: Run the Ballerina application
bal run
Point your Meta app's webhook callback URL at the listener (via a public tunnel during development) to start receiving events.
Examples
The whatsapp.business connector provides practical examples illustrating usage in various scenarios. Explore these examples.
- Send a WhatsApp message — send a text message and receive replies/status updates over a webhook listener.
Issues and projects
The Issues and Projects tabs are disabled for this repository as this is part of the Ballerina library. To report bugs, request new features, start new discussions, view project boards, etc., visit the Ballerina library parent repository.
This repository only contains the source code for the package.
Build from the source
Prerequisites
-
Download and install Java SE Development Kit (JDK) version 21. You can download it from either of the following sources:
Note: After installation, remember to set the
JAVA_HOMEenvironment variable to the directory where JDK was installed. -
Download and install Ballerina Swan Lake 2201.12.x.
Build options
Execute the commands below to build from the source.
-
To build the package:
./gradlew clean build -
To run the tests:
./gradlew clean test -
To build the package without the tests:
./gradlew clean build -x test -
To debug the package with a remote debugger:
./gradlew clean build -Pdebug=<port> -
To debug with the Ballerina language:
./gradlew clean build -PbalJavaDebug=<port> -
Publish the generated artifacts to the local Ballerina central repository:
./gradlew clean build -PpublishToLocalCentral=true -
Publish the generated artifacts to the Ballerina central repository:
./gradlew clean build -PpublishToCentral=true
Repository structure
| Directory | Contents |
|---|---|
ballerina/ | The Ballerina connector + webhook listener source and tests |
native/ | The Java native module (reflective handler dispatch for WhatsAppService) |
compiler-plugin/ | Validates WhatsAppService handler names, parameter types, and return types |
examples/ | Runnable usage examples |
build-config/ | Build resources (the Ballerina.toml/CompilerPlugin.toml version templates) |
Contribute to Ballerina
As an open-source project, Ballerina welcomes contributions from the community.
For more information, go to the contribution guidelines.
Code of conduct
All the contributors are encouraged to read the Ballerina Code of Conduct.
Useful links
- For more information go to the
whatsapp.businesspackage. - For example demonstrations of the usage, go to Ballerina By Examples.
- Chat live with us via our Discord server.
- Post all technical questions on Stack Overflow with the #ballerina tag.