Lead Forwarding
Settings → Lead Forwarding sends new leads from Evolzer CRM to another system automatically — a school admissions platform, a client's own CRM, a Zapier, Make or n8n scenario, or any endpoint that accepts an HTTP request. You describe each destination once (where to send, what the request looks like, which leads qualify); after that every new lead is pushed on its own, every send is logged, and failed sends are retried on a schedule.
Requires the Manage integrations permission (Admins by default). The section sits in the Integrations group of the docked Settings panel, next to Lead Chains and Integrations.
How forwarding works
- About once a minute the CRM looks for leads created since each destination was last checked, queues one delivery per lead, and sends whatever is due. A new lead normally reaches the destination within a minute or two.
- Only leads created after a destination is switched on are considered. Creating a destination, or turning its switch on, sets the starting point to that moment — your existing leads are never pushed in bulk, and leads created while a destination was off are skipped.
- A lead is forwarded to a given destination at most once automatically. When the send succeeds, the lead's Activity Timeline gets a "Forwarded to destination" entry.
- A destination only forwards on its own when both Enabled and Forward new leads automatically are on, and only leads that pass its Filters are queued.
Add a destination
- Click Add destination.
- Choose a preset — Schoolknot, Generic JSON Webhook, Zapier Webhook, Make (Integromat) Webhook or n8n Webhook — or Blank destination to start from scratch. A preset pre-fills the URL, method, format, headers, body template and value maps, and adds an empty slot for every secret the template refers to.
- Complete the form (see Configure a destination) and click Create destination.
New destinations are created disabled, with Forward new leads automatically on. Test first, then switch the destination on from its card or from the Enabled switch in Config.
The destination opens in a panel on the right that takes half the screen on a desktop (the full screen on a phone). A saved destination has three tabs: Config, Test and Deliveries.
The destinations list
Each destination is a card showing its name, the host it sends to, an Enabled / Disabled chip, the preset it was built from, and an on/off switch. Click the card to open it; use the switch to turn forwarding on or off without opening it.
Configure a destination
Basic
| Field | What it does |
|---|---|
| Name | How the destination is shown in the list, in the Deliveries log and on lead timelines. |
| Destination URL | Must start with https://. Addresses on private networks, localhost and .local / .internal hosts are rejected when you save. The request goes to exactly this address — redirects are not followed, and placeholders are not replaced inside the URL. |
| HTTP method | POST (default) or PUT. |
| Body format | JSON (sent as application/json) or Form (x-www-form-urlencoded). With Form, nested objects in the template are flattened with dots (student.name=…) and lists with an index (items[0]=…). |
| Enabled | Master switch. Off means nothing is sent automatically. |
| Forward new leads automatically | When on, each new lead that passes the filters is queued for this destination. When off, the only sends are the ones you trigger from Send test or Retry. |
Headers
Add a row per header: Header name and Value. Values can contain placeholders, including {{secret.name}} (see below). Content-Type is set for you from the body format; add your own Content-Type header only if the destination needs a different one — yours wins.
Header values are stored as plain text and shown in full to everyone who can open this panel. Put API keys in Secrets, not here.
Secrets
API keys and tokens live here. Add a row with a Secret name (for example api_key) and its value, then refer to it anywhere in Headers or the Body template as {{secret.api_key}}.
- Values are encrypted when stored. After you save, the field shows only the last four characters (
••••xxxx); leave it blank to keep the stored value, or type a new value to replace it. - In the Test tab's preview the secret is replaced by
***REDACTED***, so nobody learns the key by previewing a request.
Why this matters: a key pasted straight into a header value or the URL is visible to everyone with the Manage integrations permission and stays visible for as long as the destination exists. A secret is shown once — when you type it — and never again.
Body template
A JSON object that becomes the request body. Any string value can contain {{placeholders}}; objects may be nested and lists are allowed. The template must be valid JSON — an error appears under the box and the save button stays disabled until it is fixed. Show available tokens opens a reference that also lists your own Lead custom field keys.
A placeholder with no value becomes an empty string, so the key is still sent ("email": ""). Custom field values are always sent as text — a checkbox field becomes "true" or "false", a number "42".
Placeholders
| Placeholder | Value |
|---|---|
{{lead.id}} | The lead's id in Evolzer CRM. |
{{lead.name}}, {{lead.email}}, {{lead.company}}, {{lead.city}} | The matching lead fields. |
{{lead.phone}} | The phone number exactly as stored. |
{{lead.phone_country_code}} | The country code, e.g. +91. |
{{lead.phone_national}} | The number without the country code, digits only. |
{{lead.source}} | The stored source value: MANUAL, WEBSITE, Google, GOOGLE_LEAD_ADS, META_LEAD_ADS, LANDING_PAGE, OUTREACH or AI_COPILOT. |
{{lead.status}} | NEW, CONTACTED, QUALIFIED or LOST. |
{{lead.created_at}} | When the lead was created, as a full date-time (e.g. 2026-10-09T08:15:30.000Z). |
{{lead.created_date}} | The same, as YYYY-MM-DD. |
{{custom.key}} | A Lead custom field, by the key shown in Settings → Custom Fields. |
{{utm.source}}, {{utm.medium}}, {{utm.campaign}}, {{utm.term}}, {{utm.content}} | The lead's UTM parameters. |
{{org.name}} | Your organisation's name. |
{{secret.name}} | A secret from the Secrets section. |
Phone splitting: spaces, dashes, dots and brackets are removed first. A 10-digit number with no country code is treated as Indian (+91). Numbers that start with + are split on their code — +1, +44, +61, +91 and +971 are recognised directly; other prefixes are split by a best guess based on length, so check the Preview if your leads come from elsewhere.
Filters (pipes)
Add | filter after a placeholder to transform the value. Filters apply left to right and can be chained; the quotes around an argument are optional.
| Filter | What it does | Example |
|---|---|---|
default:"text" | Uses text when the value is empty. | {{lead.company | default:"Unknown"}} |
lower | Lower-cases the value. | {{lead.email | lower}} |
digits | Keeps digits only. | {{lead.phone | digits}} |
date:"YYYY-MM-DD" | Reformats a date: YYYY, MM and DD are replaced, everything else is kept (date:"DD/MM/YYYY" gives 09/10/2026). Empty values stay empty; a value that is not a date is passed through unchanged. | {{lead.created_at | date:"DD/MM/YYYY"}} |
map:name | Looks the value up in the value map called name. | {{custom.grade | map:grade_code}} |
Chained example: {{custom.grade | map:grade_code | default:"0"}} — look the grade up, and send 0 if the lookup gives nothing. A filter name the CRM does not know is ignored and the value passes through.
Value maps
Value maps translate your values into the codes the destination expects — "Grade 5" into 9, "Meta Ads" into 1, and so on.
- Type a Map name (for example
grade_code) and click Add map. - Click Add mapping and fill From value → To value for each pair. Remove map deletes the whole map.
- Use it in the template with
| map:grade_code.
Matching ignores upper/lower case. When no row matches, the original value is sent unchanged (maps that come with a preset may define their own fallback instead — see the Schoolknot preset below).
Filters
Lead sources — click the source chips to select any of Manual, Website, Google (website), Google Lead Form Ads, Meta Ads, Landing Page, Outreach and AI Copilot. With one or more selected, only leads from those sources are forwarded. With none selected, every new lead is forwarded.
Save or delete
Create destination (new) or Save changes (existing) stores the configuration. Delete asks for confirmation and removes the destination from the list; this cannot be undone.
Save before you test: the Test tab and every automatic send use the configuration as last saved, not what is currently typed in Config.
Test a destination
Open a saved destination and switch to the Test tab.
- Select a lead — the list shows up to 50 of your leads.
- Preview renders the body for that lead with secrets redacted. Check that every field holds what the destination expects. For the Schoolknot preset, a Warnings box lists any mandatory field that is still empty (
Missing mandatory field: father_name). - Send test makes a real request to the destination with that lead's data — the receiving system will get it. The result box shows SUCCEEDED or FAILED, the HTTP status, the error (if any) and the first 500 characters of the destination's reply. This is the one place where you can read the destination's actual response text, so use it to diagnose rejections.
Test sends appear in Deliveries with Kind TEST. They are not written to the lead's Activity Timeline. A test that fails is retried on the same schedule as any other delivery, using whatever configuration is saved at the time of each attempt — so once you fix the problem the pending retry goes through on its own.
Deliveries
The Deliveries tab is the log for one destination, newest first, 25 per page (Previous / Next).
| Column | What it shows |
|---|---|
| Time | When the delivery was queued. |
| Lead | The first characters of the lead id; click to open the lead on the Leads page. |
| Kind | AUTO — queued automatically for a new lead. TEST — sent from the Test tab. |
| Status | See below. |
| HTTP | The status code the destination answered with, or — when the request never got through. |
| Error | A short description of the last failure, such as HTTP 401 or fetch failed. Hover for the full text. |
| Actions | Retry on Failed and Dead rows. |
Statuses
| Status | Meaning |
|---|---|
| PENDING | Queued; goes out on the next send cycle. |
| SENDING | Being sent right now. |
| SUCCEEDED | The destination accepted the request (a 2xx reply — and, for Schoolknot, no error reported in its JSON answer). |
| FAILED | The last attempt failed; another attempt is scheduled. |
| DEAD | Six attempts failed; no more automatic retries. |
The log does not refresh itself — switch to another tab and back to reload it. The destination's response text is not shown here; use Send test to see it.
Retries and Dead deliveries
After a failed attempt the CRM waits, then tries again: after 1 minute, then 5 minutes, 30 minutes, 2 hours and 6 hours. When the sixth attempt also fails the delivery becomes DEAD, and the lead's Activity Timeline gets a "Forwarding to destination failed" entry.
Every attempt uses the destination's configuration as saved at that moment. Fixing a wrong header, URL or secret is enough — the pending retries pick the fix up without any further action.
An attempt counts as failed when the destination answers with anything other than a 2xx status, does not answer within 10 seconds, cannot be reached, replies with a redirect, or (Schoolknot only) returns JSON with status: false, error: true or success: false.
Retry button
Retry sends a Failed or Dead delivery again immediately, with the current configuration, and the row updates in place:
- A retried Failed delivery that fails again goes back onto the normal schedule.
- A retried Dead delivery either succeeds or returns to Dead.
- If the delivery happens to be mid-send at that moment the click does nothing — wait a little and look again.
The Schoolknot preset
Choose Schoolknot in Add destination to get a ready-made destination for Schoolknot's enquiry API:
- URL
https://schoolknot.com/API/newEnquiry.php, method POST, format JSON. - A Secrets slot named
api_key— paste the key Schoolknot gave you. The template sends it in the body asapi_key. - A Body template that maps the lead to Schoolknot's fields:
student_namefrom the lead's name,email,country_codeandmobilefrom the split phone number,father_namefrom the Lead custom fieldparent_name,present_schoolfromprevious_school,admission_opted_forfrom the custom fieldgradethrough thegrade_codemap, andsourcefrom the lead source through thesource_codemap.mother_name,father_occupation,dobandgenderare sent empty — fill them in the template if you capture them. - Two Value maps:
grade_codetranslates grade names (Pre Primary, Nursery, LKG, UKG, Grade 1 … Grade 12, the CBSE and IBDP variants, and their Roman-numeral forms) into Schoolknot's numeric admission codes and sends an empty value for anything it does not recognise;source_codesends1for every source. Open both maps and check the codes against what Schoolknot gave you before enabling the destination.
For this preset to work, define Lead custom fields with the keys parent_name, grade and previous_school in Settings → Custom Fields (or edit the template to use the keys you already have). Preview warns when any of Schoolknot's mandatory fields — api_key, student_name, father_name, mobile, admission_opted_for, source — would be sent empty, and a reply from Schoolknot that reports an error in its JSON is treated as a failed attempt even when the HTTP status is 200.
Common errors
| What you see | What it means | What to do |
|---|---|---|
HTTP 401 and a reply such as X-API-KEY header is required (visible in Send test) | The destination expects a header you have not added. | Under Headers add X-API-KEY with the value {{secret.api_key}}, add a secret named api_key holding the key, Save changes, test again. |
| HTTP 401 / 403 with another message | The key is wrong, expired or sent in the wrong place. | Re-enter the secret value; check whether the destination wants the key in a header or in the body. |
| HTTP 404 / 405 | Wrong URL or wrong HTTP method. | Check the URL and switch between POST and PUT. |
| HTTP 400 / 422 | The destination rejected the body. | Preview the body and compare field names and formats with the destination's documentation; for Schoolknot read the Warnings. |
fetch failed | The CRM could not complete the request: the host could not be reached, the certificate was rejected, or the destination answered with a redirect (redirects are never followed). | Check the address; use the final URL the destination actually accepts. |
This operation was aborted | No reply within 10 seconds. | Check that the destination is up and responsive. |
| "Lead forwarding URLs must use HTTPS" when saving | The URL starts with http://. | Use https://. |
| "Lead forwarding to host … is not allowed" or "private IP address is not allowed" | The destination is on a private network. | Forwarding only reaches addresses on the public internet. |
| "Body template is not valid JSON." | A typo in the template (missing comma, quote or bracket). | Fix it; the error under the box disappears when the JSON is valid. |
Missing mandatory field: father_name in Preview | The lead has no value for the custom field the template reads, or the template uses a key that does not exist in your custom fields. | Fill in the lead, or point the template at the right {{custom.key}}. |
| A new lead never shows up in Deliveries | The destination (or Forward new leads automatically) is off; the lead was created before the destination was switched on; its source is not among the selected Lead sources; or the next send cycle has not run yet. | Check the switches and filters, then wait a minute or two. |
Security notes
- Secrets are encrypted at rest, masked after saving and redacted from previews. Prefer
{{secret.name}}in a header over pasting a key anywhere visible. - A key in a URL is a password. Placeholders are not replaced in the URL, so a destination that wants its key as a query parameter (
…?key=…) forces you to type the key into the Destination URL field in plain text — where anyone with the Manage integrations permission can read it, and where it also lands in the destination's server logs. Use a header with a secret whenever the destination supports it. - If a key leaks, rotate it: get a new key from the destination, type it into the secret's value (or the URL), and Save changes. Pending retries use the new key automatically.
- Requests go only to HTTPS addresses on the public internet, never follow redirects and give up after 10 seconds.
- Everyone with the Manage integrations permission can open every destination and read its URL and header values. Grant that permission deliberately (see Team & Access).