How-to

Wire your CRM workflow to an agent (webhook URL and secret)

Last updated: September 8, 2026

Every AI agent in GodSetter has its own webhook URL. The workflow you point at that URL decides which agent makes the call — so one client can run different agents for different campaigns just by using different URLs.

This guide wires a CRM workflow (e.g. "new lead created") to an agent so that every lead the workflow processes gets called within seconds — the first call is placed the moment the lead arrives.

Before you start

  • Your CRM is connected in Connections (OAuth) and the client sub-account has been imported (it appears in Clients as active). It needs somewhere to book: a calendar of its own, or a default calendar on the agent (Identity & routing), matched by name in the client's sub-account.
  • The agent exists and has at least one active phone number assigned (agent editor → Numbers tab). This is fail-closed: an agent with no numbers never dials.
  • The agent's direction is Outbound. An inbound agent answers call-backs and is never allowed to start a call cycle, so it cannot be the target of a trigger — see Create inbound and outbound agents.

Step 1 — Copy the agent's webhook URL and secret

Open the agent in Agents, then the Data & GHL tab. You'll find:

  • the agent's webhook URL (…/api/webhooks/ghl-trigger/agent/<agent-id>),
  • the agent's webhook secret,
  • a sample request body,

each with a copy button. The secret is unique per agent — treat it like a password.

Step 2 — Add the webhook action to your workflow

In the client's sub-account, edit the workflow that should trigger calls (for example, on "Contact created" or a pipeline stage change) and add a Webhook action:

  • Method: POST
  • URL: the agent URL you copied
  • Header: Content-Type: application/json

Step 3 — Build the JSON body

Minimum required fields:

{
  "webhookSecret": "<the copied per-agent secret>",
  "locationId": "{{location.id}}",
  "contactId": "{{contact.id}}",
  "phone": "{{contact.phone}}"
}

Recommended additions:

FieldWhy
firstName, lastName, emailThe agent greets the lead by name.
customValuesKey/value map, available in the prompt as {{cv_*}} variables.
consentProofConsent evidence (source, timestamp, text). Required for every call when strict mode is on.
timezoneThe contact's own IANA time zone (e.g. America/New_York). Used by agents whose calling window runs in Contact time zone mode.

The timezone field is optional and safe to send always: an absent or unrecognised value is ignored, and the calling window falls back to the client sub-account's zone and then to the agent's fallback zone. It is stored on the lead, so later retries and callbacks reuse it. Details in Set a calling window per agent.

Step 4 — Send a test lead

The quickest check is in the app. In the same Data & GHL tab, right under the webhook card, the Send a test lead card simulates a lead arriving from the workflow: pick the client (only active clients with somewhere to book — their own calendar or the agent's default — are listed), enter a phone you control and click Send test lead. The lead goes through the very same ingress the webhooks use — direction, client, number, consent and Do-Not-Call gates — and then through the instant dispatch, so if everything is wired the agent calls you within seconds. It is a real call (real cost) on a real lead, kept in Calls and Leads like any other. The calendar is the client's real one; booking, tags and notes are simulated — nothing is left in the CRM. The card shows a three-line trace (and because the lead is real, an unanswered test is redialed by the agent's retry plan — expect more real calls to your number unless you block the lead from the Leads page):

  • Ingress — lead accepted, or skipped with the reason (same reasons as the table below);
  • Dispatch — call started, queued at the head (all slots busy), parked at the window opening (outside the calling window), or not started with the reason;
  • Open the lead — the lead the test created.

Then run the real check from the CRM: trigger the workflow with a test contact (use a phone you control). Expected response:

{ "status": "enqueued", "leadId": "…" }

Inside your calling window the call starts within seconds; outside it, the lead waits for the opening. Check Calls for the live entry.

If the response says skipped

The reason field tells you which activation gate stopped the call:

ReasonMeaningFix
client_inactive_or_not_foundThe sub-account isn't imported or is inactive.Sync sub-accounts, open the client, activate it.
not_configuredThe client has no calendar of its own and the agent has no default calendar.Set a default calendar on the agent (Identity & routing) or pick one in the client detail page.
no_numberThe agent has no active numbers assigned.Assign one in the agent's Numbers tab.
no_consentStrict mode is on and consent proof is missing/invalid.Include a valid consentProof, or review strict mode.
blockedThe lead asked not to be contacted (Do-Not-Call).Only unblock deliberately, from the Leads page.
inbound_agentThe URL points at an inbound agent, which never starts calls.Point the workflow at the outbound agent, or switch the direction in the agent's Identity & routing tab.

A duplicate trigger — the same contact fired twice within 10 minutes — gets its own response, {"status":"duplicate"}, and is simply ignored: that's the built-in dedup working as intended.

Three of these skips are also tagged in your CRM — no_number, no_consent and blocked (names configurable in Settings → CRM tags) — so your workflows can react to them. The other three (client_inactive_or_not_found, not_configured and inbound_agent) are setup mistakes on your side: they are reported in the response and on the lead, but nothing is written to the CRM.

Step 5 — Stop the cycle when the contact books on their own

A booking made during a call already stops the cycle automatically. But a contact can also book outside any call — via a funnel link, or with a human agent. Tell GodSetter about it so scheduled retries never dial someone who has already booked:

  1. In the client's sub-account, create a second workflow on the CRM's native "Customer booked appointment" trigger.
  2. Add a Webhook action pointing at the "Appointment booked (stop calls)" URL shown on the Connections page (the page also shows the agency webhook secret and a ready-made sample body to paste).
  3. Body fields: webhookSecret (the agency secret from Connections), locationId, contactId and optionally phone.

On success the response is {"status":"stopped"}: the lead is marked booked and every scheduled redial/callback for them is removed. A not_found response is benign — that contact simply was never in a call cycle.

The other URLs on the Connections page

The Inbound webhooks card on Connections lists five URLs, and only two of them are yours to paste into GoHighLevel:

  • Call trigger — the agency-level trigger (the legacy URL; the per-agent URL from Step 1 is the recommended one).
  • Appointment booked (stop calls) — Step 5 above.

The other three — Inbound voice, Call lifecycle and In-call tools — are Retell webhooks, and GodSetter configures them for you: the call-lifecycle and in-call-tool URLs are set on the agent when it is created (and re-asserted by "Sync GHL tools"), and the inbound-voice URL is set on the phone number when it is registered on Retell. Nothing to paste anywhere — they are shown for reference, e.g. to check which host your agents and numbers point at. The Webhook secret applies only to the two GoHighLevel ones.

Prefer the branded workflow actions

If the GodSetter marketplace app is installed on the sub-account, both steps are available as native workflow actions — no URL or JSON to paste. They require that app installed on the sub-account and the "Workflow LC Premium Triggers & Actions" billing enabled on it; without both, the branded nodes do not appear in the workflow builder and the generic webhook stays the way to go.

  • Start call cycle — pick the action, paste the Agent ID (copy it from the agent's Data & GHL tab). The contact's phone, name and custom fields are fetched automatically — every {{cv_contact_*}} token in the prompt resolves with no mapping work.
  • Appointment booked (stop calls) — pick the action, paste your Account ID (copy it from the Connections page).

The generic webhook remains fully supported; the actions are the same thing with less setup. One note: the start-calls action carries no consentProof — with strict mode on, use the webhook for consent-requiring clients. (Contact custom fields and any values persisted by earlier webhook triggers are applied automatically.)

Good to know

  • One URL per agent. To route a campaign to a different agent, duplicate the workflow and swap the URL + secret — no changes in GodSetter needed.
  • A new trigger restarts the cycle. Firing the workflow again for a contact GodSetter already knows resets the attempt counter and drops the retries still parked for that lead, so the plan starts from call #1 instead of resuming mid-way. A callback the lead explicitly asked for is kept.
  • The agency-level legacy webhook (without /agent/) still works and uses the client's default agent, but the per-agent URL is the recommended setup — and it answers {"status":"skipped","reason":"no_template"} when the client has no default agent. That default is the Agent Template field on the client's detail page (Manage your clients).
  • If the workflow fires while the calling window is closed, the lead waits in the queue and is dialed when the window reopens.