GHL Webhook Handler

Test the generic GHL resource webhook. There is no fixed payload shape - fields are mapped to GHL per the (resource, action[, relationKey]) mapping configured in the configurator.

Resource

contact, opportunity, company, or a custom object key.

Action

API Config

Request

Endpoint:
POST /api/v1/test-location-123/webhook/ghl/contact/create
Headers:
{
  "Content-Type": "application/json",
  "m4-connect-key": "[your-api-key]"
}
Body (Editable):

API Reference

URL contract:

POST /api/v1/[locationId]/webhook/ghl/[resource]/[action] where resource is contact, opportunity, company, or a custom object key, and action is create, update, link-{relationKey}, or createAndLink-{relationKey}. There's no resource allow-list at the route level - a request against a resource/action with no active mapping configured simply returns a 400 VALIDATION_ERROR.

create:

Maps the payload via the configured field mapping and creates the record - behaving as a smart upsert. A contact whose mapping resolves an email or phone dedups via GHL's native upsert endpoint. Any other case (a contact without email/phone, or any non-contact resource) searches for an existing record using the mapping's configured uniqueIdentifier fields and updates a match instead of duplicating; with no match, creates a new record. For opportunity/ company/custom-object resources, configuring uniqueIdentifier is required to avoid duplicating records on retried webhook calls.

update:

Maps the payload and updates the record identified by the mapping's recordIdSourceField - a payload path resolving the GHL record id, typically a GHL workflow merge field like {{contact.id}} / {{opportunity.id}} that the calling workflow puts into the payload.

link-{relationKey}:

Links two existing records via the GHL association configured under {relationKey}. The payload must resolve both the mapping's firstRecordSourceField and secondRecordSourceField to existing record ids. Calling this again for an already-linked pair is idempotent - a "duplicate relation" response from GHL is treated as success, not an error.

createAndLink-{relationKey}:

Creates a record (same behavior as create), then links it to an existing record via the association configured under {relationKey}. The payload only needs to resolve the source field for the side that is not the newly created record - which side that is (first or second) is set when the relationship mapping is configured.

Configuration:

Every mapping (field mappings, unique identifier, record id source field, and link/ createAndLink association config) is configured per location in the configurator app, under M4 Connect → GHL Webhook Handler → Manage Webhook Mappings. The mapping UI shows the exact URL a given resource/action/relationKey combination answers on.