The Basics Overview

Base URL, authentication, message send payloads, and webhook subscription basics.

Base URL

Dualhook uses Meta Graph API endpoints.

Typical Meta pattern:

  • Base: https://graph.facebook.com/<GRAPH_VERSION>/
  • Send messages: POST /<PHONE_NUMBER_ID>/messages
  • Manage subscriptions/override: POST /<WABA_ID>/subscribed_apps

Authentication Model

Dualhook uses Meta access tokens in standard bearer auth:

  • Authorization: Bearer <ACCESS_TOKEN>

Example Payload: Send Text Message

{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "12015550123",
  "type": "text",
  "text": {
    "body": "Hello there"
  }
}

Example Request: Send Text Message (cURL)

curl -X POST "https://graph.facebook.com/<GRAPH_VERSION>/<PHONE_NUMBER_ID>/messages" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product":"whatsapp",
    "recipient_type":"individual",
    "to":"12015550123",
    "type":"text",
    "text":{"body":"Hello there"}
  }'

Sending Messages (Dualhook Context)

For outgoing messages:

  1. Call Meta Cloud API directly from your backend.
  2. Use your phone_number_id in the endpoint path.
  3. Send JSON payloads according to message type.

Dualhook does not proxy message send requests.

Example Payload: Configure Webhook Override

{
  "override_callback_uri": "https://api.yourcompany.com/webhooks/whatsapp",
  "verify_token": "your-verify-token",
  "subscribed_fields": ["messages", "history", "smb_message_echoes"]
}

Example Request: Configure Webhook Override (cURL)

curl -X POST "https://graph.facebook.com/<GRAPH_VERSION>/<WABA_ID>/subscribed_apps" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "override_callback_uri":"https://api.yourcompany.com/webhooks/whatsapp",
    "verify_token":"your-verify-token",
    "subscribed_fields":["messages","history","smb_message_echoes"]
  }'

Example Webhook Payload: Incoming Message

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "15550001234",
              "phone_number_id": "123456789012345"
            },
            "contacts": [
              {
                "profile": { "name": "Alex Example" },
                "wa_id": "12015550123"
              }
            ],
            "messages": [
              {
                "from": "12015550123",
                "id": "wamid.HBgLMTIwMTU1NTAxMjMVAgARGBI...",
                "timestamp": "1735939200",
                "text": { "body": "Hi" },
                "type": "text"
              }
            ]
          }
        }
      ]
    }
  ]
}

Receiving Messages and Statuses

Webhook events are asynchronous.

In Dualhook setup:

  • messages, history, and smb_message_echoes are configured with Webhook Override to your endpoint.
  • Message content flows directly from Meta to your webhook URL.
  • Dualhook is not in the message content path.

Clarification on "Subscription"

Dualhook still performs WABA subscription configuration to set webhook behavior. However, with override configured, message webhooks are delivered to your endpoint (not Dualhook).

Dualhook mainly consumes management/operational events for dashboarding (template status, quality/account alerts, and related metadata).

Related

  • Messaging OverviewCore messaging endpoint, text messages, formatting, delivery statuses, and common errors.
  • Webhook OverrideHow Dualhook uses Meta's Webhook Override to route message webhooks directly to your server.
  • Messaging WebhookReal-time webhook events for inbound messages, delivery statuses, and errors.
Browse more docsGet started with Dualhook