WhatsApp Webhooks

WhatsApp Webhooks

WhatsApp webhooks integration allows for real-time notifications of message status updates and WhatsApp user engagement.


Go to WhatsApp > Accounts in the left hand menu in your SMSPortal account, click the numbers tab and select webhooks from the actions button where you can configure your Status and Replies per number.

Technical Details

All WhatsApp webhooks are sent as HTTP POST requests with static JSON bodies. Your system must respond with a valid 2xx HTTP response code for us to deem a webhook as successful. The response body is not read or stored by our system.

All failed webhooks are retried up to 5 times with exponential backoff.

NOTE: We will not make breaking changes to our webhook bodies by removing fields, renaming fields, or changing the JSON structure without notice. However, new fields may be added without notice, and we expect all webhook integrations to use robust JSON parsing that can successfully parse and ignore new fields.

All webhooks include the following predefined HTTP headers. Additional custom webhook headers can be configured on the webhook.

Fixed Webhook Headers

HeaderValueDescription
Content-Typeapplication/json; charset=utf-8Indicates the request body is JSON encoded in UTF-8.
Content-LengthComputed per requestSize of the request body in bytes.
User-AgentSMSPortal Webhook EngineSMSPortal webhook engine user agent.
Webhook-Engine-Key-IdIdentifier of the signing key usedSpecifies which signing key generated the request signature.
Webhook-Engine-SignatureSignature for this requestCryptographic signature to verify authenticity.
Webhook-Engine-TimestampWhen the webhook was signedTimestamp used for signature validation.
Webhook-Engine-RetriesNumber of retry attemptsIndicates how many times the webhook has been attempted.

Performance

All webhooks you receive must be processed out of band from the main webhook request/response flow.

Best practice is to:

  1. Place the received webhook onto an internal queue in your system.
  2. Immediately respond to the webhook request (~250ms) before starting additional processing.
  3. Process the webhook data asynchronously afterward.

If our servers do not receive a 2xx response code before we time the request out, we will assume the webhook failed and retry based on the retry scheme.


Webhook Security

There are two ways to improve webhook security:

  • IP whitelisting
  • Signature validation

Originating IP Addresses

All webhook messages originate from one of the following IP addresses:

  • 105.29.233.2
  • 102.205.164.49
  • 102.205.166.49

Signature Validation

Signature validation requires an active signature setup via our control panel.

To verify a webhook signature please go through the following steps:

  1. Concatenate the Webhook-Engine-Timestamp and the request body as follows:

    v1:{Timestamp}|{RequestBody}
  2. Compute the HMAC-SHA256 hash of the previous step, using the key secret as the key for the algorithm.

  3. The output from the previous step should match the hexadecimal formatted value in the Webhook-Engine-Signature.

The Webhook-Engine-Signature contains the signature version and the algorithm used to compute the request hash, for example:

v1,hmac_sha256=<signature>

NOTE: If the Webhook-Engine-Signature header equals
v1,hmac_sha256=CANNOT SIGN REQUEST WITHOUT SECRET KEY!
then the account does not have a signature key configured.


Outbound Message States

There are 5 states a WhatsApp message can be in once submitted and accepted by our platform:

  • Submitted
    We have received the message and passed it on to Meta for final termination
    (There is no webhook for this. the successful response from our rest API is the signal for this state.)

  • Sent
    This is sent when we are notified by Meta that the message has been sent out to the WhatsApp user and a delivery is expected.

  • Delivered
    The message has been successfully delivered to the WhatsApp user.

  • Read
    The message has been read by the WhatsApp user. Not all WhatsApp users have read receipts enabled so not all delivered messages will result in a read status.

  • Failed
    The message is unable to be delivered. The error code will indicate what the reason for failure was.

Note: If the WhatsApp user has the chat open you may not receive a Delivered status and only receive a Read status, in which case the Read status implies the message has been Delivered.


Webhook Types

All webhooks are sent in batches. Each message in the batch must be handled individually.

Batches cannot partially succeed. Batches cannot succeed partially and if a 2xx response code is received it is assumed the whole batch has been successfully received.


Status Webhooks

Status webhooks notify you when a message has changed status.

All status webhooks are sent as HTTP POST requests with a static JSON body, see the below example.

Example

[
  {
    "Wamid": "wamid.HBgLMjc3OTkzNDAwMzYVAgARGBJDN0RFMUFDMjlGQkVBNDg5MUEA",
    "MessageId": 123456,
    "CustomerId": "ed3622cc-91c6-4413-a258-32676b98508c",
    "BusinessPhoneNumberId": "891234567890123",
    "BusinessDisplayNumber": "27000000001",
    "DestinationNumber": "27000000002",
    "Status": "Delivered",
    "ErrorCode": "",
    "ErrorDetail": "No error",
    "Timestamp": 1763999491
  }
]

Fields

FieldTypeNot NullDescription
Wamidstring❎WhatsApp message ID, only generated after Meta accept the message.
MessageIdlong✅Smsportal ID, only generated after we accept the message.
CustomerIdstring❎Optional customer provided ID.
BusinessPhoneNumberIdstring✅The ID of the business phone number that sent the message.
BusinessDisplayNumberstring✅The business phone number shown to the WhatsApp user.
DestinationNumberstring✅WhatsApp user's number.
Statusstring✅Status of the message, one of: Sent, Delivered, Read or Error
ErrorCodestring❎Error code (see Outbound Error Codes).
ErrorDetailstring❎Error code description.
Timestamplong✅Timestamp of the status update as a UNIX timestamp (the number of seconds that have elapsed since January 1, 1970, midnight UTC/GMT)

Outbound Error Codes

Error CodeDescription
Message.RejectedThe message was valid, but was rejected by WhatsApp.
Message.InvalidThe message failed validation.
Message.Invalid.TemplateThe message failed template validation.
Message.UndeliverableThe message was not delivered to the recipient.
Message.Undeliverable.RateLimitThe message was not delivered due to rate limiting.
WabaErrorSomething on your account is preventing the message from being sent.
UnknownErrorAn unknown error occurred, please contact support.

Reply Webhooks

Reply webhooks notify you when a WhatsApp user has engaged with your WhatsApp Business number.

Examples include:

  • A user sends you a message
  • A User reacts to a message in the chat
  • A user interacts with a template message option you have sent them.

All reply webhooks are sent as HTTP POST requests with a static JSON body.

Note: Responses containing media (images, videos, documents, stickers, voice notes, and audio) will have an ID and a link to download the media content included in the webhook, but the actual media will not be included in the webhook. The link requires the same authentication used to send messages.

Example

[
 {
    "Wamid": "wamid.HBgLMjc3OTkzNDAwMzYVAgARGBJDN0RFMUFDMjlGQkVBNDg5MUEA",
    "BusinessPhoneNumberId": "891234567890123",
    "BusinessDisplayNumber": "27000000001",
    "SourceNumber": "27000000002",
    "ContentType": "text",
    "Content": "The reply body",
    "ButtonPayload": "OrderId=123",
    "PreviousMessage": {
      "Wamid": "wamid.HBgLMjc3OTkzNDAwMzYVAgARGBJDN0RFMUFDMjlGQkVBNDg5MUEA",
      "Explicit": false
    },
    "Timestamp": 1763999491,
    "Attachments": {
      "Media": {
        "MediaId": 69000123,
        "MimeType": "image/jpeg",
        "Link": "https://rest.smsportal.com/whatsapp/media/6900013/download"
      },
      "Contacts": [
        {
          "Name": {
            "FormattedName": "Joe Soap"
          },
          "Phones":[
            {
              "Number": "27810496640",
              "Type": "MOBILE"
            }
          ]
        }
      ],
      "Location": {
        "Latitude": 56.1235,
        "Longitude": 12.1231
      }
    }
  }
]

Fields

FieldTypeNot NullDescription
Wamidstring✅Meta message ID.
BusinessPhoneNumberIdstring✅Meta business phone number ID.
BusinessDisplayNumberstring✅Display phone number (the "to" number).
SourceNumberstring✅WhatsApp user's phone number (the "from" number).
ContentTypestring✅Type of the reply, one of: text, reaction, button, location, contact or media.
Contentstring✅The reply content or the caption of a media message (if it was provided).
ButtonPayloadstring❎Optional additional data attached to quick reaction message buttons.
PreviousMessageobject❎Context information about the previous message being replied to, e.g. the message that was reacted to or explicilty replied to.
PreviousMessage.Wamidstring❎The message ID (wamid) of the context message.
PreviousMessage.Explicitboolean❎Indicates whether the reply targeted a specific message.
Timestamplong✅Timestamp of the status update as a UNIX timestamp (the number of seconds that have elapsed since January 1, 1970 midnight UTC/GMT).
Attachmentsobject❎Rich content attached to the message.
Attachments.Mediaobject❎Details of the attached Media, used for images, videos, stickers, documents and audio.
Attachments.Media.MediaIdlong❎The Id of received media, required to download the media.
Attachments.Media.MimeTypestring❎The MIME type of the media.
Attachments.Media.Linkstring❎The URL to download the media from (authentication is required).
Attachments.Contactslist❎A list of contacts attached to the message.
Attachments.Contacts.Nameobject❎The details of the name for the contact.
Attachments.Contacts.Name.FormattedNamestring❎The formatted name of the contact.
Attachments.Contacts.Phoneslist❎A list of phone numbers for the contact.
Attachments.Contacts.Phones.Typestring❎The type of number e.g. CELL or WORK.
Attachments.Contacts.Phones.Numberstring❎The phone number.
Attachments.Locationobject❎The location attached to the message.
Attachments.Location.Latitudedouble❎The latitude of the location pin.
Attachments.Location.Longitudedouble❎The longitude of the location pin.

Did this page help you?