Skip to content

Instantly share code, notes, and snippets.

@hmseeb
Last active March 13, 2026 16:40
Show Gist options
  • Select an option

  • Save hmseeb/2063a27ff2672d9c36ca4e695c359ddb to your computer and use it in GitHub Desktop.

Select an option

Save hmseeb/2063a27ff2672d9c36ca4e695c359ddb to your computer and use it in GitHub Desktop.

GHL Webhook Integration — PPL Onboarding

Endpoint

POST https://ppl-onboarding.vercel.app/api/webhooks/ghl
Content-Type: application/json

Request Payload

{
  "ghl_contact_id": "abc123xyz",        // REQUIRED — unique GHL contact ID
  "first_name": "John",                  // REQUIRED
  "last_name": "Smith",                  // REQUIRED
  "email": "john@example.com",           // REQUIRED — valid email
  "phone": "+17025551234",               // optional
  "company_name": "Smith Funding LLC",   // optional — used for onboarding URL slug
  "state": "NV",                         // optional
  "primary_vertical": "MCA",             // optional — collected during onboarding if missing
  "secondary_vertical": "Equipment",     // optional
  "batch_size": 25,                      // REQUIRED — positive integer, max 10,000 (can be string, auto-coerced)
  "deal_amount": 1500                    // REQUIRED — positive number, max 10,000,000 (can be string, auto-coerced)
}

Field Notes

Field Type Required Notes
ghl_contact_id string Yes Must be unique per broker. Used for idempotency — duplicate webhooks with same ID won't create duplicate brokers.
first_name string Yes Auto title-cased (e.g. "john" → "John")
last_name string Yes Auto title-cased
email string Yes Must be valid email format. Auto lowercased.
phone string No Any format accepted
company_name string No Used to generate the onboarding URL slug. Falls back to broker name if missing.
state string No US state code or full name
primary_vertical string No Pre-populated if sent, always editable by broker during onboarding (Step 2). Options: MCA, Equipment, SBA, Real Estate, Business Line of Credit, Invoice Factoring.
secondary_vertical string No Same options as primary. Always shown during onboarding, pre-populated if sent.
batch_size number Yes Number of referrals in the batch. Positive integer, max 10,000. Can be sent as string — auto-coerced.
deal_amount number Yes Total deal amount in USD. Positive number, max 10,000,000. Can be sent as string — auto-coerced.

Note: timezone is not part of the webhook payload. It is auto-detected from the broker's device during onboarding (Step 2) and can be changed manually. Mapped to the nearest US timezone (Eastern, Central, Mountain, Pacific, Alaska, Hawaii).

Response

Success (new broker created)

// 201 Created
{
  "onboarding_url": "https://ppl-onboarding.vercel.app/onboard/smith-funding-llc",
  "broker_name": "John",
  "status": "created"
}

Duplicate (broker already exists for this ghl_contact_id)

// 200 OK
{
  "onboarding_url": "https://ppl-onboarding.vercel.app/onboard/smith-funding-llc",
  "broker_name": "John",
  "status": "exists"
}

Validation Error

// 400 Bad Request
{
  "error": "Validation failed",
  "details": { ... }
}

Behavior

  1. Webhook receives the payload and validates all fields via Zod schema
  2. Checks if a broker with that ghl_contact_id already exists
    • If yes → returns existing onboarding URL (idempotent, safe to retry)
    • If no → generates a human-readable slug token (from company name or broker name), creates the broker record, returns new onboarding URL
  3. The onboarding_url is what gets sent to the broker (via SMS/email in GHL workflow)
  4. Broker opens the link → 7-step onboarding flow → marked as completed when they accept the policy at step 6

Example cURL

curl -X POST https://ppl-onboarding.vercel.app/api/webhooks/ghl \
  -H "Content-Type: application/json" \
  -d '{
    "ghl_contact_id": "ghl_test_001",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "+15551234567",
    "company_name": "Doe Funding",
    "primary_vertical": "MCA",
    "batch_size": 20,
    "deal_amount": 1300
  }'

ROI Math (for reference)

The onboarding flow shows the broker their ROI breakdown:

  • Price per referral = deal_amount / batch_size
  • Example: $1500 deal / 25 referrals = $60 per referral
  • This is calculated dynamically, never hardcoded
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment