Skip to content
Get a free quoteGet a quote
Published
Byline
GoHighLevel Partners Editorial

The three parts of a delivery, the three payload shapes you will meet, and the five failures that turn one event into three contacts.

What is a webhook payload, and what is actually inside one

A webhook is the delivery. The payload is what was delivered. Most confusion about integrations dissolves once those two are held apart: the webhook is the arrangement — one system agrees to make an HTTP request to a URL you own whenever something happens — and the payload is the body of that request, the block of data describing what happened.

Agencies meet payloads at the seam where a CRM has to talk to something it does not integrate with natively: a booking tool, a client’s back-office system, a spreadsheet, a small script on a server. Reading the payload correctly is most of that work. The rest is plumbing.

A delivery has three parts, and only one of them is the payload

When a sender fires a webhook, three separate things arrive together, and it is normal to spend an hour looking for a value in the wrong one.

Part What it carries What it is for
The URL The endpoint you registered, sometimes with query parameters Routing. One URL per event type keeps each handler simple
The headers Content type, a signature, a delivery identifier, often a retry counter Verifying the sender and spotting a repeat delivery
The body The event data itself, almost always JSON — this is the payload Everything you map into an automation

The practical consequence is that a receiver which reads only the body cannot verify anything, because the signature is a header. It also cannot tell a first attempt from a fourth, because the retry count is a header too.

Three payload shapes you will meet

Shape What arrives What it costs you
Full object The whole record inline — the contact, the order, the appointment Convenient and large; it changes shape whenever the sender adds a field
Thin, identifier only An event name and a record id Forces a follow-up API read, but what you read back is always current
Event envelope A wrapper of event metadata with the record nested inside a data object Cleanest to route on; you have to read one level down for every field

None of these is better in the abstract. A thin payload plus a read-back is the right choice when the record changes often between the event and the moment you process it; a full object is right when the receiver has no credentials to read anything back.

What is normally inside the body

  • An event name — what happened, and the thing you branch on.
  • A timestamp — when it happened at the sender, which is not when it arrived.
  • Identifiers — for the record, and usually for the account or sub-account it belongs to.
  • The record’s own fields — name, email, amount, status.
  • Custom fields — normally keyed by an internal id rather than by the label a human typed.
  • Sometimes a previous-values block on update events, which is the only way to know what actually changed.

That custom-field line costs agencies more time than any other. Labels get renamed by clients; ids do not. A mapping written against the label breaks silently the first time somebody tidies up a field name, and the symptom is an automation that runs with an empty value rather than one that errors. Where a record points at another record, the same warning applies to the relationship itself — see associated records and the snapshot trap for what happens to those ids when a build is copied to another account.

Inspect a real one before you build anything

Do not write a mapping from documentation alone. Point the webhook at a request-capture endpoint, fire one genuine event, and read what actually arrives. Then do it again for every event type you intend to handle, because the payload for a created record and an updated one are rarely the same shape, and a deletion is usually thinner than both.

Capture at least one example of each event you care about and keep the raw JSON somewhere the next person can find it. That file is the specification the integration is really built against. If you are wiring the connection through a no-code layer rather than your own endpoint, building a Zapier integration for an agency CRM covers the same inspection step in that environment.

Mapping payload fields into an automation

Once the shape is known, mapping is mechanical. Two details are worth stating. Nested values are addressed a level at a time, so a field inside a data object is not missing when the top level does not show it — it is one step down. And arrays have no stable position: the second item in a list of line items today may be the first tomorrow, so match on an identifier rather than on an index.

What you do with the mapped values is ordinary automation work. A payload that signals a new lead can start the same response path as any other lead source — the timing of which is the whole argument in the lead response playbook — while a payload carrying an email address can feed the sequences described in CRM marketing email automation. Inbound events from the phone system work the same way; missed call text back is that pattern with a very short fuse.

Where webhook integrations actually break

The shape changed underneath you

Senders add fields, rename nesting levels and version their events. Additive changes are safe; a moved field is not. Log the raw body of every delivery for a retention window you choose deliberately, because without it a mapping failure is unreproducible.

The same event arrived twice

Retries are normal. A sender that does not get a fast success response will try again, so a receiver must be idempotent: record the delivery id from the headers and ignore one you have already processed. Without that, a single lead becomes three contacts and three notifications.

The receiver was slow

Most senders expect a response within a few seconds and treat anything longer as a failure. Acknowledge first, process afterwards. A handler that does its work before replying converts every slow database write into a duplicate delivery.

Nobody verified the sender

A webhook URL is a public endpoint that anyone can post to. Verify the signature header against the shared secret before you trust a single field, and treat an unsigned sender as a reason to add your own shared token to the URL. This is also one of the review criteria that surfaces when an integration is packaged for distribution rather than kept private — see marketplace app approval.

The event you subscribed to is not the event you meant

Event names are close together and easy to confuse, and a subscription to the wrong one produces an integration that works perfectly and never fires. Confirm which native trigger already covers your case before you build anything: a new opportunity, a stalled one and a bulk change are three different events, covered respectively by the prospect generated trigger, the stale opportunity trigger and bulk workflow triggers. A file arriving in a client portal is another one entirely — see the file uploaded trigger.

A short pre-handover checklist

  1. Capture and store one raw payload per event type you handle.
  2. Map custom fields by id, never by label.
  3. Verify the signature, or add a secret to the URL where none exists.
  4. Deduplicate on the delivery id from the headers.
  5. Return a success response before doing the slow work.
  6. Log failures somewhere a human will actually look.
  7. Write down which sender event drives which automation, and hand that over.

Two habits carry most of this. Attribution data such as UTM parameters only survives if the field is present in the payload at the moment the event fires, so check that before promising a client source reporting; and the number of fields you collect at the front door determines how much the payload can carry at all, which is the trade-off in splitting a contact form across steps. A webhook payload is not complicated. It is only unforgiving about being read before it is relied upon.

Frequently Asked Questions

What is the difference between a webhook and a webhook payload?

The webhook is the arrangement and the delivery: one system makes an HTTP request to a URL you registered whenever a chosen event happens. The payload is the body of that request, the actual data describing the event. Saying “the webhook contains the email address” is loose shorthand for “the payload does”, and the distinction matters as soon as you need something that lives in the headers instead.

What format is a webhook payload in?

JSON in the overwhelming majority of cases, declared by a content-type header of application/json. Some older senders post form-encoded data instead, which looks like a query string rather than an object and has no nesting. Read the content-type header rather than assuming, because a parser pointed at the wrong format fails in a way that looks like an empty payload.

Why is a field missing from my webhook payload?

Three causes account for most of it. The value is nested one level down inside a data or object wrapper and the top level genuinely does not show it. The field is a custom field keyed by internal id, so it is present but not under the name you expected. Or the event type you subscribed to does not carry that field at all, which is common on delete and on thin identifier-only payloads.

Do I have to verify a webhook signature?

Treat it as required. A webhook endpoint is a public URL that anyone who learns it can post to, so without verification you are letting an unauthenticated caller create records and start automations. Compare the signature header against the shared secret before reading any field. Where a sender offers no signature, add a long random token to the URL and reject requests that arrive without it.

Why did one event create two contacts?

Almost always a retry. Senders resend a delivery when they do not receive a fast success response, and a handler that does its work before replying invites exactly that. Record the delivery identifier from the headers, skip anything you have already processed, and acknowledge the request before starting slow work. That combination makes duplicates harmless rather than merely rare.

Should I use the data in the payload, or read the record back from the API?

Use the payload when the receiver has no credentials, when the record rarely changes, or when you need the values as they were at the moment of the event. Read back from the API when the record changes frequently, when the payload is thin by design, or when you need fields the event does not carry. Many integrations do both: branch on the payload, then read back before writing anything.

We build your GoHighLevel account for you

CRM, pipelines, funnels, SMS and automation — configured for your business, not left for you to figure out.

  • Setup (one-time)$850
  • Ongoing (per month)$38.80
Get my free setup quote

No obligation quote · reply within 1 business day

This site is independently operated and is not officially affiliated with, endorsed by, or sponsored by HighLevel LLC. We do not receive referral commissions — this is our own flat-fee implementation service.

$850 setup, $38.80/mo ongoingGet a quote