Buddy
All posts

Developers

WhatsApp Business API integration: a practical guide for developers

Connecting your product to WhatsApp means working with Meta's Cloud API, message templates, webhooks and a few rules that trip up most first integrations. This guide explains all of it, compares building directly with building on Buddy, and shows exactly what the Buddy API does today.

The Buddy Team · · 11 min read

Developers

API integration

A WhatsApp Business API integration connects your software to Meta's WhatsApp Business Platform so it can send messages, manage approved templates and receive webhooks for replies and delivery statuses. Today that means Meta's Cloud API. You can build on it directly, or build on a platform such as Buddy that handles numbers, consent, templates and analytics for you.

Either way, the same Meta rules apply: people must opt in, business-initiated messages need an approved template, and your number has a daily limit tied to message quality. This guide walks through the moving parts, the webhook details that matter in production, the trade-offs of each approach, and the Buddy API endpoints you can call right now.

What is the WhatsApp Business API (Cloud API)?

The WhatsApp Business Platform is Meta's official way for businesses and software to message people on WhatsApp at scale. The Cloud API is hosted by Meta and exposed through the Graph API (Meta, about the platform). Before you write any code, it helps to know the six objects you will deal with.

ConceptWhat it isWhy it matters
Business portfolioThe Meta business that owns everythingMessaging limits and verification sit here
WhatsApp Business Account (WABA)The account that holds numbers and templatesTemplates are approved per WABA
Business phone numberThe number people see, identified by a phone number IDYou send from the phone number ID
Access tokenA system user token with WhatsApp permissionsTemporary tokens expire quickly; production needs a system user token
Message templatePre-approved message with variables, header, footer, buttonsRequired to start a conversation outside the 24-hour window
WebhookYour HTTPS endpoint that Meta callsIncoming messages and delivery statuses only arrive this way

The 24-hour rule that shapes every integration

When a customer messages you, a 24-hour customer service window opens and you can reply with free-form messages. Outside that window you must use an approved template (Meta, send messages). Your code has to know which situation it is in. A support reply three hours after the customer wrote is fine; the same text sent the next day fails unless it is a template. Templates are reviewed by Meta, often within minutes but sometimes up to 24 hours, so create them before you need them (Meta, templates).

What does it take to integrate directly with the Cloud API?

Meta's get started guide sets out the path. In outline:

  1. 1Create a Meta app with the WhatsApp use case and link a WhatsApp Business Account.
  2. 2Use the temporary access token and test number to send a first template message to the /{phone-number-id}/messages endpoint on graph.facebook.com.
  3. 3Set up a webhook endpoint to receive message statuses and incoming messages.
  4. 4Create a system user in Business Settings and generate a permanent token with the whatsapp_business_messaging and whatsapp_business_management permissions.
  5. 5Add and register your real business phone number, and submit your own templates for review.
  6. 6If you are building software that other businesses connect to, you also need Embedded Signup and the right Meta programme (Tech Provider or Solution Partner), plus App Review for the permissions you use.

Sending the first message takes an afternoon. Production takes much longer, because the hard parts are everything around the send: storing consent, handling STOP, tracking statuses, retrying failures sensibly, respecting messaging limits, keeping templates in sync, and building screens for the people who actually write the messages.

How WhatsApp webhooks work

Webhooks are where most integrations break in production, so these details are worth getting right on day one. All of them come from Meta's documentation.

  • Verification handshake. When you register the endpoint, Meta sends a GET request with hub.mode (always "subscribe"), hub.challenge and hub.verify_token. Check the token matches yours and respond with the challenge value (Meta, webhooks getting started).
  • Signature check. Meta signs every payload with SHA256 using your app secret and sends it in the X-Hub-Signature-256 header as sha256=.... Compute the same signature over the raw body and compare before trusting anything (Meta).
  • Respond with 200. Your endpoint must return HTTP 200 to acknowledge receipt. Any other response, or a failed delivery, triggers retries (Meta, webhooks overview).
  • Retries last up to 7 days. Meta retries failed deliveries with decreasing frequency until they succeed, for up to 7 days, and retries can produce duplicate notifications (Meta). Deduplicate on the message ID and make your handlers idempotent.
  • Payloads can be up to 3 MB (Meta). Do not assume a small body, and do not do heavy work before returning 200. Store the payload, acknowledge, then process it on a queue.
  • Many topics. Beyond messages, Meta offers fields such as message_template_status_update, message_template_quality_update, phone_number_quality_update, account_update, account_alerts and user_preferences (Meta). Subscribe to the ones you will act on.

Message statuses, and why read counts are always low

Status webhooks report sent, delivered, read, failed and played (for voice messages) (Meta, status webhooks). Two quirks matter for reporting. First, if a message is delivered and read at the same moment, Meta may send only the read status, so never require a delivered event before a read. Second, people can turn off read receipts (WhatsApp Help Center), so read counts understate reality. Status webhooks also carry a pricing object showing whether a message was billable and in which category, which is useful for reconciling costs against Meta's pricing.

Build on the Cloud API directly, or use Buddy?

Both are legitimate choices. Building directly gives you complete control and no third party in the path. Building on Buddy gives you a working WhatsApp engagement system, with screens your marketing and support teams can use, and an API for the parts your product needs to automate.

TaskDirectly on Meta's Cloud APIWith Buddy
Connect a numberBuild Embedded Signup or handle tokens yourselfConnect through Meta Embedded Signup in Settings; the number stays in your own portfolio
Collect opt-insBuild forms, storage and an audit trailHosted opt-in page, QR code, website widget and the Subscribers API, each recording source and date
STOP and opt-outsParse replies and suppress numbers yourselfSTOP, unsubscribe and opt out handled automatically, with Meta's marketing preference respected
TemplatesCall the management API, track review by webhookTemplate builder that submits to Meta, with status and quality kept in sync
Campaign sendsQueue, throttle and retry yourselfWhatsNews builder with scheduling, audiences by tag and failure reasons in plain language
RepliesStore inbound messages and build a UIShared inbox, intent-sorted Responses and automations
Number healthPoll fields and handle quality webhooksWhatsApp health and WhatsApp accounts pages
Meta feesBilled by Meta to your WABAStill billed by Meta to your WABA; Buddy does not mark them up

If you are weighing platforms more broadly, our pillar guide to choosing a WhatsApp marketing platform compares the WhatsApp Business app, raw API access and full platforms side by side.

What the Buddy API does today

The Buddy API is in early access now and opens as a public beta on 12 October 2026. Today it has one resource, subscribers, with two live operations: list your subscribers and add a subscriber. That is deliberately small, and it is enough to connect your own signup flow, CRM or checkout to your Buddy audience.

Get an API key

You create keys in Buddy under Settings, API keys, on plans that include API access (see pricing). Each key starts with bd_live_, is shown once when you create it, and is stored only as a SHA-256 hash. The settings page lists each key by prefix with its last-used date, and you can revoke a key there at any time. Keep keys on your server; never put them in browser JavaScript or a mobile app.

List subscribers

GET /api/v1/subscribers returns every subscriber in the key's workspace, newest first.
curl https://usebuddy.app/api/v1/subscribers \
  -H "Authorization: Bearer $BUDDY_API_KEY"
Response (200). The fields are exactly those the endpoint returns today.
{
  "data": [
    {
      "id": "3f6c2a1e-8b1d-4c55-9a0e-2d7f4b9c1a22",
      "name": "Ada Obi",
      "phone": "+447700900123",
      "status": "subscribed",
      "tags": ["newsletter", "london"],
      "created_at": "2026-09-30T09:14:02.511Z"
    }
  ]
}

Add a subscriber

POST /api/v1/subscribers. Only phone is required; name and tags are optional.
curl -X POST https://usebuddy.app/api/v1/subscribers \
  -H "Authorization: Bearer $BUDDY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ada Obi",
    "phone": "+447700900123",
    "tags": ["newsletter", "london"]
  }'
Response (201). The full stored record is returned; source is always "API".
{
  "data": {
    "id": "3f6c2a1e-8b1d-4c55-9a0e-2d7f4b9c1a22",
    "workspace_id": "9b1e0c7d-2f3a-4e8b-8c61-5a4d3e2f1b00",
    "page_handle": null,
    "name": "Ada Obi",
    "phone": "+447700900123",
    "source": "API",
    "status": "subscribed",
    "consent_state": "opted_in",
    "tags": ["newsletter", "london"],
    "created_at": "2026-09-30T09:14:02.511Z",
    "updated_at": "2026-09-30T09:14:02.511Z"
  }
}

How the endpoint behaves

  • Send numbers in international format, starting with + and the country code. Buddy strips spaces and punctuation and accepts + followed by 8 to 15 digits. This endpoint does not add a country code for you, so a local number such as 07700 900123 would be stored incorrectly. Convert to international format before you post.
  • Adding the same number twice updates it. Subscribers are unique by phone within your workspace. A repeat POST returns 200, updates the name if you send one and adds any new tags to the existing ones. It never changes consent: someone who opted out stays opted out, and you get a 409.
  • Every add logs a consent event with the source recorded as API, so the person appears in your Consent history like any other opt-in.
  • Contacts added by API do not trigger the "When someone subscribes" automation. That trigger fires on first opt-in through your opt-in page or website form. Send a welcome WhatsNew from the app, or wait for message sending in the public beta.
  • The list returns everything in one response. There is no pagination or filtering on this endpoint today.
StatusBodyMeaning
201{ "data": { ... } }Subscriber created
200{ "data": { ... } }Number already in your audience; name updated and tags merged
200{ "data": [ ... ] }List returned (GET)
409{ "error": "opted_out", ... }The person opted out; Buddy leaves them unsubscribed
400{ "error": "phone_required" }No phone in the request body
400{ "error": "insert_failed" }The number is not a valid international number, or it could not be saved
401{ "error": "unauthorized" }Missing, wrong or revoked key

What arrives in the public beta on 12 October 2026

The public beta widens the API from subscribers to the full loop. These are planned for launch and not live yet, so there is no code for them here; the documentation will ship with them.

Contacts

A fuller contacts resource for managing your audience from your own systems.

Send approved templates

Send a Meta-approved template to a subscriber from your product, using your connected number.

Campaigns

Work with WhatsNews programmatically.

Outbound webhooks

HMAC-signed events for subscriber.created, subscriber.opted_out, message status and reply.received.

Test keys

Keys for development that never touch real numbers.

Documentation

Reference docs for every public endpoint.

Release 1.1: transactional messages and OTP

Planned for mid-October 2026, release 1.1 adds transactional messages and one-time passcodes through the API, using utility and authentication templates. That covers order updates, booking confirmations and login codes sent from your own backend. Until then, treat anything transactional as coming soon.

Not built yet, and not part of the launch: an events API, SDKs, OAuth, idempotency keys and enforced per-key scopes. We will announce them when they have dates.

Integration patterns that work today

Even with one resource, you can connect a lot. Each pattern below uses the live endpoints plus the Buddy App for sending.

Signup form to WhatsApp list

A SaaS product in Berlin adds an unticked "Send me product updates on WhatsApp" box to its signup form. When ticked, its backend POSTs the number with a tag like trial. The team sends onboarding WhatsNews to that tag.

CRM sync

A nightly job in a Lagos agency pushes contacts who opted in through its CRM, tagged by client interest. Marketing then targets each tag from Buddy.

Checkout opt-in

A store in São Paulo adds a WhatsApp opt-in to its checkout and posts buyers with a tag such as customer, ready for launch announcements.

Reporting

A data team in Mumbai pulls the subscriber list into its warehouse daily to track list growth by tag and source alongside revenue.

Tags you set through the API are the same tags the campaign builder uses for "Contacts with a tag" audiences, so what your code writes, your marketers can use immediately. For no-code sources, Buddy Connect is planned for late October with Selar, Paystack, Shopify and Zapier/Make. Collecting signups on your own site without writing backend code? The Buddy opt-in widget does that with one script tag.

What about AI agents?

On 15 September 2026 Meta announced a WhatsApp Business MCP server that lets AI agents help with setup work such as templates and webhook testing. It is aimed at building on the platform rather than running customer conversations. A Buddy MCP interface, with scopes, confirmations and audit logs, is planned for after launch and is not built yet. See Buddy MCP for the direction.

Frequently asked questions

Is the WhatsApp Business API free?

Meta charges per message, by category and country, billed to your WhatsApp Business Account. Marketing and authentication templates are always charged, and from 1 October 2026 service replies and utility messages inside the 24-hour window are charged too. See Meta's pricing and our October 2026 pricing explainer.

Can I send any message through the API?

Only inside a 24-hour customer service window. To start a conversation, or to write after the window closes, you must send a template Meta has approved, and the person must have opted in to hear from your business.

How long does Meta keep retrying a webhook?

Up to 7 days, with decreasing frequency, until your endpoint returns 200. Retries can create duplicates, so deduplicate by message ID (Meta).

Can I send WhatsApp messages with the Buddy API today?

Not yet. Today the API lists and adds subscribers. Sending approved templates arrives with the public beta on 12 October 2026, and transactional messages and OTP with release 1.1 in mid-October. You can send WhatsNews from the Buddy App now.

Do I need my own Meta developer app to use Buddy?

No. You connect your WhatsApp Business number to Buddy through Meta's Embedded Signup. Buddy is an approved Meta Tech Provider, and your account, number and templates stay in your own business portfolio.

Start your WhatsApp channel with Buddy.

Connect your number, collect subscribers with consent and send your first WhatsNew.

Start free