Motyw
75. Webhook Automation - integracje API
Poziom: Zaawansowany | Czas: 10 min
Webhooks pozwalają GHL komunikować się z external applications w real-time. To klucz do zaawansowanych integracji z narzędziami, których GHL nie obsługuje natywnie.
Czym jest Webhook?
WEBHOOK = "Wywołanie API" triggered przez event w GHL
Event w GHL (np. new contact)
↓
GHL wysyła HTTP POST request
↓
Do external URL (np. Zapier, Make, własny serwer)
↓
External system odbiera dane i wykonuje akcjęExample:
Contact submits form in GHL
→ GHL wysyła dane via webhook
→ Twój CRM dostaje notification
→ Automatycznie tworzy leadTypy Webhooks w GHL
1. Outbound Webhooks (GHL → External)
GHL wysyła dane OUT do innych systemów:
TRIGGER: Contact created
↓
ACTION: Webhook POST to:
URL: https://your api.com/new-contact
BODY:
{
"firstName": "{{contact.firstName}}",
"lastName": "{{contact.lastName}}",
"email": "{{contact.email}}",
"phone": "{{contact.phone}}",
"source": "{{contact.source}}",
"timestamp": "{{currentTimestamp}}"
}
Your system receives data → processes it2. Inbound Webhooks (External → GHL)
Other systems send data INTO GHL:
External system (e.g., payment processor):
Sends POST to your GHL webhook URL
GHL receives:
{
"customerEmail": "customer@example.com",
"amount": "297",
"product": "Coaching Package"
}
GHL workflow triggered:
- Find contact by email
- Tag "purchased-{{productName}}"
- Add to customer workflow
- Send confirmation emailSetup Outbound Webhook
In Workflow:
Workflows → Create/Edit Workflow
[1] TRIGGER: (e.g., Form submitted)
↓
[2] ACTION: Webhook
Settings:
- Method: POST (most common) or GET
- URL: https://hooks.zapier.com/your-unique-url
(or Make.com, your API, etc.)
- Headers:
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY (if needed)
- Body (JSON):
{
"firstName": "{{contact.firstName}}",
"email": "{{contact.email}}",
"formName": "{{trigger.formName}}",
"customField": "{{custom.YourField}}"
}
- Test: Click "Test Webhook" → Verify data arrivesCommon Use Cases
1. Send to Zapier/Make
GHL → Zapier → (1000+ apps)
EXAMPLE:
New contact in GHL
→ Webhook to Zapier
→ Zapier adds row to Google Sheet
→ Sends Slack notification
→ Creates task in Asana
Setup:
1. Zapier → Webhooks by Zapier → Catch Hook
2. Copy Zapier webhook URL
3. GHL workflow → Webhook action → Paste URL
4. Test → Zapier receives data
5. Continue Zap with other apps2. Send to External CRM (Salesforce, HubSpot)
GHL contact created
→ Webhook to Salesforce API
→ Create lead in Salesforce
Webhook body:
{
"FirstName": "{{contact.firstName}}",
"LastName": "{{contact.lastName}}",
"Email": "{{contact.email}}",
"Phone": "{{contact.phone}}",
"LeadSource": "GHL Form - {{trigger.formName}}"
}
URL: https://salesforce.com/services/data/v52.0/sobjects/Lead
Headers:
Authorization: Bearer {{salesforceToken}}
Content-Type: application/json3. Send to Custom Database
GHL workflow → Your server
Your API endpoint:
POST https://yourapp.com/api/ghl-webhook
Receives:
{
"contactId": "{{contact.id}}",
"firstName": "{{contact.firstName}}",
"email": "{{contact.email}}",
"tags": ["hot-lead", "webinar-attended"]
}
Your server code (Node.js example):
app.post('/api/ghl-webhook', (req, res) => {
const { contactId, firstName, email, tags } = req.body;
// Save to your database
db.contacts.create({
ghl_id: contactId,
name: firstName,
email: email,
tags: tags
});
res.status(200).send('OK');
});4. Trigger SMS via Twilio (Custom)
GHL workflow → Your middleware → Twilio
Why? Custom SMS logic not possible in GHL alone
Webhook to: https://yourapp.com/send-custom-sms
Body:
{
"to": "{{contact.phone}}",
"firstName": "{{contact.firstName}}",
"appointmentTime": "{{appointment.startTime}}"
}
Your server:
- Receives webhook
- Calculates optimal send time based on timezone
- Formats custom message using template
- Calls Twilio API to send SMS
- Returns result to GHL5. Update External Calendar (Google, Outlook)
GHL appointment booked
→ Webhook to Google Calendar API
→ Create calendar event
Useful if you need appointments in multiple calendarsInbound Webhooks (Receiving Data)
Get GHL Webhook URL:
Settings → Integrations → Webhooks
Custom Webhook URL:
https://services.leadconnectorhq.com/hooks/abc123xyz
Use this URL in external systems to send data TO GHLExample: Payment Processor → GHL
Stripe payment successful
→ Stripe webhook fires
→ Sends to GHL webhook URL
GHL workflow:
TRIGGER: Incoming webhook (custom)
FILTER: webhookBody.amount > 100
ACTION:
- Find contact by webhookBody.email
- Tag "paid-customer"
- Add to "Customer Onboarding" workflow
- Send thank you emailWebhook Body Parsing:
Incoming webhook data stored in:
{{webhook.body}}
Access specific fields:
{{webhook.body.email}}
{{webhook.body.amount}}
{{webhook.body.productName}}
Use in conditions, tags, custom fields, etc.Error Handling
Webhook Fails - What Happens?
IF webhook fails (URL down, timeout, 500 error):
- GHL retries 3 times (with delays)
- After 3 failures → marks as failed
- Contact continues through workflow (doesn't stop)
BEST PRACTICE:
Monitor webhook failures:
Settings → Webhooks → View Logs → Filter "failed"
Set up alert:
Daily check of failed webhooks → Manual review/retryReturn Response:
Your webhook endpoint should return:
SUCCESS:
HTTP 200 OK
Body: {"status": "success"}
ERROR:
HTTP 400/500
Body: {"status": "error", "message": "Invalid email"}
GHL logs response for debuggingAuthentication & Security
API Keys:
Headers:
Authorization: Bearer YOUR_SECRET_API_KEY
X-API-Key: YOUR_KEY
Prevents unauthorized access to your endpointVerify GHL Webhooks:
GHL signs webhooks with signature header
In your server code:
const signature = req.headers['x-ghl-signature'];
const payload = JSON.stringify(req.body);
const secret = 'YOUR_WEBHOOK_SECRET';
const hash = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
if (hash === signature) {
// Legitimate GHL webhook
} else {
// Reject (potential fraud)
}Advanced: Conditional Webhooks
Workflow:
IF: {{contact.leadScore}} > 70
→ Webhook to "Hot Lead" endpoint
→ URL: https://api.com/hot-leads
ELSE IF: {{contact.leadScore}} 40-70
→ Webhook to "Warm Lead" endpoint
→ URL: https://api.com/warm-leads
ELSE:
→ No webhook (cold lead)
Different data to different systems based on logicCommon Integrations via Webhooks
✅ Zapier / Make / Integromat (no-code automation)
✅ Slack (team notifications)
✅ Google Sheets (data logging)
✅ Airtable (database)
✅ Salesforce / HubSpot (CRM sync)
✅ Stripe / PayPal (payment processing)
✅ Twilio (custom SMS logic)
✅ SendGrid / Mailgun (email via API)
✅ Custom applications (your own software)
✅ Internal dashboards (real-time data)Testing Webhooks
Use Webhook.site:
1. Go to: webhook.site
2. Copy unique URL (e.g., https://webhook.site/abc-123)
3. GHL workflow → Webhook → Paste URL
4. Trigger workflow (test contact)
5. webhook.site shows exact data received
6. Verify format, fields, values
Perfect for debugging!GHL Test Button:
Workflow → Webhook action → "Test"
Sends test payload immediately
Check your endpoint logs to verify receiptWebhook Logs & Debugging
GHL → Settings → Webhooks → Logs
Shows:
- Timestamp
- URL called
- Request body sent
- Response received
- Status (success/failed)
- Retry attempts
Use for:
- Debugging failed webhooks
- Verifying data sent correctly
- Monitoring webhook healthLimits & Considerations
RATE LIMITS:
- GHL doesn't officially publish limits
- General good practice: <100 webhooks/second
- If high volume, batch data or use queue
TIMEOUTS:
- Webhook timeout: 30 seconds
- If your endpoint takes >30s → failure
- Solution: Respond quickly, process async
DATA SIZE:
- Keep payload <1 MB
- For large data, send ID and fetch details separatelyReal-World Example: Full Integration
USE CASE: Sync GHL contacts with external membership site
[GHL → Your Server → Membership Platform]
GHL Workflow:
TRIGGER: Tag "paid-member" added
ACTION: Webhook POST
URL: https://yourapp.com/api/create-member
Body:
{
"email": "{{contact.email}}",
"firstName": "{{contact.firstName}}",
"membershipLevel": "{{custom.membershipTier}}",
"ghlContactId": "{{contact.id}}"
}
Your Server (e.g., Node.js):
app.post('/api/create-member', async (req, res) => {
const { email, firstName, membershipLevel, ghlContactId } = req.body;
try {
// Create user in membership platform
const newUser = await MembershipPlatform.createUser({
email: email,
name: firstName,
accessLevel: membershipLevel
});
// Send credentials email via membership platform
await MembershipPlatform.sendWelcomeEmail(newUser.id);
// Update GHL with membership ID (via GHL API)
await GHL.updateContact(ghlContactId, {
customField: { membershipId: newUser.id }
});
res.status(200).json({ success: true, memberId: newUser.id });
} catch (error) {
console.error(error);
res.status(500).json({ success: false, error: error.message });
}
});
Result:
- Customer tagged in GHL → Instant membership access
- GHL stores membership ID → Full sync
- Customer gets welcome email with login detailsChecklist
☑ Webhook endpoint URL ready (Zapier, your server, etc.)
☑ Authentication configured (API keys if needed)
☑ Request body formatted (JSON with dynamic fields)
☑ Headers set (Content-Type, Authorization)
☑ Test webhook (use webhook.site or test button)
☑ Verify data arrives correctly
☑ Handle errors gracefully (try/catch in your code)
☑ Monitor webhook logs regularly
☑ Set up alerts for failures
☑ Document integration for teamGratulacje! Ukończyłeś sekcję Automatyzacje (56-75) - 19 zaawansowanych artykułów!
Następna sekcja: 77. Funnel Builder
