> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.leadtruffle.co/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# How to Send Leads to LeadTruffle Using Custom Lead Sources (Webhooks)

📝 *Send leads from Zapier, Make, web forms, or any external tool into LeadTruffle via webhook, with SMS opt-in set up so your texts send.*

---

## Table of contents

* [Overview](#2-overview)
* [Step 1: Open Custom Lead Sources](#2-step-1-open-custom-lead-sources)
* [Step 2: Create the source](#2-step-2-create-the-source)
* [Step 3: Copy your webhook URL](#2-step-3-copy-your-webhook-url)
* [Step 4: Send a test lead](#2-step-4-send-a-test-lead)
* [Step 5: Map lead fields](#2-step-5-map-lead-fields)
* [Step 6: Set up SMS opt-in proof](#2-step-6-set-up-sms-opt-in-proof)
* [Step 7: Add optional and custom fields](#2-step-7-add-optional-and-custom-fields)
* [Step 8: Prevent duplicate leads with External Lead ID](#2-step-8-prevent-duplicate-leads-with-external-lead-id)
* [Step 9: Handle returning contacts and repeat inquiries](#2-step-9-handle-returning-contacts-and-repeat-inquiries)
* [Step 10: Run a dry test](#2-step-10-run-a-dry-test)
* [Step 11: Choose what happens when leads arrive](#2-step-11-choose-what-happens-when-leads-arrive)
* [Step 12: Activate the endpoint and confirm SMS compliance](#2-step-12-activate-the-endpoint-and-confirm-sms-compliance)
* [Recap](#2-recap)

---

## Overview

Custom Lead Sources let you send leads from **almost any external system** into LeadTruffle using a webhook.

${frame}[](https://www.loom.com/embed/05fbc771f96d49cfa7d527048746bb80)

This is ideal for advanced integrations such as:

* Zapier
* Make
* n8n
* Custom web forms
* Lead aggregators
* CRMs or internal tools

Instead of forwarding leads by email, you **POST lead data directly to LeadTruffle**, which then creates and optionally qualifies the lead automatically.

If you want a simpler option, you can also forward leads using the Email Gateway.

---

## Step 1: Open Custom Lead Sources

1. Log into app.leadtruffle.com
2. Navigate to **Custom Lead Sources**
3. Click **Add Source**

|| If you don't see **Custom Lead Sources**, contact support and we can enable it for your account.

---

## Step 2: Create the source

Fill out the basic setup:

1. **Configuration name:** Choose something unique (e.g. "Web Forms"). This is used inside LeadTruffle and becomes the fallback Lead Source label if you do not enter a separate display label.
2. **Source Template:** Select **Custom**.
3. **Provider type (optional):** Add a technical provider classification if your setup requires one. This value does not appear as the Lead Source on the contact and does not override any source label.
4. **Lead Source label (optional):** Enter the fixed, customer-facing name you want shown in the Leads table (e.g. "Corporate Leads" or "Opta"). Leave this blank to use the Configuration name.
5. **Icon:** Choose the icon that best represents this source. The icon appears with the source in lead and conversation views and does not affect field mapping or lead routing.
6. Click **Continue**.

![Custom Lead Source setup showing the configuration name, Lead Source label, icon picker, and Leads table preview](https://storage.crisp.chat/users/helpdesk/website/-/d/c/4/1/dc41d3f6726e4000/image_pohd61.png =750x552)

| The **Leads Table Preview** shows how the source will appear before you begin mapping the payload. You can keep this fixed label for every lead or override it per lead using a mapped payload value during Optional Mapping.

---

## Step 3: Copy your webhook URL

On the next screen you'll see **two webhook endpoints**:

* **Test Endpoint**
* **Live Endpoint**

| Recommended: use the **Live Endpoint** right away so you don't have to update your integrations later.

Click **Copy URL**. This is where your external systems will send lead data.

---

## Step 4: Send a test lead

Before mapping fields, send **one test lead** so LeadTruffle can detect the incoming data structure.

You can do this a few ways:

### Option 1 — Test from your integration tool

Many platforms include a test feature:

* Zapier → **Test Trigger**
* Make → **Run once**
* Some CRMs and lead providers can also send test data

### Option 2 — Send a test via terminal (cURL)

You can manually send a sample lead with a **cURL POST request**. Replace the URL with your **Live Endpoint** from LeadTruffle:

```
curl -X POST "PASTE_YOUR_LEADTRUFFLE_WEBHOOK_URL_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "John",
    "lastName": "Smith",
    "phone": "5125550123",
    "email": "john.smith@example.com",
    "message": "I need a quote for pressure washing my driveway and patio.",
    "service": "Pressure Washing",
    "source": "Website Contact Form",
    "smsOptInUrl": "https://example.com/consent/john-smith-optin"
  }'
```

| If your source sends the name as one combined field instead of separate first/last fields, include a single `full_name` value (e.g. `"full_name": "John Smith"`). You'll choose how to map it in Step 5.

### What this test does

* Sends a **sample lead** to your webhook
* Lets LeadTruffle **capture the payload**
* Enables you to **map incoming fields** during setup

### Fields included in the example

| Field | Description |
| ---- |
| firstName | Lead's first name |
| lastName | Lead's last name |
| phone | Lead phone number |
| email | Lead email |
| message | Project description |
| service | Example custom field |
| source | Where the lead originated |
| smsOptInUrl | URL showing SMS consent proof |

After running the test, return to the **Custom Lead Source setup screen** and confirm that **Payloads Captured = 1**, then click **Continue**.

---

## Step 5: Map lead fields

LeadTruffle now displays the fields captured from your webhook. Click **Auto Map Fields** to match common fields automatically.

Typical required mappings:

| Incoming field | LeadTruffle field |
| ---- |
| email | Email |
| phone | Phone |
| message | Project Description |

### Map the contact name

LeadTruffle gives you two ways to map the lead's name, depending on how your source sends it. Use the **Full name / First + last** toggle on the **Contact Name** field to switch between them.

* **First + last** — map two separate fields. Use this when your webhook sends the name in two parts (e.g. `$.firstName` and `$.lastName`).
* **Full name** — map a single field (e.g. `$.full_name`). LeadTruffle automatically splits it into a first and last name for you.

![](https://storage.crisp.chat/users/helpdesk/website/-/d/c/4/1/dc41d3f6726e4000/image_u45ulo.png)

| Many lead sources — like Meta Lead Ads — send the name as one combined field. In that case, choose **Full name** and map it to that single field. The **Live Mapping Preview** confirms the split (e.g. Full Name: Angie Sandridge → First Name: Angie, Last Name: Sandridge).

When the name field resolves, you'll see a green **Resolved** badge.

### Choose how the lead source appears

LeadTruffle can show two levels of source information:

* **Lead Source** — the primary source name shown for the lead, such as "New Leads From Corporate," "Opta," or "Facebook."
* **Original Source** — the upstream channel, vendor, or marketplace that produced that individual lead, such as "Facebook" or "Google."

### Lead Source label priority

When more than one Lead Source label is configured, the highest available value in this order is displayed:

| Priority | Setting | How it works |
| ---- |
| 1 — highest | Dynamic `leadSourceLabel` mapping | Uses a value from each incoming payload, so different leads can display different primary sources. |
| 2 | Fixed **Lead Source label** from the Basics step | Uses the same customer-facing Lead Source for every lead created by this configuration. |
| 3 — fallback | **Configuration name** | Displays only when neither a dynamic value nor a fixed Lead Source label is available. |

**Provider type** and **Original Source** are not part of this priority order:

* **Provider type** is technical metadata and does not display as the contact's Lead Source.
* **Original Source** is a separate secondary value. It can appear alongside the primary Lead Source but does not replace it.

Use the option that matches how you want to report on these leads:

| What you want to see | What to configure | Example result |
| ---- |
| Keep one fixed Lead Source and show the payload value underneath | Set the fixed **Lead Source label** in the Basics step. In **Additional Data**, use the key `Source` and map it to the payload path containing the origin, such as `$.leadsource`. | Lead Source: New Leads From Corporate; Original Source: Facebook |
| Use the payload value as the primary Lead Source | In **Additional Data**, use the key `leadSourceLabel` and map it to the payload path, such as `$.leadsource`. This overrides the fixed Basics label for each lead. | Lead Source: Facebook |
| Use only one fixed Lead Source for every lead | Set the **Lead Source label** in the Basics step and do not map a source field from the payload. | Lead Source: New Leads From Corporate |
| Map both levels from the payload | Map the primary value using the key `leadSourceLabel`, and map the upstream value using the key `Source` or `originalSourceLabel`. | Lead Source: Corporate Campaign; Original Source: Facebook |

For example, if the payload contains:

```
"leadsource": "Facebook"
```

Use one of these mappings:

```
Source → $.leadsource
```

This keeps the configured Lead Source and displays **Facebook** as the **Original Source**.

Or:

```
leadSourceLabel → $.leadsource
```

This displays **Facebook** as the primary **Lead Source** instead.

||| A payload field named `source` or `leadsource` usually belongs in **Original Source**. 

Use `leadSourceLabel` only when that payload value should replace the configured Lead Source label for the individual lead.

---

## Step 6: Set up SMS opt-in proof

If you plan to qualify leads over SMS, LeadTruffle needs to know that each lead consented to receive text messages. **How you handle this during mapping determines what you'll need to check when you activate the endpoint in** [**Step 12**](#2-step-12-activate-the-endpoint-and-confirm-sms-compliance)**.**

### Map the SMS Opt-In Proof URL field

In the **Optional standard fields** section, find **SMS Opt-In Proof URL** and map it to the webhook field that holds your consent proof. This can be either:

* A URL pointing to stored consent proof — for example `$.smsOptInUrl`
* The consent or disclaimer text passed in the payload — for example `$.disclaimer`

![SMS Opt-In Proof URL mapped and resolved during field mapping](https://storage.crisp.chat/users/helpdesk/website/-/d/c/4/1/dc41d3f6726e4000/image_p4nic1.png =750x513)

| As long as **any** text value lands in this field, LeadTruffle treats the lead as opted in and SMS will send. Almost any text passes — the only values that fail are clearly negative ones like "no" or "false."

When the field resolves to a value, you'll see a green **Resolved** badge. That's your confirmation that opt-in proof is being captured for each lead.

|| No opt-in proof field to map? You can still send SMS — but you'll need to override the opt-in check during activation. See [Step 12](#2-step-12-activate-the-endpoint-and-confirm-sms-compliance).

---

## Step 7: Add optional and custom fields

Optional and custom fields let you capture additional lead information.

### Reference webhook fields

The format for referencing a webhook field is:

```
$.fieldName
```

For example:

```
$.smsOptInUrl
```

### Create a custom field

If your webhook sends a field that doesn't exist in LeadTruffle, you can create one:

1. Scroll to **Additional Data**
2. Click **Add Field**
3. Name the field (e.g. `service`)
4. Map it using `$.service`

If it's configured correctly, you'll see a **green checkmark** confirming the field exists in the webhook payload.

---

## Step 8: Prevent duplicate leads with External Lead ID

LeadTruffle already checks every incoming webhook against the webhook body and automatically ignores exact duplicate deliveries — so most sources never need to configure anything here. Use this step only if you're seeing duplicate leads, or you want an extra layer of protection based on a unique ID from your source.

### How it works

You can map an **External Lead ID** — the value your source uses to uniquely identify a single lead inquiry — and tell LeadTruffle to ignore any repeat webhook that carries the same ID.

1. In the **Optional standard fields** section, find **External Lead ID**
2. Map it to the webhook field that holds your source's unique lead ID (e.g. `$.leadId`)
3. Check **Use External Lead ID to ignore duplicate webhooks**

![External Lead ID field with the option to ignore duplicate webhooks](https://storage.crisp.chat/users/helpdesk/website/-/d/c/4/1/dc41d3f6726e4000/screenshot-from-2026-08-03-16-_huo0b.png)

Mapping the field on its own only stores the ID on the lead record — it does **not** turn on duplicate protection. The checkbox is what enables it.

Once enabled, any repeat delivery with the same External Lead ID is stored as an **ignored duplicate**: it won't create another contact, lead inquiry, or message.

||| Only enable this when the mapped value uniquely identifies **one** lead inquiry. If you map it to a value that's shared across leads — like a Facebook or Meta ad ID — every lead after the first will carry that same ID and be ignored as a duplicate. If you're not certain the value is unique per lead, leave the checkbox off.

### Review your webhook logs

Your webhook logs show **deduplicated, failed, and retried** deliveries together in one place. That makes it easy to confirm when a duplicate was ignored, spot a delivery that failed, and see what was retried — so you can tell the difference between "no lead came through" and "the lead was correctly deduplicated."

---

## Step 9: Handle returning contacts and repeat inquiries

When the same person reaches out more than once, LeadTruffle handles it intelligently — both in how the AI talks to them and in how repeat webhooks are treated. This is separate from the External Lead ID check in Step 8: External Lead ID matches on a unique **inquiry** ID, while the settings here work at the **contact** level.

### Smarter returning-contact conversations

If a contact who has reached out before comes in again, the AI recognizes them as a returning contact instead of treating them like a brand-new lead. It draws on what already happened with that contact — including prior outbound-call outcomes, such as a booked estimate — and continues the conversation naturally from there rather than starting over.

*Example: You already spoke with a contact and booked an estimate. When they send a new inquiry, the AI picks up with that context instead of re-asking the same qualifying questions.*

### Ignore repeat inquiries from the same contact

You can also tell LeadTruffle to ignore repeat inquiries from a contact within a set time window.

1. On the test endpoint setup screen (the same screen where you copy your webhook URL), look under **Auth mode**
2. Find **Ignore duplicate contact webhooks within [ ] days**
3. Enter the number of days you want the window to cover - this defaults to **30**

![Ignore duplicate contact webhooks within a set number of days, shown on the test endpoint setup screen](https://storage.crisp.chat/users/helpdesk/website/-/d/c/4/1/dc41d3f6726e4000/image_1tkovyu.png =800x565)
How it behaves:

* If a new webhook matches a contact who already has a recent custom webhook inquiry inside the window, it's stored as an **ignored duplicate** — no new inquiry is created and no message is sent.
* Set the value to **0** to disable this behavior entirely and treat every webhook as a fresh inquiry.

| Ignored webhooks are still recorded in your webhook logs (the same logs from Step 8), so you can confirm a repeat was correctly ignored rather than silently dropped.

||| Choose your window based on your sales cycle. A longer window suppresses more repeat inquiries from the same person; a shorter window (or `0`) lets a returning contact start a fresh inquiry sooner.

---

## Step 10: Run a dry test

Before going live, LeadTruffle runs a **dry test** to preview how the lead will be created. Example output:

* Name: John Smith
* Email: john.smith@example.com
* Phone: 512-555-0123
* Project Description: Pressure washing quote

If a required field appears empty, go back and adjust your mappings.

---

## Step 11: Choose what happens when leads arrive

LeadTruffle gives you four options for handling incoming webhook leads.

### 1. Create lead only

Creates the lead without sending any messages. Useful if your team wants to follow up manually.

### 2. Create + qualify over email

Creates the lead and sends an automated email.

|| Requires an **Email Gateway** to be configured.

You can customize the subject line with variables such as:

```
{{firstName}} your pressure washing request
```

### 3. Create + qualify over SMS

Creates the lead and starts an **AI SMS conversation**.

### 4. Create + qualify over email AND SMS (recommended)

Creates the lead, sends an email, and starts an SMS conversation — maximizing your chance of reaching the lead quickly.

---

## Step 12: Activate the endpoint and confirm SMS compliance

Before your webhook goes live, you'll confirm a short set of SMS compliance requirements. **Which boxes you need to check depends on whether you mapped an SMS Opt-In Proof URL in** [**Step 6**](#2-step-6-set-up-sms-opt-in-proof)**.**

![SMS Compliance Requirements checkboxes on the activation screen](https://storage.crisp.chat/users/helpdesk/website/-/d/c/4/1/dc41d3f6726e4000/image_uoksf9.png =750x451)

You'll see up to three checkboxes:

1. **I confirm these leads explicitly consented to receive SMS messages, and my company has active 10DLC registration.**
2. **Override opt-in checks and always consider all leads opted in.** — bypasses the per-webhook consent proof check for every lead from this source.
3. **I understand activating this endpoint can create real leads and trigger automated messaging.**

### Make sure SMS will actually send

What you check depends on your Step 6 setup:

**If you mapped an SMS Opt-In Proof URL with a value:**

* Check **box 1** and **box 3**
* Leave box 2 unchecked — LeadTruffle reads the opt-in proof from each lead's payload

**If you did NOT pass a value into SMS Opt-In Proof URL:**

* Check **box 1**, **box 2**, and **box 3**
* Box 2 overrides the consent-proof check so SMS can still send

||| Only use box 2 (override) when you have independent proof that every lead from this source has consented to SMS. It bypasses LeadTruffle's per-lead consent verification for the entire source.

Once the required boxes are checked, the **Activate Live Endpoint** button becomes available. Click it to go live. Any system sending data to your webhook will now create leads in LeadTruffle automatically.

---

## Recap

To send leads into LeadTruffle using webhooks:

1. Create a **Custom Lead Source**, choose its display label, and select an icon
2. Copy your **Webhook Endpoint**
3. Send a **test lead**
4. **Map required fields** — including the contact name as **First + last** or **Full name**
5. Choose whether a mapped source value should be the primary **Lead Source** or the secondary **Original Source**
6. Set up your **SMS Opt-In Proof URL** so texts can send
7. Add optional or custom fields
8. (Optional) Map an **External Lead ID** and enable dedup if you run into duplicate webhooks
9. Set your **duplicate-contact window** and let the AI pick up naturally with returning contacts
10. Run a **dry test**
11. Choose how leads should be handled
12. Confirm the right **SMS compliance** boxes and **activate the Live Endpoint**

Once set up, your external tools can automatically send leads into LeadTruffle for capture and qualification.

---

Need help? Contact us at support@leadtruffle.com or message the team via the chat on this article or in-app.