Module · The nineteen workflows
Capturing a lead from any other system
Lesson 15 of 40 · 6 min
Every other workflow in this module starts from something that has already happened inside Expedify — a deal appearing, a contact changing, a message arriving. This one starts somewhere else entirely: a system you do not control posts to a URL, and a lead exists that did not exist a second ago.
This is the workflow that answers the first question a client asks. “We already have a website, an ad account and a dialler — will this work with what we have?” The answer is this URL, and it is worth being able to open it on a screen while you say so.
The front door
1.1 · Bring leads in from any other system
Something posts in. The org looks for that phone number. Either a contact is created or an existing one is topped up — and either way, an enquiry is raised.
Scroll for all 6 steps →
Six boxes, and only one of them is unusual. The rest are the CRM Manager and branch boxes you already read in Module 2. The unusual one is the first: a Webhook Trigger is a door rather than a watcher — it does not look at your data at all, it waits to be knocked on.
Any system that can post JSON
The sending system needs to know nothing about Expedify. Not your schema, not your stages, not your field names — just a URL and a body. That is a low enough bar that most things a client already runs can clear it:
- The website form they already have, pointed at a new address.
- An ad platform's lead form, through whatever connector they use today.
- A call centre or dialler, posting when an agent takes a number down.
- The old CRM, during the month you run both.
- A spreadsheet, a Zap, a script somebody's nephew wrote. It genuinely does not matter.
This is what makes an Expedify org reachable rather than a destination. No client is going to re-point every system they own on day one. They point one, see enquiries appear, and point the next.
The payload is a contract
Open create_contact and raise_enquiry, and read what they are built from. Every value is a reference into the body that was posted, which means the workflow is stating, in writing, what the sender has to send:
| Lands on | Fields the sender must post |
|---|---|
| The contact | first_name, last_name, email, phone, city, source |
| The enquiry | first_name, last_name, amount, source, requirement |
The contact
- Fields the sender must post
first_name, last_name, email, phone, city, source
The enquiry
- Fields the sender must post
first_name, last_name, amount, source, requirement
Hand a client's developer this list and the integration is specified. There is no separate contract to write, and no way for the contract to drift from what the workflow reads — because it is what the workflow reads. Same {{ }} mechanism as Variables: how one node uses another's output, pointed at a body that arrived over the wire.
Nobody gets a second record
The second box searches contacts for the phone number that just came in, and the branch after it asks one question: did that search come back empty?
| The search found | Which arm runs | What happens |
|---|---|---|
| Nothing | New person | A contact is created from the whole payload. |
| Somebody | Already on file | The existing contact is topped up. No second record. |
Nothing
- Which arm runs
- New person
- What happens
- A contact is created from the whole payload.
Somebody
- Which arm runs
- Already on file
- What happens
- The existing contact is topped up. No second record.
Phone, not email, and that is deliberate. People give a work email one week and a personal one the next; the number on the form is the number they answer. Whatever a client's version matches on, the shape is the same one you read in Conditions and branches — a search, then a fork on what it returned.
The returning arm writes two fields, not six
This is the detail worth slowing down for, because it is the difference between a workflow that helps and one that quietly destroys history. When somebody already on file enquires again, only these are rewritten:
cityemail
Everything else is left exactly as it was — including first_name, last_name, phone, source. The record on file is what the business has learnt about this person. The form is a fresh claim about how to reach them today. Contact details are worth taking from the newer of the two; who they are, and where they originally came from, are not.
If this arm overwrote source, every returning lead would look like it came from wherever they happened to click last. Attribution would be destroyed a record at a time, silently, and the reports in Module 3's last lesson would be confidently wrong. A one-line decision in one node, with consequences three modules away.
Change one thing — knock on your own door
You are going to post a lead into your own org, twice, and watch a different arm run each time. Open intake and copy the URL out of your own org — it is unique to your webhook, and the one in this page is not yours.
curl -X POST '<the webhook URL from your intake node>' \
-H 'Content-Type: application/json' \
-d '{
"first_name": "Ravi",
"last_name": "Deshmukh",
"phone": "+919876500011",
"email": "ravi.d@example.com",
"city": "Pune",
"source": "Partner test",
"amount": "1500000",
"requirement": "Wants a term plan, first time buyer"
}'- Post it once. Open the run and confirm the New person arm ran, and that a contact and an enquiry both appeared.
- Post the same body again, unchanged. This is the important one.
- Open the second run. A different arm ran, no second contact exists, and there are now two enquiries against one person — which is correct: they enquired twice.
- Change the city in the body and post a third time. Check the contact's city moved and their name did not.
- Delete the test contact and its enquiries when you are done.
Try it
- Post a body with the phone number missing and read what the run does about it. Decide whether you would ship that behaviour to a client.
- Write down, in one sentence each, what you would need from a client's developer to point their form here. You should need two things and no meetings.
Next: Filling in what the form did not ask — the lead is now in the org with four fields filled in, and something has to go and find the rest before anybody picks up the phone.

