HelpStackDocs

Integrations

Webhooks

Inbound webhook endpoints for Meta channels: Facebook Messenger, Instagram DM, and WhatsApp.

Quick facts#

Base URLhttps://helpstack.eu/api/webhooks
Auth (verify)hub.verify_token must equal the configured verify token (GET handshake)
Auth (receive)x-hub-signature-256: sha256=<HMAC-SHA256(rawBody, FACEBOOK_APP_SECRET)>
Content-Typeapplication/json
VisibilityEndpoints are public; security is the token + signature

Webhooks are received at helpstack.eu; you register that callback URL in the Meta App dashboard. The verify token and app secret are configured by HelpStack (see the environment variables referenced below).

How the handshake works (all providers)#

Meta verifies a webhook by sending a GET with three query params. HelpStack echoes the challenge only if the verify token matches.

GET /api/webhooks/facebook
  ?hub.mode=subscribe
  &hub.verify_token=TOKEN
  &hub.challenge=CHALLENGE
  • If TOKEN equals the configured verify token → respond 200 with the raw CHALLENGE value.
  • Otherwise → respond 403.

How signature verification works (all providers)#

Every POST carries an x-hub-signature-256 header. The signature is computed over the raw request body using HMAC-SHA256 keyed by FACEBOOK_APP_SECRET, prefixed with sha256=.

x-hub-signature-256: sha256=<hex HMAC-SHA256(rawBody, FACEBOOK_APP_SECRET)>

Node example (how to compute / verify):

import crypto from 'node:crypto';

function verifySignature(rawBody, headerValue, appSecret) {
  const expected =
    'sha256=' +
    crypto.createHmac('sha256', appSecret).update(rawBody).digest('hex');
  return headerValue === expected;
}

Gotcha — use the raw body. The signature is computed over the exact bytes Meta sent. HelpStack reads the body as raw text before parsing JSON. If you build your own verifier, do not re-serialize the parsed JSON object (key order/whitespace will differ and the signature will not match). Capture the raw body string and HMAC that.

Facebook / Messenger#

Verify endpointGET /api/webhooks/facebook
Receive endpointPOST /api/webhooks/facebook
Signature keyFACEBOOK_APP_SECRET
Verify token envFACEBOOK_VERIFY_TOKEN

Inbound payload shape. The body contains an entry[] array. Each entry has either:

  • entry[].messaging[] — legacy Messenger format, or
  • entry[].changes[] — newer format.

Channel matching & processing. The handler matches a channel by facebookPageId / credentials.pageId, then:

  1. Creates or updates a conversation keyed by the sender PSID.
  2. Stores the inbound message.
  3. Fetches the sender's profile and downloads attachments to storage.
  4. Emits a real-time event to the dashboard.

Instagram#

EndpointGET/POST /api/webhooks/instagram
Signature keyFACEBOOK_APP_SECRET
Verify token envINSTAGRAM_VERIFY_TOKEN (falls back to FACEBOOK_VERIFY_TOKEN)

Matches OAuth-managed channels by Instagram account id. Handshake and signature verification work the same as Facebook.

WhatsApp#

EndpointGET/POST /api/webhooks/whatsapp
Signature keyFACEBOOK_APP_SECRET
Verify token envWHATSAPP_VERIFY_TOKEN (falls back to FACEBOOK_VERIFY_TOKEN)

Inbound payload shape. The body contains entry[].changes[].value with messages[] and contacts[]. The handler matches a channel by credentials.phoneNumberId and keys the conversation by the sender's phone number.

Environment variables#

VariableUsed byPurpose
FACEBOOK_APP_SECRETFB, IG, WhatsAppHMAC-SHA256 signature key for x-hub-signature-256
FACEBOOK_VERIFY_TOKENFB (IG/WhatsApp fallback)GET handshake verify token
INSTAGRAM_VERIFY_TOKENInstagramVerify token; falls back to FACEBOOK_VERIFY_TOKEN
WHATSAPP_VERIFY_TOKENWhatsAppVerify token; falls back to FACEBOOK_VERIFY_TOKEN

Register in the Meta App dashboard#

For Messenger (the same pattern applies to Instagram and WhatsApp with their endpoints):

  1. In the Meta App dashboard, open the product (Messenger / Instagram / WhatsApp) → Webhooks.
  2. Callback URL: https://helpstack.eu/api/webhooks/facebook (Instagram: .../api/webhooks/instagram, WhatsApp: .../api/webhooks/whatsapp.)
  3. Verify token: the value you set in FACEBOOK_VERIFY_TOKEN (or the provider-specific token).
  4. Click Verify and Save — Meta sends the GET handshake; it succeeds when the token matches.
  5. Subscribe to fields: subscribe to the messages / messaging fields so message events are delivered.
  6. Ensure your app's App Secret matches FACEBOOK_APP_SECRET so signature verification passes on POST.

After saving, send a test message to the page/account — it should appear as a new conversation in the dashboard.