Skip to main content

WhatsApp API

Your app can send WhatsApp messages to a store's buyers through four endpoints. The messages use the order templates that Meta approved for DZBuild, and each one is paid from the store's WhatsApp wallet, exactly like the messages the WhatsApp Sender addon sends on its own. You cannot send free text or your own templates.

The full request and response reference is in the OpenAPI description, linked from the API reference page. This page explains how the pieces fit together.

Scopes​

ScopeAllows
whatsapp:readGET /v1/whatsapp/templates, GET /v1/whatsapp/balance, GET /v1/whatsapp/messages
whatsapp:sendPOST /v1/orders/{id}/whatsapp

Request only the scopes you need in the authorize URL. A call without the scope answers 403 with the code forbidden and the message Missing scope: whatsapp:send (or whatsapp:read). See Scopes.

Templates​

GET /v1/whatsapp/templates lists the six templates. It reads the approval status DZBuild keeps and never calls Meta.

KeySent for
receivedThe order was received.
confirmedThe order was confirmed.
shipped_homeThe parcel is on its way to the buyer's address.
shipped_deskThe parcel is on its way to a courier desk.
delivery_failedThe delivery attempt failed.
desk_readyThe parcel is ready for pickup.

Each item carries key, name (the template name at Meta, for example dz_order_confirmed), toggle (the merchant's matching switch in the addon) and languages. languages.ar and languages.fr each hold the body with its placeholders, an example, and the status. A template can only be sent in a language whose status is APPROVED. UNKNOWN means DZBuild has no status stored yet.

Wallet​

GET /v1/whatsapp/balance returns:

FieldMeaning
balanceMessages left in the store's wallet. One message costs one credit.
low_balancetrue when fewer than 50 messages are left.
addon_activeWhether the merchant has the WhatsApp Sender addon turned on.
statsCounts for the last 30 days by status (sent, delivered, read, failed) and used_month, the credits used since the first day of this month.

The merchant tops up the wallet in the DZBuild dashboard. Your app cannot add credit.

Send a message​

POST /v1/orders/{id}/whatsapp queues one template for one order of the store. It is a write, so it needs an Idempotency-Key header (see Rate limits).

POST /v1/orders/98765/whatsapp HTTP/1.1
Host: api.dzbuild.app
Authorization: Bearer dzpk_live_xxxxxxxx
Idempotency-Key: wa-98765-confirmed
Content-Type: application/json

{"template": "confirmed", "language": "fr"}
Body fieldRequiredMeaning
templateYesOne of the six keys, or shipped. shipped picks the right template from the order's delivery type: shipped_home for home delivery, shipped_desk for a desk, desk_ready for pickup.
languageNoar or fr. Without it, the language set in the store's WhatsApp Sender is used, or the store's language when the addon has none. When that fallback is neither ar nor fr, the message goes in Arabic.

A manual send ignores the merchant's automatic switches in the addon. The addon itself must be active on the store.

The call answers 202 when the message is queued and the credit is taken:

{
"data": { "message_id": 4411, "status": "queued", "template": "confirmed", "language": "fr" },
"meta": { "request_id": "8f2c1a9d4b7e6035", "api_version": "v1" }
}

DZBuild sends queued messages in the background. Follow the result with GET /v1/whatsapp/messages.

Answers and error codes​

StatusCodeMeaning
202Queued, one credit taken.
400bad_requestThe order id is not numeric, or the body is not valid JSON.
402no_creditThe store's wallet is empty. Nothing was queued and nothing was charged.
403addon_not_activeThe merchant has not turned on the WhatsApp Sender addon.
403forbiddenThe token lacks whatsapp:send.
404not_foundNo order with this id on this store.
409already_sentThis template was already sent for this order. The error object carries the existing message id and status.
422unknown_templatetemplate is not one of the accepted keys.
422invalid_languagelanguage is not ar or fr.
422invalid_numberThe buyer's phone is not a valid Algerian mobile number.
422suppressedThe buyer's number is blocked for WhatsApp messages on the platform.
422template_not_approvedThe template is not approved in that language.
422empty_paramA value the template needs is empty on the order.
500send_failedThe message could not be queued. Retry later.

Each template can be sent once per order through the API. A later call for the same template and order answers 409, even if the first message failed. The 422 answers from invalid_number to empty_param are different: nothing was charged, and the next call for that template and order tries again, so fix the cause (for example the phone number on the order) and call again with a new Idempotency-Key.

Message log​

GET /v1/whatsapp/messages lists the store's messages, newest first. Query parameters: order_id to filter one order, limit (default 50, maximum 200) and cursor (the next_cursor of the previous page). The buyer's phone number is never returned.

FieldMeaning
idThe message id, the same as message_id in the send answer.
order_idThe order.
eventThe template key for API messages, or the addon event (received, confirmed, shipped, delivery_failed, desk_ready) for automatic ones.
sourceapi for messages sent through the API, auto for the addon's automatic messages.
statusqueued, sending, sent, delivered, read, failed or skipped.
languagear or fr.
template_nameThe template name at Meta.
error_titleWhy the message failed or was skipped, or null.
refundedtrue when the credit was given back.
billingcharged once WhatsApp billed the message, free once the credit came back, null while WhatsApp has not reported the outcome.
created_atWhen the message was queued.

A message that fails, expires undelivered after 30 days, or is delivered without a charge from WhatsApp gets its credit back once: refunded turns true and billing becomes free. A message WhatsApp bills settles as charged.

This page for AI toolsView as MarkdownOpen in ChatGPTOpen in Claude