Home
WAAPI API

WAAPI External API

The WAAPI programmatic API, organized by service namespace. WhatsApp Cloud API endpoints live under /whatsapp-api/*; WhatsApp QR session endpoints live under /whatsapp-qr/*; contacts are cross-cutting at /contacts. Each API key may be bound to any mix of services, accounts, numbers and scopes — and you pick which number to send from per-request via fromPhoneNo.

Base URL

https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external

Auth headers

X-API-Key · X-API-Secret

Namespaces

/whatsapp-api · /whatsapp-qr · /contacts

Authentication

Every request must carry your API key in the X-API-Key header AND your secret in X-API-Secret. Both are returned once when you create the key in your WAAPI panel — copy them to a safe place at that moment.

Every send must carry both the recipient to and the sending number fromPhoneNo (E.164). fromPhoneNo must be one of the WhatsApp numbers your key is bound to — a key can be bound to one number, several, or all of them.

GET/ping

Authentication

Every request must carry both the X-API-Key header AND the X-API-Secret header. A key is bound to one or more of your WhatsApp numbers; every send must name which one to use via `fromPhoneNo` (E.164), alongside the recipient `to`. The ping endpoint echoes back your vendor id and the name of the key you authenticated with.

FieldTypeReq?Description
X-API-KeyheaderrequiredPublic API key, starts with `waapi_`
X-API-SecretheaderrequiredSecret token, starts with `secr_`. Required when the key was created with a secret.

Request

curl --request GET \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/ping' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \

Success response

{
  "success": true,
  "pong": true,
  "vendorId": "6a2a74...",
  "apiKeyName": "Production CRM"
}
Error responses (3)

HTTP 401Missing API key

{
  "success": false,
  "message": "API key required (Authorization: Bearer <waapi_… key or JWT> or X-API-Key header)"
}

HTTP 401Missing secret

{
  "success": false,
  "message": "API secret required (X-API-Secret header)"
}

HTTP 401Invalid credential

{
  "success": false,
  "message": "Invalid API secret"
}

Error format

Errors return a non-2xx HTTP status with a JSON body. Validation problems are 400, auth problems 401, missing permissions 403, missing resources 404, conflicts 409, and Meta-side send failures bubble up as 400 with Meta's error code in the message.

{
  "success": false,
  "error": "(#131026) Recipient phone number does not have WhatsApp installed"
}
StatusMeaning
400Bad request — body validation failed or Meta returned an error code
401Auth — missing/invalid X-API-Key or X-API-Secret
403Forbidden — key lacks the required permission or scope
404Not found — resource (contact, message, template) does not exist
409Conflict — duplicate or state-incompatible
429Rate limited — slow down to your key's per-minute/hour quota
500Server error — please retry; if persistent, open a ticket with the response body

Cloud API — Send endpoints (/whatsapp-api/*)

POST/whatsapp-api/messages/template

1. Send Template Message

Permissions: messages.send

Send an approved WhatsApp template by name. The template must be APPROVED in Meta Business Manager. Pass parameters using the Meta-shaped `components` array.

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164 (e.g. 917890000198)
fromPhoneNostringrequiredE.164 number to send FROM — one of the WhatsApp numbers your API key is bound to. REQUIRED on every send, alongside `to`.
namestringrequiredTemplate name (case-sensitive) — must match an approved template
languagestringrequiredBCP-47 language code (e.g. en, en_US, hi)
componentsarrayoptionalMeta-shaped components: header / body / button (url) for template parameters
replyToWaMessageIdstringoptionalQuote a prior message (wamid)

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-api/messages/template' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "name": "order_shipped",
  "language": "en",
  "components": [
    {
      "type": "body",
      "parameters": [
        {
          "type": "text",
          "text": "Sayantan"
        },
        {
          "type": "text",
          "text": "AWB-12345"
        }
      ]
    }
  ]
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "wamid.HBgM...",
    "id": "6a2dbff6...",
    "status": "sent",
    "to": "917890000198",
    "type": "template",
    "timestamp": "2026-06-17T12:00:00.000Z"
  }
}
Error responses (2)

HTTP 400Template not found

{
  "success": false,
  "error": "(#132001) Template name does not exist in the translation"
}

HTTP 403Wrong scope

{
  "success": false,
  "message": "API key scope 'read' does not permit send actions"
}
POST/whatsapp-api/messages/buttons

2. Send Interactive Message (Buttons)

Permissions: messages.send

Send a quick-reply button message — up to 3 buttons. Customer taps a button → you receive a button_reply webhook with the button id you assigned.

Note: Variants: /messages/list (sectioned list), /messages/cta (call-to-action URL), /messages/flow (Flow embed).

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164
fromPhoneNostringrequiredE.164 number to send FROM — one of the WhatsApp numbers your API key is bound to. REQUIRED on every send, alongside `to`.
bodyTextstringrequiredMain message body (1024 char max)
buttonsarray<{id,title}>required1–3 buttons. id ≤ 256 chars; title ≤ 20 chars.
headerTextstringoptionalOptional header line
footerTextstringoptionalOptional footer line

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-api/messages/buttons' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "headerText": "Order #1234",
  "bodyText": "Your order is ready. What would you like to do?",
  "footerText": "WAAPI demo",
  "buttons": [
    {
      "id": "track",
      "title": "Track"
    },
    {
      "id": "cancel",
      "title": "Cancel"
    },
    {
      "id": "support",
      "title": "Talk to support"
    }
  ]
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "wamid.HBgM...",
    "status": "sent",
    "to": "917890000198",
    "type": "interactive"
  }
}
Error responses (1)

HTTP 400Too many buttons

{
  "success": false,
  "error": "(#100) buttons must be 1-3 items"
}
POST/whatsapp-api/messages/text

3a. Send Text Message

Permissions: messages.send

Send a plain text message. Outside the 24-hour customer service window only TEMPLATES are allowed; this endpoint will error there.

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164
fromPhoneNostringrequiredE.164 number to send FROM — one of the WhatsApp numbers your API key is bound to. REQUIRED on every send, alongside `to`.
bodystringrequiredMessage text (4096 char max)
previewUrlbooleanoptionalIf true, the first URL in body gets a link preview card

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-api/messages/text' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "body": "Hello from the WAAPI public API.",
  "previewUrl": false
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "wamid.HBgM...",
    "status": "sent",
    "to": "917890000198",
    "type": "text"
  }
}
Error responses (1)

HTTP 400Outside service window

{
  "success": false,
  "error": "(#131047) Re-engagement message: outside 24h window — send a template instead"
}
POST/whatsapp-api/messages/image

3b. Send Image

Permissions: messages.send

Send an image by public URL (`link`) or by a previously uploaded Meta media id (`mediaId`). One of the two is required.

Note: Variants: /whatsapp-api/messages/video (mp4/3gp, ≤16 MB), /messages/audio (aac/mp3/ogg/amr/m4a, ≤16 MB), /messages/sticker (webp).

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164
fromPhoneNostringrequiredE.164 number to send FROM — one of the WhatsApp numbers your API key is bound to. REQUIRED on every send, alongside `to`.
linkstringoptionalPublic HTTPS URL of a JPG/PNG (≤5 MB)
mediaIdstringoptionalMeta media_id from /media upload (≤30 days)
captionstringoptionalOptional caption (1024 char max)

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-api/messages/image' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "link": "https://example.com/order.jpg",
  "caption": "Your order, packed"
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "wamid.HBgM...",
    "status": "sent",
    "type": "image"
  }
}
POST/whatsapp-api/messages/document

3c. Send Document

Permissions: messages.send

Send any document file (PDF, DOCX, XLSX, CSV, etc.) up to 100 MB. The filename you pass is what the recipient sees in WhatsApp.

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164
fromPhoneNostringrequiredE.164 number to send FROM — one of the WhatsApp numbers your API key is bound to. REQUIRED on every send, alongside `to`.
linkstringoptionalPublic HTTPS URL of the file
mediaIdstringoptionalMeta media_id from /media upload
filenamestringoptionalDisplay filename shown to the recipient
captionstringoptionalOptional caption (1024 char max)

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-api/messages/document' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "link": "https://example.com/invoice-1234.pdf",
  "filename": "Invoice 1234.pdf",
  "caption": "Your invoice"
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "wamid.HBgM...",
    "status": "sent",
    "type": "document"
  }
}
POST/whatsapp-api/messages/send

5. Send Message + Update Contact (combined)

Permissions: messages.sendcontacts.write

Flagship endpoint: atomically upserts the contact AND dispatches ANY supported message type in one request. Saves a network round trip for CRM-style flows.

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164
fromPhoneNostringrequiredE.164 number to send FROM — one of the WhatsApp numbers your API key is bound to. REQUIRED on every send, alongside `to`.
countryCodestringoptionalDefaults to +91
contactobjectoptionalSame shape as POST /contacts (first_name, last_name, email, tags…). Pass an empty {} to skip upsert and only send.
typeenumrequiredOne of: 'text' | 'image' | 'video' | 'audio' | 'document' | 'template' | 'buttons' | 'list' | 'cta'
payloadobjectrequiredType-specific payload — same shape as the dedicated /messages/<type> endpoint

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-api/messages/send' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "contact": {
    "first_name": "Sayantan",
    "email": "sayantan@example.com",
    "tags": [
      "new-lead"
    ]
  },
  "type": "text",
  "payload": {
    "body": "Hi Sayantan, thanks for signing up. Your account is now active."
  }
}'

Success response

{
  "success": true,
  "data": {
    "contact": {
      "_id": "6a2c5...",
      "phoneNumber": "917890000198",
      "first_name": "Sayantan",
      "email": "sayantan@example.com",
      "tags": [
        "new-lead"
      ]
    },
    "message": {
      "messageId": "wamid.HBgM...",
      "status": "sent",
      "to": "917890000198",
      "type": "text"
    }
  }
}
Error responses (2)

HTTP 403Missing perm

{
  "success": false,
  "error": "API key needs 'contacts.write' for combined send+upsert"
}

HTTP 400Bad type

{
  "success": false,
  "error": "Unsupported type 'sticker-pack'"
}

Contacts (/contacts)

PATCH/contacts

4. Update Contact

Permissions: contacts.write

Partial update keyed by phone number. Only the fields you include in `updates` are written — every other field is untouched. Use this for CRM-driven name/email/tag sync without risking data loss.

Note: Use POST /contacts instead when you want create-or-update (upsert). PATCH only updates existing rows.

FieldTypeReq?Description
phoneNumberstringrequiredPhone in any format (we normalize)
countryCodestringoptionalDefaults to +91 if absent
updates.first_namestringoptional
updates.last_namestringoptional
updates.profile_namestringoptionalWhatsApp display name override
updates.emailstringoptional
updates.tagsstring[]optionalReplaces the existing tag list

Request

curl --request PATCH \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/contacts' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "phoneNumber": "917890000198",
  "countryCode": "+91",
  "updates": {
    "first_name": "Sayantan",
    "last_name": "Kar",
    "tags": [
      "vip",
      "crm-sync"
    ]
  }
}'

Success response

{
  "success": true,
  "data": {
    "_id": "6a2c5...",
    "phoneNumber": "917890000198",
    "first_name": "Sayantan",
    "last_name": "Kar",
    "tags": [
      "vip",
      "crm-sync"
    ]
  }
}
Error responses (2)

HTTP 404Not found

{
  "success": false,
  "error": "Contact not found"
}

HTTP 400Nothing to update

{
  "success": false,
  "error": "No updatable fields provided"
}

WhatsApp QR — Send endpoints (/whatsapp-qr/*)

Send through a connected QR linked-device session. Requires an API key with the WhatsApp QR service enabled. A QR "number" is a session, not a Meta phoneNumberId — select it with sessionId or fromPhoneNo.

POST/whatsapp-qr/messages/text

QR · Send Text

Permissions: messages.send

Send a plain text message from a connected WhatsApp QR session. Requires a key with the WhatsApp QR service enabled. No 24-hour customer-service-window restriction applies.

Note: Variants: /whatsapp-qr/messages/image, /video, /audio, /document, /location (use `link` for the media URL).

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164 (no @s.whatsapp.net needed)
bodystringrequiredMessage text
fromPhoneNostringrequiredE.164 of the connected QR number to send FROM (matches a session). Required unless you pass `sessionId`.
sessionIdstringoptionalExplicit QR session id — an alternative to fromPhoneNo for choosing the sending session.

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-qr/messages/text' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "body": "Hello from a WAAPI QR session."
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "BAE5...",
    "from": "917890000199",
    "sessionId": "sess_abc",
    "to": "917890000198@s.whatsapp.net",
    "type": "text"
  }
}
Error responses (2)

HTTP 400No session

{
  "success": false,
  "error": "No connected WhatsApp QR session found. Connect a device first."
}

HTTP 403Wrong service

{
  "success": false,
  "message": "This API key is not authorized for the WhatsApp QR service"
}
POST/whatsapp-qr/messages/image

QR · Send Image

Permissions: messages.send

Send an image from a connected QR session by public URL.

FieldTypeReq?Description
tostringrequiredRecipient phone in E.164
linkstringrequiredPublic HTTPS URL of the image
captionstringoptionalOptional caption
fromPhoneNostringrequiredE.164 of the QR number to send FROM. Required unless you pass `sessionId`.

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-qr/messages/image' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "917890000198",
  "fromPhoneNo": "+917890000199",
  "link": "https://example.com/order.jpg",
  "caption": "Your order"
}'

Success response

{
  "success": true,
  "data": {
    "messageId": "BAE5...",
    "sessionId": "sess_abc",
    "type": "image"
  }
}
GET/whatsapp-qr/sessions

QR · List Sessions

Permissions: messages.read

List the vendor's connected QR sessions so you can discover the numbers you can send from.

Request

curl --request GET \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external/whatsapp-qr/sessions' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \

Success response

{
  "success": true,
  "data": [
    {
      "sessionId": "sess_abc",
      "sessionName": "Primary",
      "phoneNumber": "917890000199",
      "status": "connected"
    }
  ],
  "count": 1
}

Webhooks

Configure a Webhook URL on an API key and the platform forwards every matching event it receives from Meta — incoming messages, delivery/read/failed status updates, and template status changes — to that URL. The payload is Meta's native envelope ({ object, entry:[{ id, changes:[…] }] }), untransformed. Each key is one webhook; create more keys to fan the same events out to unlimited endpoints. Pick which events a key receives in the panel (no selection = all events).

Signature. Every delivery carries X-Hub-Signature-256: sha256=<hmac> — HMAC-SHA-256 of the raw body using your key's webhookVerifyToken (shown once at create). Verify it before trusting the payload. Deliveries also carry X-WAAPI-Event (the event type, e.g. messages) and X-WAAPI-Delivery (a unique id). ACK with any 2xx; non-2xx / timeouts are retried with backoff (5xx/408/429 only). Use the Send test event button on a key to verify your endpoint.

POST{your-callback-url}

Incoming Text Message

Delivered when a customer sends you a text message. Acknowledge with HTTP 200 within 5 seconds (Meta retries with exponential backoff if you don't).

FieldTypeReq?Description
objectstringrequiredAlways 'whatsapp_business_account'
entry[].idstringrequiredWABA id
entry[].changes[].value.messages[]arrayrequiredThe actual messages
entry[].changes[].value.metadata.phone_number_idstringrequiredWhich of your numbers received the message
entry[].changes[].value.contacts[]arrayrequiredSender profile (name, wa_id)

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external{your-callback-url}' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "959648497055756",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "+91 78900 00199",
              "phone_number_id": "1226212787235581"
            },
            "contacts": [
              {
                "profile": {
                  "name": "Sayantan Kar"
                },
                "wa_id": "917890000198"
              }
            ],
            "messages": [
              {
                "from": "917890000198",
                "id": "wamid.HBgMOTE4NTk3NDA2Njk0FQIAEhgUM0EwMzQy...",
                "timestamp": "1718635789",
                "text": {
                  "body": "Hi, is the order shipped?"
                },
                "type": "text"
              }
            ]
          }
        }
      ]
    }
  ]
}'

Success response

{
  "ok": true
}
POST{your-callback-url}

Incoming Image (with caption)

Delivered when a customer sends a picture. Use `image.id` + GET /media to download bytes.

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external{your-callback-url}' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "959648497055756",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "+91 78900 00199",
              "phone_number_id": "1226212787235581"
            },
            "contacts": [
              {
                "profile": {
                  "name": "Sayantan Kar"
                },
                "wa_id": "917890000198"
              }
            ],
            "messages": [
              {
                "from": "917890000198",
                "id": "wamid.HBgMO...",
                "timestamp": "1718635892",
                "type": "image",
                "image": {
                  "caption": "Is this the right colour?",
                  "mime_type": "image/jpeg",
                  "sha256": "A2k...",
                  "id": "1234567890123456"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}'

Success response

{
  "ok": true
}
POST{your-callback-url}

Incoming Button Reply

Delivered when a customer taps a button on an interactive message you sent.

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external{your-callback-url}' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "959648497055756",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "+91 78900 00199",
              "phone_number_id": "1226212787235581"
            },
            "contacts": [
              {
                "profile": {
                  "name": "Sayantan Kar"
                },
                "wa_id": "917890000198"
              }
            ],
            "messages": [
              {
                "from": "917890000198",
                "id": "wamid.HBgMO...",
                "timestamp": "1718635950",
                "type": "interactive",
                "interactive": {
                  "type": "button_reply",
                  "button_reply": {
                    "id": "track",
                    "title": "Track"
                  }
                },
                "context": {
                  "from": "+91 78900 00199",
                  "id": "wamid.HBgMO_THE_MESSAGE_THAT_HAD_BUTTONS"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}'

Success response

{
  "ok": true
}
POST{your-callback-url}

Status — Delivered (with pricing + conversation)

Delivered when Meta finishes routing a message to the recipient device. Includes the `conversation` block (24-hour billing window id) and the `pricing` block (category Meta charged at).

FieldTypeReq?Description
statuses[].idstringrequiredThe wamid you got from our send response
statuses[].statusstringrequired'sent' | 'delivered' | 'read' | 'failed'
statuses[].conversation.idstringoptionalMeta 24h conversation id (CBP)
statuses[].conversation.origin.typestringoptionalmarketing | utility | authentication | service
statuses[].pricingobjectoptionalbillable, pricing_model, category

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external{your-callback-url}' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "959648497055756",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "+91 78900 00199",
              "phone_number_id": "1226212787235581"
            },
            "statuses": [
              {
                "id": "wamid.HBgMOTE4NTk3NDA2Njk0FQIAEhgUM0EwMzQy...",
                "status": "delivered",
                "timestamp": "1718635790",
                "recipient_id": "917890000198",
                "conversation": {
                  "id": "7e8d9f3a1c2b4d5e8f9a0b1c2d3e4f5a",
                  "expiration_timestamp": "1718722190",
                  "origin": {
                    "type": "marketing"
                  }
                },
                "pricing": {
                  "billable": true,
                  "pricing_model": "CBP",
                  "category": "marketing",
                  "type": "regular"
                }
              }
            ]
          }
        }
      ]
    }
  ]
}'

Success response

{
  "ok": true
}
POST{your-callback-url}

Status — Failed

Delivered when a message could not be delivered. `errors[]` has Meta's error code + reason.

Request

curl --request POST \
  --url 'https://cname.betazen.vendor.waapi.easycrm4u.com/api/v1/external{your-callback-url}' \
  --header 'X-API-Key: waapi_YOUR_API_KEY' \
  --header 'X-API-Secret: secr_YOUR_API_SECRET' \
  --header 'Content-Type: application/json' \
  --data '{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "959648497055756",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "+91 78900 00199",
              "phone_number_id": "1226212787235581"
            },
            "statuses": [
              {
                "id": "wamid.HBgMO...",
                "status": "failed",
                "timestamp": "1718635800",
                "recipient_id": "917890000198",
                "errors": [
                  {
                    "code": 131026,
                    "title": "Message undeliverable",
                    "error_data": {
                      "details": "Recipient phone number does not have WhatsApp installed"
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  ]
}'

Success response

{
  "ok": true
}

Postman collection

The full collection (v2.1) covers every endpoint on this page plus the webhook examples. Import into Postman, set your baseUrl, apiKey, and apiSecret collection variables, and run.

Download Vendor_External_API.json