Most of the “how do I connect X to GoHighLevel” questions I get have the same answer: a webhook, and no middle tool. GoHighLevel can receive a webhook from anything that can send one, and it can send a webhook to anything with a URL — which is nearly everything. The GoHighLevel webhook features are not hidden, but they are underused, because the two directions are set up in different places and the field mapping trips people up once. This is the full picture with worked examples.
If webhooks in general are new, the explainer is five minutes well spent; and if you are wondering whether you need Zapier or Make at all, that comparison ends with “often not” for exactly this reason.
The two directions
| Direction | GoHighLevel feature | Use it for |
|---|---|---|
| Into GoHighLevel | Workflow trigger: Inbound Webhook | Website forms, quoting tools, booking apps, other CRMs, anything that can POST JSON |
| Out of GoHighLevel | Workflow actions: Webhook (basic) and Custom Webhook (full control) | Slack, Google Sheets scripts, invoicing, job management software, your own database, other CRMs |
| Out, no webhook needed | Native actions: Google Sheets, Slack, email, SMS, internal notifications | Common destinations — check for a native action first |
| Direct API | Private Integration token + API v2 | Developers building a two-way integration from their own code |
Inbound: turning any form or app into a lead
- Create a workflow and choose the Inbound Webhook trigger. It shows a unique URL. Copy it.
- Send a sample payload. From the source system, submit a test (a form entry, a test order); or send one yourself from any HTTP tool. The trigger shows the received JSON.
- Map the fields. Point
first_name,email,phone, and any custom fields at the matching contact fields. Include asourceor tag value so the contact carries where it came from. Email or phone is required for the contact to be created or matched. - Add the rest of the workflow — tag, pipeline stage, notify, text the lead — exactly as for any other trigger.
- Send a second test and open the contact to confirm every field landed.
The WordPress form guide is this pattern with a form plugin as the sender; the same trigger accepts anything.
A sample inbound payload
{
"first_name": "Sarah",
"last_name": "Khan",
"email": "sarah@example.com",
"phone": "+447700900123",
"service": "Boiler service",
"postcode": "M6 5AB",
"urgency": "This week",
"source": "website-quote-form"
}
Flat keys, one level deep, are easiest to map. If the source sends nested data, map what you can and consider a small transformation step in the source.
Outbound: pushing contacts and events anywhere
Webhook (basic) posts the whole contact record and trigger data to your URL. No options. Fine for a receiving script you control that can pick out what it needs.
Custom Webhook (premium) is the real tool: choose GET, POST, PUT or DELETE; add headers (an API key, a bearer token, a content type); write the JSON body yourself using merge fields such as {{contact.first_name}}, {{contact.email}} and custom fields; and send it to any API that accepts a request. This is how a new lead becomes a Slack message, a job in your scheduling software, a row in an external database or a record in another CRM — without an intermediary.
A sample Custom Webhook body
{
"name": "{{contact.first_name}} {{contact.last_name}}",
"email": "{{contact.email}}",
"phone": "{{contact.phone}}",
"service": "{{contact.service}}",
"stage": "New lead",
"ghl_id": "{{contact.id}}"
}
Five examples that come up constantly
- Website quote form → GoHighLevel. Inbound webhook with mapping; tag
source-website; instant SMS to the lead; task for the owner. No plugin needed beyond the form’s webhook feature. - New hot lead → Slack channel. Trigger: tag added
hot. Custom Webhook POST to a Slack incoming-webhook URL with a text body built from merge fields. (There is also a native Slack action; use whichever fits.) - Every new lead → Google Sheet. Use the native Google Sheets action to add a row. Reach for a Custom Webhook to a Google Apps Script only when you need logic Sheets cannot do on its own.
- Appointment booked → job management or invoicing app. Trigger: appointment status booked. Custom Webhook POST to the app’s API with the customer, service and time. Most trade and clinic software has an API that accepts this.
- External system → update an existing contact. Inbound webhook with the email or phone as the match key and the changed fields mapped; the workflow updates rather than duplicates. Add a condition so it does not re-run welcome messages for existing contacts.
Testing without guessing
- Capture first. Point an outbound webhook at a request-capture tool (webhook.site or similar) to see exactly what GoHighLevel sends before pointing it at the real system.
- Sample payloads on the inbound side: send the real thing from the real source, not a hand-written guess.
- Workflow execution logs show each step’s status and, for Custom Webhooks, the response code. A 4xx is your request; a 5xx is their server.
- Test contacts tagged
test, and a filter at the top of live workflows that skips them.
Security and reliability
An inbound webhook URL is a door; anyone with the URL can create contacts. Keep it out of public code, and if the sender supports a secret, include one in a field or header and filter on it in the workflow. Send only over HTTPS. Outbound: put API keys in headers, not the URL. Reliability: GoHighLevel does not retry failed outbound requests indefinitely, so the receiving endpoint should respond quickly with a 200 and do its work afterwards; and set an alert (a notification step on failure, or a monitoring workflow) for integrations that matter.
When you still need Zapier or Make
- The other system has no API or webhook, only a Zapier or Make app.
- You need to transform data in ways merge fields cannot — look-ups, calculations, splitting arrays.
- Multi-step logic across several external systems with branching.
- You need the response from an external call to drive the next step in complex ways.
For everything else — which is most small-business integrations — the two GoHighLevel webhook features and the native actions inside workflows are enough, cheaper, and one fewer thing to break.
Further reading: GoHighLevel Help Center · webhook.site (request capture).
FAQ
What is the difference between the Webhook and Custom Webhook actions in GoHighLevel?
The basic Webhook action posts the whole contact and trigger data to a URL with no options. Custom Webhook lets you choose the method, add headers such as an API key, and write the JSON body yourself with merge fields — which is what most real integrations need.
How does the GoHighLevel inbound webhook work?
A workflow with the Inbound Webhook trigger gets a unique URL. Any system that can send an HTTP POST with JSON sends the lead there; you paste a sample payload, map its fields to contact fields, and the workflow creates or updates the contact and runs the rest of its steps.
Can I send GoHighLevel data to Google Sheets?
Yes, without a webhook — the native Google Sheets action adds or updates rows from a workflow. Use a Custom Webhook only if you need to hit a script or an app that Sheets alone cannot handle.
Do GoHighLevel webhooks cost extra?
The inbound webhook trigger and the Custom Webhook action are premium workflow steps billed per execution in tiny amounts, with a free monthly allowance. For a small business the cost is negligible; check the agency’s rebilling settings if you are on an agency account.
Have a system that needs to talk to GoHighLevel and no appetite for the mapping? See the integration services — most connections are a half-day job, tested end to end, with monitoring so you hear about failures before customers do.