ballerinax/whatsapp.business Ballerina library

2.0.1

Overview

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-in X-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

  1. Go to Meta for Developers and create a new app of type Business.
  2. 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_messaging and whatsapp_business_management permissions.

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:

  1. Set the Callback URL to your listener's public URL (e.g. via a tunnel during development).
  2. Set a Verify token — this must match the verifyToken you pass to whatsapp:Listener.
  3. Subscribe to the fields you want notifications for. Each maps 1:1 to one WhatsAppService handler: messages (onMessages — inbound messages and status updates both arrive here, as two mutually exclusive payload shapes; narrow the MessagesNotification parameter with notification 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.
  4. Copy the app's App secret (App Settings → Basic) and pass it as the listener's appSecret so inbound notifications are authenticated via X-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

Copy
import ballerina/io;
import ballerinax/whatsapp.business as whatsapp;

Step 2: Initialize a WhatsApp client

Copy
configurable string accessToken = ?;
configurable string phoneNumberId = ?;

whatsapp:Client whatsappClient = check new ({auth: {token: accessToken}});

Step 3: Invoke connector operations

Copy
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:

Copy
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

Copy
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

Copy
import ballerinax/whatsapp.business as whatsapp;

Step 2: Initialize a WhatsApp listener

Copy
configurable string verifyToken = ?;
configurable string appSecret = ?;

listener whatsapp:Listener whatsappListener = new (8090, verifyToken = verifyToken, appSecret = appSecret);

Step 3: Implement the service

whatsapp:WhatsAppService has ten webhook-field handlers, one per WhatsApp Business Cloud webhook field, plus an eleventh optional onError handler — 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. onError(whatsapp:HandlerError handlerError) returns error? doesn't correspond to a webhook field — it's invoked whenever one of the ten handlers above returns an error while being dispatched, and is the only way to react to a handler failure beyond logging. A compiler plugin validates every handler you do declare: its name must be one of these eleven, its parameter must match the documented event type, and it must return error?.

Copy
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

Copy
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.

  1. Send a WhatsApp message — send a text message and receive replies/status updates over a webhook listener.

Import

import ballerinax/whatsapp.business;Copy

Other versions

See more...

Metadata

Released date: 2 days ago

Version: 2.0.1

License: Apache-2.0


Compatibility

Platform: java21

Ballerina version: 2201.12.0

GraalVM compatible: Yes


Pull count

Total: 59

Current verison: 2


Weekly downloads


Source repository


Keywords

Communication/WhatsApp

Cost/Freemium

Vendor/Meta

Area/Communication

Type/Connector

Type/Trigger


Contributors