Home/Features/Webhooks

Integrations

Outbound Webhooks

Get signed, real-time HTTP callbacks for 15 event types, new messages, contacts, leads, broadcasts and more, into Make, Pabbly, n8n or your own systems.

By Chirag Darji · Updated 26 Aug 2026 · 11 min read

Plans: All plans. Webhook endpoints are managed under Settings, which requires the org settings permission (Owner or Admin, or a custom role with that access); there is no separate plan cap on the number of endpoints or events.

On this page
  1. What you get
  2. How it works
  3. What events can I subscribe to?
  4. What does a payload actually look like?
  5. How do I verify the signature?
  6. Why does a webhook URL sometimes get rejected?
  7. How does this power the Zapier integration?
  8. With VGraple CRM webhooks vs a typical WhatsApp CRM
  9. Who uses it
  10. What Meta allows
  11. Plans and limits
  12. Recent improvements
Outbound webhooks in VGraple CRM with the events each endpoint subscribes to and its delivery status

In short

  • 15 event types, from message.received and contact.created to broadcast.completed and form.submitted
  • Every delivery is signed with HMAC-SHA256 in an X-Signature-256 header, the same pattern Stripe uses
  • Failed deliveries retry automatically at 1 minute, 5 minutes and 30 minutes, then stop
  • An SSRF guard blocks endpoints that resolve to localhost, private IP ranges or the cloud metadata address, checked at creation and again at send time

Outbound webhooks send a signed HTTP POST to a URL you control the moment something happens in VGraple CRM, a message arrives, a contact is created, a broadcast finishes, so your own systems, or a tool like Make, Pabbly Connect or n8n, can react in real time instead of polling an API. What changes for a business is that WhatsApp events stop being locked inside the inbox: a new lead can trigger a Slack alert, a completed broadcast can update a spreadsheet, an opted-out contact can sync to an external list, all without anyone checking the CRM by hand.

What you get

  • 15 event types covering messages, contacts, leads, broadcasts, conversations and forms
  • HMAC-SHA256 signed payloads (X-Signature-256 header), the same verification pattern Stripe uses
  • Automatic retry on failure at 1 minute, 5 minutes and 30 minutes, then a clear failed state
  • A delivery log per endpoint showing every attempt, its response status and body
  • An SSRF guard that blocks private, loopback and cloud-metadata hosts, checked at save time and again at send time
  • The same event system that powers the built-in Zapier app, so any endpoint you build works identically to a Zap

How it works

  1. Open Settings > Webhooks. The page lists every endpoint your organisation has created, its subscribed events, whether it is active, and how many deliveries it has made. Endpoints created by the Zapier integration show a "Zapier" badge here.

API keys in VGraple CRM with prefix, creation date and last use

  1. Add an endpoint. Enter the URL your receiver listens on and pick one or more events from the 15-item catalog. The URL is validated immediately: it must be https or http, it must not contain embedded credentials, and it must not resolve to a private, loopback or link-local address.

  2. Copy the signing secret. The endpoint's secret (formatted whsec_...) is shown exactly once at creation. Store it in your receiver's environment so it can verify the X-Signature-256 header on every incoming request.

  3. The event fires and VGraple CRM POSTs the payload. The instant the underlying action happens (a message arrives, a lead is created), a signed JSON envelope is sent to every active endpoint subscribed to that event type, in parallel if you have more than one.

  4. Your endpoint responds, and the delivery is logged. A 2xx status is recorded as delivered; anything else, or a timeout, is recorded as failed and queued for retry. The delivery log on the endpoint's detail view shows the response status and the first 500 characters of the response body for every attempt.

  5. A failed delivery retries automatically. Three retries follow, at 1 minute, 5 minutes and 30 minutes after the first failure. If the third retry also fails, the delivery is marked failed permanently and stops retrying; you can see exactly which delivery failed and why in the log.

What events can I subscribe to?

The event catalog covers the actions most integrations actually need to react to, not every internal state change. Subscribing an endpoint to an event means it receives that event's payload the moment it happens; you choose per endpoint which of the 15 to receive.

WhatsApp channel settings in VGraple CRM with Embedded Signup and coexistence mode connect options

EventFires when
message.receivedA customer's inbound message is saved to a conversation
message.sentAn agent, automation rule or API call sends an outbound message
contact.createdA new contact is created from any real source (inbound message, manual add, CSV import, lead, Calendly, comment DM, API); synthetic web-chat placeholder contacts do not fire it
contact.opted_outA contact opts out of messaging
lead.createdA new lead is created, from any of the six lead sources
lead.stage_changedA lead moves to a different pipeline stage
broadcast.startedA broadcast campaign begins sending
broadcast.pausedA broadcast auto-parks (template pause, portfolio pacing, red quality, quota, failure rate)
broadcast.completedA broadcast finishes, including crash-recovery completion after a deploy
broadcast.failedA broadcast ends in a failed state
broadcast.replyA recipient replies to a broadcast
conversation.assignedA conversation is assigned to an agent, manually or by SLA auto-assign
conversation.resolvedAn agent marks a conversation resolved
conversation.reopenedA resolved conversation reopens, by an agent or a new customer message
form.submittedA VGraple form is submitted

Note

Broadcast events are campaign-level, not per-recipient. A campaign reaching 10,000 contacts fires one broadcast.completed event, not 10,000 individual message events, so your endpoint is never asked to absorb a burst proportional to audience size.

What does a payload actually look like?

Every delivery is a JSON object with a stable envelope: an id prefixed evt_, a type matching the event name, a Unix created timestamp, and a data object holding the event's own payload. Here is a real message.sent shape:

{
  "id": "evt_9f2a7c1b4e8d0a3f",
  "type": "message.sent",
  "created": 1798329600,
  "data": {
    "message": {
      "id": "msg_01H...",
      "wa_message_id": "wamid.HBgL...",
      "body": "Your appointment is confirmed for Saturday at 3 PM.",
      "type": "text",
      "direction": "outbound",
      "template_name": null,
      "created_at": "2026-08-26T09:00:00.000Z"
    },
    "contact": { "id": "con_01H...", "name": "Priya Sharma", "phone": "+919876543210" },
    "conversation_id": "conv_01H..."
  }
}

A contact.created event's data.contact carries id, wa_id, name, phone, email, source, source_channel, opted_in and created_at. A lead.created event's data.lead carries id, name, phone, email, source, stage_id, stage_name, pipeline_id, contact_id, form_name and campaign_name. Every payload shape is stable across the events that share a resource, so a message.received and a message.sent event use the same message object structure with only direction differing.

How do I verify the signature?

Every request carries an X-Signature-256 header formatted sha256=<hex digest>, computed as an HMAC-SHA256 of the exact raw request body using the endpoint's secret. On your receiver, read the raw body before any JSON parsing, compute the same HMAC with your stored secret, and compare it to the header using a constant-time comparison. A mismatch means the request either did not come from VGraple CRM or the body was altered in transit, and should be rejected.

Example

A Node receiver computes "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex") and compares it to the X-Signature-256 header with crypto.timingSafeEqual. This is exactly the server-side check VGraple CRM itself uses to sign the request in the first place, so any language with an HMAC-SHA256 implementation can verify it the same way.

Why does a webhook URL sometimes get rejected?

An outbound webhook is the server making an HTTP request to whatever URL you give it, which means a URL pointing at your own internal network, a metadata endpoint, or localhost would let a webhook configuration reach infrastructure that was never meant to be internet-facing. VGraple CRM checks every webhook URL against a list of private, loopback, link-local and reserved address patterns (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x, and their IPv6 equivalents) both when you save the endpoint and again, via a DNS resolution check, at the moment of every delivery. The second check exists because a hostname can resolve to a public address when you save it and a private one later (DNS rebinding), so the guard is not a one-time gate.

Watch out

A webhook URL must resolve to a public host at all times. If your receiver moves behind a VPN, a private load balancer, or a hostname that later starts resolving internally, deliveries will start failing with "Webhook host resolves to a private or reserved address" until the URL points somewhere public again.

How does this power the Zapier integration?

The Zapier app does not have a separate delivery system; turning a Zap on calls the public API's POST /api/v1/hooks endpoint, which creates a row in the exact same webhook endpoint table described on this page, tagged with source "zapier." Every event, retry, and delivery log entry works identically whether the endpoint was created by hand in Settings or by a Zap turning on. Deleting a Zapier-created endpoint from the Settings page breaks the Zap until it is reconnected, since the two are the same underlying object.

With VGraple CRM webhooks vs a typical WhatsApp CRM

Typical WhatsApp CRMVGraple CRM webhooks
Event coverageMessage events only, if any15 events across messages, contacts, leads, broadcasts, conversations, forms
Payload authenticityOften unsigned, or a shared static tokenHMAC-SHA256 per request, verifiable without a live call back to the vendor
Failed delivery handlingOften silent, no retry, no logAutomatic retry at 1m/5m/30m with a visible delivery log
Campaign-scale eventsPer-recipient events flood the endpointCampaign-level events (started, paused, completed, failed, reply)
Internal network safetyRarely checkedSSRF guard on every URL, checked at save and at send time
Zapier compatibilityA separate, thinner integrationZapier rides the same event catalog and delivery system

Who uses it

Salons and spas wire broadcast.completed into a spreadsheet automation that logs campaign results without anyone exporting a CSV by hand. See WhatsApp CRM for salons.

D2C stores subscribe to lead.created and contact.opted_out to keep an external marketing list in sync, so a customer who stops WhatsApp marketing is not still receiving email campaigns built from a stale export. See WhatsApp CRM for D2C.

Real-estate agencies use lead.stage_changed to post a Slack message when a lead reaches "Site Visit Scheduled," so an agent's manager sees pipeline movement without opening the CRM. See WhatsApp CRM for real estate.

Coaching institutes use form.submitted to push new enrolment enquiries into a spreadsheet-based counsellor roster the moment a prospective student fills out a form. See WhatsApp CRM for coaching institutes.

What Meta allows

Meta policy

Meta's own platform does not define or restrict outbound webhooks from a Tech Provider's own CRM to a business's own systems, this is application-level infrastructure, not a WhatsApp Business Platform feature. What Meta does require is that any data you receive through these webhooks (message content, phone numbers, opt-in status) is handled in line with WhatsApp's Business Messaging Policy and your own privacy obligations to the people you are messaging.

VGraple CRM's webhook payloads carry only the data your organisation already has in its own account (its own contacts, its own messages, its own leads); nothing about another organisation on the platform is ever included, and the delivery system enforces organisation-level scoping the same way every other part of the platform does.

Plans and limits

Webhooks are available on every plan, including Free. Managing endpoints requires the org settings permission (Owner, Admin, or a custom role granted that access); agents and viewers cannot create or delete endpoints. There is no plan-based cap on user-managed endpoints or on which events you can subscribe to; API-created subscriptions, the kind the Zapier integration uses, are capped at 50 per organisation.

Recent improvements

  • 2026-07-13: The full 15-event catalog went live alongside the public API v1 and the Zapier app; every event now fires from every real code path that produces it (verified per-event against actual call sites, not just declared in the catalog).
  • 2026-07-13: contact.created deliberately excludes synthetic web-chat placeholder contacts, so an endpoint listening for new contacts is not flooded with rows for visitors who never gave contact details.
  • 2026-07-13: The SSRF guard's DNS-rebinding check was added at send time, on top of the existing save-time URL validation, closing the gap where a hostname could resolve publicly when saved and privately when actually delivered to.

Frequently asked questions

What events can I subscribe a webhook to?
15 event types across messages, contacts, leads, broadcasts, conversations and forms, listed in the table on this page. You choose which events an endpoint receives when you create it; a single endpoint can subscribe to one event or all of them.
How do I verify a webhook actually came from VGraple CRM?
Every delivery carries an X-Signature-256 header, an HMAC-SHA256 hash of the raw request body using a secret shown once when you create the endpoint. Recompute the same hash on your side and compare it before trusting the payload, the same verification pattern Stripe's webhooks use.
What happens if my endpoint is down when an event fires?
Delivery is retried automatically at 1 minute, 5 minutes and 30 minutes after the first failed attempt (a non-2xx response or a network error). After the third retry fails, the delivery is marked failed and is not retried again; the failed attempt and its response are visible in the delivery log.
Can I point a webhook at an internal or localhost URL for testing?
No. Webhook URLs are checked against a private-host guard both when you save the endpoint and again at the moment of every delivery, so a URL that resolves to localhost, a private IP range (10.x, 172.16-31.x, 192.168.x), or a cloud metadata address is rejected. This exists to stop a compromised or careless integration from using your webhook as a path into internal infrastructure.
Does VGraple CRM have a Zapier integration built on the same webhooks?
Yes. The Zapier app subscribes and unsubscribes REST hooks through the public API, which creates and deletes rows in the exact same webhook system described here; a Zapier-created endpoint shows a "Zapier" badge in Settings > Webhooks so you can tell it apart from one you configured by hand.
Can I use these webhooks with Make, Pabbly Connect or n8n?
Yes. Any tool that can receive an HTTP POST and verify (or ignore) an HMAC signature works: point its webhook-trigger URL at the endpoint field in Settings > Webhooks, choose your events, and save. Make, Pabbly Connect and n8n all support a generic "custom webhook" trigger for exactly this.
What does a webhook payload actually look like?
A JSON envelope with an id, a type matching the event name, a created Unix timestamp, and a data object holding the event-specific payload, for example a message or contact record. See the example payload on this page for the exact shape of a message.received event.
Is there a way to test a webhook without waiting for a real event?
Use the Test button on the endpoint row, which sends a synthetic message.received event to your URL and logs the response, or trigger the real action (send a test message, add a test contact). Because deliveries and their responses are logged, you can watch the delivery log fill in as soon as the real event fires and confirm your endpoint received and accepted it.
Do broadcast recipients each fire their own webhook event?
No. A broadcast firing thousands of sends does not emit one event per recipient; it emits broadcast.started, broadcast.paused, broadcast.completed and broadcast.failed at the campaign level, and broadcast.reply when someone responds. This keeps a large campaign from flooding your endpoint with one event per contact.
How many webhook endpoints can I create?
There is no hard limit on user-managed endpoints created in Settings > Webhooks. API-created subscriptions (the kind Zapier uses) are capped at 50 per organisation, enough headroom for every Zap you would realistically run without needing to prune old ones.

Run your WhatsApp on VGraple CRM

Free forever plan, official Meta WhatsApp Business API, set up in 15 minutes. No card needed.