Skip to content

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 lead

Typy 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 it

2. 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 email

Setup 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 arrives

Common 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 apps

2. 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/json

3. 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 GHL

5. Update External Calendar (Google, Outlook)

GHL appointment booked 
→ Webhook to Google Calendar API 
→ Create calendar event

Useful if you need appointments in multiple calendars

Inbound 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 GHL

Example: 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 email

Webhook 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/retry

Return 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 debugging

Authentication & Security

API Keys:

Headers:
Authorization: Bearer YOUR_SECRET_API_KEY
X-API-Key: YOUR_KEY

Prevents unauthorized access to your endpoint

Verify 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 logic

Common 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 receipt

Webhook 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 health

Limits & 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 separately

Real-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 details

Checklist

☑ 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 team

Gratulacje! Ukończyłeś sekcję Automatyzacje (56-75) - 19 zaawansowanych artykułów!

Następna sekcja: 77. Funnel Builder