Integrations

Webhook Forwarding

Forward WhatsApp message events from WAppChat into your external system while keeping WAppChat as the reliable WhatsApp message ledger.

Updated May 24, 2026

Webhook forwarding lets your external system receive WhatsApp message events from WAppChat in real time.

Use this when your team already works inside its own property management system, support desk, or booking platform, but wants WhatsApp conversations synced there.

How It Works #

Guest messages your WhatsApp number
-> Meta sends the webhook to WAppChat
-> WAppChat stores the contact, conversation, and message
-> WAppChat forwards a webhook event to your external system
-> Your external system displays the message in its own inbox

For replies:

Agent replies inside your external system
-> Your external system calls the WAppChat send API
-> WAppChat sends the message through Meta WhatsApp Cloud API
-> WAppChat stores and forwards the sent-message event

What WAppChat Stores #

WAppChat stores WhatsApp communication records even when Webhook forwarding is enabled.

Stored data includes:

  • contact name and phone number
  • conversation ID and status
  • message content and message type
  • inbound or outbound direction
  • Meta WhatsApp message ID
  • timestamps
  • delivery status such as sent, delivered, read, or failed
  • service-window metadata
  • routing, automation, and contact metadata

This storage is required for message history, delivery tracking, debugging, audit logs, duplicate prevention, automation, and WhatsApp 24-hour service-window checks.

Your external system can remain the source of truth for business data such as guests, bookings, properties, agents, and reservations. WAppChat acts as the WhatsApp communication ledger and delivery layer.

Availability #

Webhook forwarding is intended for teams integrating WAppChat with an external system.

Recommended plan placement:

WhatsApp Business

Basic inbox and message storage can be available on lower WhatsApp plans. External Webhook forwarding and reply-through-API integration should be treated as a Business or custom integration feature.

Setup #

Open:

WhatsApp Settings -> External Webhook Forwarding

Configure:

Enabled: on
Webhook URL: https://your-system.com/webhooks/wappchat
Signing secret: optional shared secret

Production webhook URLs must use HTTPS.

Events #

WAppChat sends these event types:

whatsapp.message.received
whatsapp.message.sent

whatsapp.message.received is sent after an inbound WhatsApp message is stored.

whatsapp.message.sent is sent after WAppChat sends and stores an outbound WhatsApp message.

Headers #

Webhook requests include:

Content-Type: application/json
User-Agent: WAppChat-Webhook-Forwarding/1.0
x-wappchat-event: whatsapp.message.received
x-wappchat-timestamp: 1779111111

If a signing secret is configured, WAppChat also sends:

x-wappchat-signature: sha256=<hex-hmac>

Signature Verification #

The signed payload is:

{unix_timestamp}.{raw_json_body}

The signature uses HMAC SHA-256 with the Webhook signing secret.

Node.js example:

import crypto from "crypto";

function verifyWappChatWebhook({ rawBody, timestamp, signature, secret }) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  const actual = signature.replace(/^sha256=/, "").trim();

  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(actual, "hex")
  );
}

Reject requests with old timestamps to reduce replay risk.

Example Received Message Payload #

{
  "event": "whatsapp.message.received",
  "tenant": {
    "id": "tenant_123"
  },
  "phone_number_id": "1234567890",
  "contact": {
    "id": "contact_123",
    "name": "Abdallah",
    "phone": "917205290217",
    "tags": [],
    "metadata": {
      "external": {
        "guest_id": "guest_123",
        "booking_id": "booking_456",
        "property_id": "property_789"
      }
    }
  },
  "conversation": {
    "id": "conversation_123",
    "status": "OPEN",
    "last_message_at": "2026-05-24T12:00:00.000Z",
    "service_window_expires_at": "2026-05-25T12:00:00.000Z",
    "metadata": {}
  },
  "message": {
    "id": "message_123",
    "wa_message_id": "wamid...",
    "direction": "INBOUND",
    "type": "TEXT",
    "status": "RECEIVED",
    "text": "Can I get the wifi details?",
    "content": {
      "from": "917205290217",
      "id": "wamid...",
      "timestamp": "1779111111",
      "type": "text",
      "text": {
        "body": "Can I get the wifi details?"
      }
    },
    "created_at": "2026-05-24T12:00:00.000Z"
  }
}

Example Sent Message Payload #

{
  "event": "whatsapp.message.sent",
  "tenant": {
    "id": "tenant_123"
  },
  "phone_number_id": "1234567890",
  "contact": {
    "id": "contact_123",
    "name": "Abdallah",
    "phone": "917205290217",
    "tags": [],
    "metadata": {}
  },
  "conversation": {
    "id": "conversation_123",
    "status": "OPEN",
    "last_message_at": "2026-05-24T12:01:00.000Z",
    "service_window_expires_at": "2026-05-25T12:00:00.000Z",
    "metadata": {}
  },
  "message": {
    "id": "message_124",
    "wa_message_id": "wamid...",
    "direction": "OUTBOUND",
    "type": "TEXT",
    "status": "SENT",
    "text": "Sure, the WiFi is MarinaGuest and the password is welcome204.",
    "content": {
      "messaging_product": "whatsapp",
      "recipient_type": "individual",
      "to": "917205290217",
      "type": "text",
      "text": {
        "preview_url": false,
        "body": "Sure, the WiFi is MarinaGuest and the password is welcome204."
      }
    },
    "created_at": "2026-05-24T12:01:00.000Z"
  }
}

Replying From Your External System #

To send a reply from your external system, call the WAppChat send API:

POST https://wapp.chat/api/whatsapp/send
Content-Type: application/json
Authorization: Bearer <user-access-token>

Text reply:

{
  "phone_number": "917205290217",
  "type": "text",
  "text": "Sure, the WiFi is MarinaGuest and the password is welcome204."
}

Template message:

{
  "phone_number": "917205290217",
  "type": "template",
  "template": {
    "name": "appointment_confirmation",
    "language": {
      "code": "en_US"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "Abdallah"
          },
          {
            "type": "text",
            "text": "Marina Studio 204 check-in on May 24, 2026 at 3:00 PM"
          }
        ]
      }
    ]
  }
}

Free-form text replies require an open WhatsApp customer service window. Use approved Meta templates to start or reopen a conversation.

When your external system receives a webhook:

  1. Verify the signature if a signing secret is configured.
  2. Use message.wa_message_id for deduplication.
  3. Match the contact by contact.phone.
  4. Attach the message to the correct external conversation, guest, booking, or property.
  5. Store WAppChat IDs such as contact.id, conversation.id, and message.id for future troubleshooting.
  6. Reply through the WAppChat send API when an agent sends an external message.

Failure Behavior #

Webhook forwarding happens after WAppChat stores the WhatsApp message.

If your webhook endpoint is unavailable or returns an error:

  • the WhatsApp message remains stored in WAppChat
  • the WAppChat inbox can still show the conversation
  • forwarding failure is logged for troubleshooting
  • WhatsApp delivery is not blocked by your webhook outage

Keep your webhook endpoint fast and return a 2xx response after accepting the event.