Creating a Client from a Signed Contract
When a contract is signed, your CRM knows before you do. With a webhook it can tell SalesControl: the client shows up here on its own, with its service, its instalments already worked out, and the signature recorded in the Timeline.
Nobody has to retype anything, and above all no signature gets lost: even when something is missing, the client still comes in and someone is told to finish it.
Here your CRM calls SalesControl. If you need the other direction — SalesControl notifying an external system when someone signs a contract in here — see Outbound Webhooks: Notify an External System on Signing.
This page is for agencies that have contracts signed outside SalesControl (DocuSign, PandaDoc, their own CRM) and only want the client to land here on signature. If instead you want to write the contracts and have them signed inside SalesControl, that is a different path: see Contracts Overview. The two can coexist.
A paid plan is needed (Starter and above), as for the other inbound webhooks. See Subscription Plans.
How to connect it
In the Admin Panel, Integrations tab, look for the Signed contract → client card.
New webhook, give it a name (“Signed contracts”) and, if you like, pick a default setter and closer: they are used whenever the workflow sends no names.
It ends with /functions/v1/contract-signed-intake?t=…. Everything after t= is the token: whoever holds it can create clients in your agency, so treat it like a password. If it leaks, Regenerate token and the old address stops working at once.
In GoHighLevel: in the workflow that fires on a signed contract, add a Webhook action with method POST. In Zapier or Make: a “Webhooks → POST” step with a JSON body.
How to connect it inside the card opens the JSON body already written, with a copy button. Drop the fields you do not need: none is mandatory except the name.
The field that matters: the service
The service_name field must match the name of one of your services exactly — the one you read on the Services page. Capitals and extra spaces do not count, everything else does. There are no fuzzy matches, and that is deliberate: attaching the wrong service to a contract means wrong instalments, wrong commissions and wrong bonuses.
If it matches, the client is created Active with its instalments. If it is missing or does not match, the client is still created, in the To complete state, and the closer gets the notification “this client signed, choose the service”. You will find it in the Clients list with its own tag and a dedicated box at the top: it cannot slip past you.
The alternative would have been to create the client with a zero-euro, twelve-month contract. It would have looked like a real contract straight away, expiring in a year, sitting in the statistics and in renewals. A client that is to complete tells the truth: the signature is there, the contract is not yet.
If the contact is already a client
SalesControl recognises whoever arrives in three ways, in this order: your CRM’s contact id, then the email, then the exact name. The first is the only one that never changes, so it is worth always sending it.
- If the recognised client was waiting for its service and this time the service is there, it gets completed: Active state, instalments generated, welcome message in the chat.
- If it already has a live contract, SalesControl touches nothing: it records the signature in the Timeline and alerts the closer. A renewal stays something you do from the client page, because it archives the previous contract and rebuilds the instalments: doing that quietly from a workflow would leave the contract in a state nobody decided.
One handy consequence: if the workflow fires twice, no duplicates appear. On the second call the client already exists and is recognised.
What happens when the client comes in
- If the contact was a lead, it is marked converted: it leaves the list of people still to work.
- Whatever you send in
eventbecomes a Timeline entry (“Contract signed”). Leave it empty if you do not need it. - The language you send becomes the client’s language: from then on emails and messages reach them in it. It accepts the forms your CRM uses —
it,ITA,Italiano,en,Eng. - Once the client is complete, they receive by email the link to their support group, inviting them to open it on their phone and add it to the Home screen. That is the “Your support chat” email, and you switch it off from the toggle under Settings › Notifications › General. It needs the plan that includes the chat, that is Enterprise: below that plan it never goes out, not even when this webhook asks for it. It also never goes out for clients created from a signature on screen in SalesControl, who already have the link from the page after signing and from the contract email.
Setter and closer
You can send names in the setter and closer fields: they are looked up among the people who hold that role, even with just a first name or just a surname. If a name does not identify one single person, SalesControl does not guess: it uses the webhook default. Which is why setting one is worth it.
Two webhooks on the same workflow
If you also want a Timeline entry with a name other than “Contract signed”, you can chain this webhook and then the custom events one. The order matters: the first creates the client, the second finds someone to attach the event to. Reversed, the second event would sit in the “to match” queue waiting for you to assign it by hand.
If something does not work
- 404: wrong address, regenerated token, or disabled webhook.
- 403: the agency is on the Free plan.
- A reply with
"reason": "no_name": there is no name in the payload. Without a name nobody can be created. - A reply with
"blocked": "plan_limit": your plan has run out of client slots. The signature is not lost — it waits and you get notified — but letting it in needs a bigger plan. - Clients always come in as To complete: the service name you send matches none of yours. Compare it character by character with the Services page.
- Wrong setter or closer: the name you sent probably matched more than one person, so the webhook default won.