Add Duplicate Lead
Scope:
crmWho can execute the method: users with read access permission for leads, contacts, companies, and permission to create leads.
If you are developing integrations for Bitrix24 using AI tools (Codex, Claude Code, Cursor), connect the MCP server so that the assistant can utilize the official REST documentation.
When a client fills out a form on the website, their data is sent to a handler. The script searches the CRM for matches by phone or email among leads, contacts, and companies. If matches are found, the lead is marked as a duplicate and linked to the existing record. This approach helps avoid duplicates and increases the efficiency of managers.
The repeat lead mode must be enabled in Bitrix24. Read more in the article Repeat Leads and Deals.
The setup consists of two stages:
-
Prepare the fields and place the form on the page.
-
Create a handler file that sequentially calls the methods crm.duplicate.findbycomm, crm.lead.list, crm.lead.add.
1. Create a Web Form
Create an HTML form with the following fields:
-
NAME— client's first name, required field, -
LAST_NAME— last name, -
PHONE— phone number, -
EMAIL— email address.
The form sends data using the POST method to the file form.php.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#form_to_crm').on('submit', function(el) { // event submit form
el.preventDefault(); // the default action of the event will not be triggered
var formData = $(this).serialize();
$.ajax({
'method': 'POST',
'dataType': 'json',
'url': 'form.php', // file for saving filled forms
'data': formData,
success: function(data) { // success callback
alert(data.message);
}
});
});
});
</script>
<form id="form_to_crm">
<input type="text" name="NAME" placeholder="Name" required>
<input type="text" name="LAST_NAME" placeholder="Last name">
<input type="text" name="PHONE" placeholder="Phone">
<input type="text" name="EMAIL" placeholder="E-mail">
<input type="submit" value="Submit">
</form>
2. Create the Form Handler
Create the file form.php. The handler will process the data, check for duplicates, and create a lead.
Retrieve Data from the Form
Retrieve and safely process the data from the fields NAME, LAST_NAME, PHONE, EMAIL to avoid XSS attacks.
$sName = htmlspecialchars($_POST["NAME"]);
$sLastName = htmlspecialchars($_POST["LAST_NAME"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$sEmail = htmlspecialchars($_POST["EMAIL"]);
Form an array $arFields with the new lead's data.
$arFields = [
'TITLE' => 'From the site: ' . implode(' ', [$sName, $sLastName]),
'NAME' => (!empty($sName)) ? $sName : 'Empty name',
'LAST_NAME' => $sLastName,
'PHONE' => (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'HOME')) : array(),
'EMAIL' => (!empty($sEmail)) ? array(array('VALUE' => $sEmail, 'VALUE_TYPE' => 'HOME')) : array()
];
The lead's title is formed as From the site: FirstName LastName.
The system stores phone numbers and email addresses as arrays of objects crm_multifield, so we create arrays PHONE and EMAIL using the values $sPhone and $sEmail.
-
In the
VALUEfields, we write$sPhoneand$sEmail. -
In the
VALUE_TYPEfields, we pass types, for example,HOME.
If the variables $sPhone and $sEmail have no values, we specify empty arrays.
Searching for Duplicate Leads
To find duplicate leads by phone and email, we use the method crm.duplicate.findbycomm twice. We need to pass the following data:
-
entity_type— object type. We passLEAD— lead. -
type— communication type. For the first call, we specifyPHONE, and for the second,EMAIL. -
PHONE— an array with the phone number$arPhoneobtained from the form.
Searching by phone, "type" => "PHONE".
if(!empty($sPhone)){
$arResultDuplicate = CRest::call('crm.duplicate.findbycomm', [
"entity_type" => "LEAD",
"type" => "PHONE",
"values" => array($sPhone)
]);
if(!empty($arResultDuplicate['result']['LEAD'])){
$arLeadDuplicate = array_merge($arLeadDuplicate, $arResultDuplicate['result']['LEAD']);
}
}
Searching for duplicates by email, "type" => "EMAIL".
if(!empty($sEmail)){
$arResultDuplicate = CRest::call('crm.duplicate.findbycomm', [
"entity_type" => "LEAD",
"type" => "EMAIL",
"values" => array($sEmail)
]);
if(!empty($arResultDuplicate['result']['LEAD'])){
$arLeadDuplicate = array_merge($arLeadDuplicate, $arResultDuplicate['result']['LEAD']);
}
}
The identifiers of found duplicates are merged into the array $arLeadDuplicate.
Processing Duplicates
If duplicates are found, we call the method crm.lead.list.
-
Apply a filter by ID and status
CONVERTED. -
Select fields:
ID,COMPANY_ID,CONTACT_ID. -
Save the result in the array
$arDuplicateLead. -
Fill the
COMPANY_IDandCONTACT_IDfields in the$arFieldsarray with values from$arDuplicateLead.
if(!empty($arLeadDuplicate)){
$arDuplicateLead = CRest::call('crm.lead.list', [
"filter" => [
'=ID' => $arLeadDuplicate,
'STATUS_ID' => 'CONVERTED'
],
"select" => ['ID', 'COMPANY_ID', 'CONTACT_ID']
]);
if(!empty($arDuplicateLead['result'])){
$sCompany = reset(array_diff(array_column($arDuplicateLead['result'], 'COMPANY_ID', 'ID'), ['']));
$sContact = reset(array_diff(array_column($arDuplicateLead['result'], 'CONTACT_ID', 'ID'), ['']));
if($sCompany > 0) $arFields['COMPANY_ID'] = $sCompany;
if($sContact > 0) $arFields['CONTACT_ID'] = $sContact;
}
}
Adding a New Lead
To add a lead, we use the method crm.lead.add. We pass the array $arFields.
Check which required fields are set for leads in your Bitrix24. All required fields must be passed to the method crm.lead.add.
$result = CRest::call('crm.lead.add', [
'fields' => $arFields
]);
If the lead is successfully created, the method will return its identifier. If you receive an error, review the possible error descriptions in the documentation for the method crm.lead.add.
{
"result": 3289,
}
Complete Example of the Handler Code
<?php
$sName = htmlspecialchars($_POST["NAME"]);
$sLastName = htmlspecialchars($_POST["LAST_NAME"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$sEmail = htmlspecialchars($_POST["EMAIL"]);
$arFields = [
'TITLE' => 'From the site: ' . implode(' ', [$sName, $sLastName]),
'NAME' => (!empty($sName)) ? $sName : 'Empty name',
'LAST_NAME' => $sLastName,
'PHONE' => (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'HOME')) : array(),
'EMAIL' => (!empty($sEmail)) ? array(array('VALUE' => $sEmail, 'VALUE_TYPE' => 'HOME')) : array()
];
$arLeadDuplicate = [];
if(!empty($sPhone)){ // searching for duplicates by phone
$arResultDuplicate = CRest::call('crm.duplicate.findbycomm', [
"entity_type" => "LEAD",
"type" => "PHONE",
"values" => array($sPhone)
]);
if(!empty($arResultDuplicate['result']['LEAD'])){
$arLeadDuplicate = array_merge($arLeadDuplicate, $arResultDuplicate['result']['LEAD']);
}
}
if(!empty($sEmail)) { // searching for duplicates by email
$arResultDuplicate = CRest::call('crm.duplicate.findbycomm', [
"entity_type" => "LEAD",
"type" => "EMAIL",
"values" => [$sEmail]
]);
if(!empty($arResultDuplicate['result']['LEAD'])) {
$arLeadDuplicate = array_merge($arLeadDuplicate, $arResultDuplicate['result']['LEAD']);
}
}
if(!empty($arLeadDuplicate)){ // retrieving the duplicate lead with selected fields for related contact and company
$arDuplicateLead = CRest::call('crm.lead.list', [
"filter" => [
'=ID' => $arLeadDuplicate,
'STATUS_ID' => 'CONVERTED',
],
'select' => [
'ID', 'COMPANY_ID', 'CONTACT_ID'
]
]);
if(!empty($arDuplicateLead['result'])){
$sCompany = reset(array_diff(array_column($arDuplicateLead['result'], 'COMPANY_ID', 'ID'), ['']));
$sContact = reset(array_diff(array_column($arDuplicateLead['result'], 'CONTACT_ID', 'ID'), ['']));
if($sCompany > 0)
$arFields['COMPANY_ID'] = $sCompany;
if($sContact > 0)
$arFields['CONTACT_ID'] = $sContact;
}
}
$result = CRest::call('crm.lead.add', // creating a duplicate lead
[
'fields' => $arFields
]
);
if(!empty($result['result'])){
echo json_encode(['message' => 'Lead added']);
}elseif(!empty($result['error_description'])){
echo json_encode(['message' => 'Lead not added: '.$result['error_description']]);
}else{
echo json_encode(['message' => 'Lead not added']);
}
?>
Continue Learning
- Get leads, contacts, and companies with matching data crm.duplicate.findbycomm
- Get a List of Leads crm.lead.list
- Create a New Lead crm.lead.add