Add a Deal and Company with Requisites
Scope:
crmWho can execute the method: users with administrative access to the CRM section
If you are developing integrations for Bitrix24 using AI tools (Codex, Claude Code, Cursor), connect the MCP server so that the assistant uses the official REST documentation.
Using a web form, you can automatically add new deals and companies with requisites to Bitrix24. When a client fills out the form, the data is sent to a handler. The handler script creates objects in the CRM via the API.
The setup consists of two stages.
-
Prepare the fields and place the web form on the page.
-
Create a handler file that sequentially calls the methods crm.company.add, crm.requisite.add, crm.address.add, and crm.deal.add.
1. Create the Web Form
To generate the fields, we use two methods:
-
crm.address.fields — retrieves the list of address fields. The result is saved in the array
$arAddressFields. -
crm.requisite.preset.list — retrieves the list of requisites templates by fields
IDandNAME. The result is saved in the array$arRequisiteType.
How to Use Examples in Documentation
$arAddressFields = CRest::call('crm.address.fields', []);
$arRequisiteType = CRest::call('crm.requisite.preset.list',
[
'select' => [
"ID", "NAME"
]
]
);
From the $arAddressFields array, we remove unnecessary address fields so that they do not appear in the form.
unset($arAddressFields['result']['TYPE_ID']);
unset($arAddressFields['result']['ENTITY_TYPE_ID']);
unset($arAddressFields['result']['ENTITY_ID']);
unset($arAddressFields['result']['COUNTRY_CODE']);
unset($arAddressFields['result']['ANCHOR_TYPE_ID']);
unset($arAddressFields['result']['ANCHOR_ID']);
We create an HTML form with the fields:
-
REQ_TYPE— a dropdown list with requisites templates from the$arRequisiteTypearray. This is a required field. -
TITLE— the name of the company. This is a required field. -
INN— the company's INN. -
PHONE— the phone number. -
ADDRESS— fields for the address are created dynamically from$arAddressFields. If a field is required, therequiredattribute is added.
The form collects data into a string and sends it via POST to the form.php file.
<form id="form_to_crm">
<select name="REQ_TYPE" required>
<option value="" disabled selected>Select</option>
<?php foreach($arRequisiteType as $id => $name): ?>
<option value="<?=$id?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<input type="text" name="TITLE" placeholder="Org name" required>
<input type="text" name="INN" placeholder="INN">
<input type="text" name="PHONE" placeholder="Phone">
<?php if(is_array($arAddressFields['result'])): ?>
<?php foreach($arAddressFields['result'] as $key => $arField): ?>
<input type="text" name="ADDRESS[<?=$key?>]" placeholder="<?=$arField['title']?>" <?=($arField['isRequired']) ? 'required' : ''; ?>>
<?php endforeach; ?>
<?php endif; ?>
<input type="submit" value="Submit">
</form>
Full Code Example
<?php
require_once('crest.php');
$arAddressFields = CRest::call('crm.address.fields', []);
$arRequisiteType = CRest::call('crm.requisite.preset.list',
[
'select' => [
"ID", "NAME"
]
]
);
if(!empty($arRequisiteType['result'])):
$arRequisiteType = array_column($arRequisiteType['result'], 'NAME', 'ID');
//unset system address fields
unset($arAddressFields['result']['TYPE_ID']);
unset($arAddressFields['result']['ENTITY_TYPE_ID']);
unset($arAddressFields['result']['ENTITY_ID']);
//unset uninteresting address fields
unset($arAddressFields['result']['COUNTRY_CODE']);
unset($arAddressFields['result']['ANCHOR_TYPE_ID']);
unset($arAddressFields['result']['ANCHOR_ID']);
?>
<form id="form_to_crm">
<select name="REQ_TYPE" required>
<option value="" disabled selected>Select</option>
<?php foreach($arRequisiteType as $id => $name): ?>
<option value="<?=$id?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<input type="text" name="TITLE" placeholder="Org name" required>
<input type="text" name="INN" placeholder="INN">
<input type="text" name="PHONE" placeholder="Phone">
<?php if(is_array($arAddressFields['result'])): ?>
<?php foreach($arAddressFields['result'] as $key => $arField): ?>
<input type="text" name="ADDRESS[<?=$key?>]" placeholder="<?=$arField['title']?>" <?=($arField['isRequired']) ? 'required' : ''; ?>>
<?php endforeach; ?>
<?php endif; ?>
<input type="submit" value="Submit">
</form>
<?php else: ?>
No requisite types.
<?php endif; ?>
<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>
2. Create the Form Handler
Create a file form.php that will process the data and save it in the CRM.
Retrieve Data
Retrieve and process the data from the form.
$iRequisitePresetID = intval($_POST["REQ_TYPE"]);
$sTitle = htmlspecialchars($_POST["TITLE"]);
$sINN = htmlspecialchars($_POST["INN"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$arAddress = [];
foreach ($_POST["ADDRESS"] as $key => $val) {
$arAddress[$key] = htmlspecialchars($val);
}
-
$iRequisitePresetID— converts the requisites template identifierREQ_TYPEto an integer. -
$sTitle,$sINN,$sPhone— safely processes data fromTITLE,INN,PHONEto avoid XSS attacks. -
$arAddress— stores data from the array with address fieldsADDRESS.
Prepare Data
Add two required system fields to the $arAddress array.
-
TYPE_ID— address type. We will specify1— actual address. The list of address types can be retrieved using the method crm.enum.addresstype. -
ENTITY_TYPE_ID— CRM object type identifier. We pass8— requisites. The complete list of object types can be retrieved using the method crm.enum.ownertype.
$arAddress['TYPE_ID'] = 1;
$arAddress['ENTITY_TYPE_ID'] = 8;
The system stores the phone as an array of objects crm_multifield, so the value of $sPhone needs to be formatted as an array:
-
in the first element
VALUE, we write$sPhone, -
in the second element
VALUE_TYPE, we pass, for example,WORK.
If the variable $sPhone has no value, we specify an empty array.
$arPhone = (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'WORK')) : array();
Add Company
To add a company, we use the method crm.company.add. We need to pass the following data:
-
TITLE— the name of the company. We pass$sTitle, which we obtained from the form. -
COMPANY_TYPE— the type of company. We will specifyCUSTOMER— client. The list of types can be obtained using the method crm.status.list with the filter'filter'=>['ENTITY_ID'=>'COMPANY_TYPE']. -
PHONE— an array with the phone$arPhone, which we obtained from the form.
Check which required fields are set for companies in your Bitrix24. All required fields must be passed to the method crm.company.add.
$result = CRest::call(
'crm.company.add',
[
'fields' => [
'TITLE' => $sTitle,
'COMPANY_TYPE' => 'CUSTOMER',
'PHONE' => $arPhone,
]
]
);
If the company is successfully created, the method will return its identifier in $result. If you receive an error, review the possible error descriptions in the documentation for the method crm.company.add.
Add Requisites
To add requisites, we use the method crm.requisite.add. We need to pass the following data:
-
ENTITY_TYPE_ID— CRM object type identifier. We pass4— company. The complete list of object types can be retrieved using the method crm.enum.ownertype. -
ENTITY_ID— the company identifier. We pass$result, which we obtained when creating the company. -
PRESET_ID— the requisites template identifier. We specify$iRequisitePresetID, which we obtained from the form. -
NAME— the name of the requisite. We pass$sTitle, which we obtained from the form. -
RQ_INN— the company's INN. We pass$sINN, which we obtained from the form. -
ACTIVE— the active flag, we will specifyY.
$resultRequisite = CRest::call(
'crm.requisite.add',
[
'fields' => [
'ENTITY_TYPE_ID' => 4,
'ENTITY_ID' => $result['result'],
'PRESET_ID' => $iRequisitePresetID,
'ACTIVE' => 'Y',
'NAME' => $sTitle,
'RQ_INN' => $sINN,
]
]
);
If the requisites are successfully added, the method will return the record identifier in $resultRequisite. If you receive an error, review the possible error descriptions in the documentation for the method crm.requisite.add.
Add Address to Requisites
-
Add the
ENTITY_IDfield to the$arAddressarray — the requisites identifier. We pass$resultRequisite, which we obtained when creating the requisites.$arAddress['ENTITY_ID'] = $resultRequisite['result']; -
Use the method crm.address.add. We need to pass the
$arAddressarray.$resultAddress = CRest::call( 'crm.address.add', [ 'fields' => $arAddress ] );
The method returns one of the following values in the $resultAddress variable:
-
true— address added, -
false— address not added.
Add Deal
We create an array $arDealFields with data for the deal.
-
TITLE— the name of the deal. We will specify the name of the company$sTitle, which was obtained from the form, -
COMPANY_ID— the identifier of the company associated with the deal. We pass$result, which we obtained when creating the company, -
REQUISITE_ID— the requisites identifier. If the requisite is created, we pass$resultRequisite.
$arDealFields = [
'TITLE' => $sTitle,
'COMPANY_ID' => $result['result']
];
if(!empty($resultRequisite['result'])){
$arDealFields['REQUISITE_ID'] = $resultRequisite['result'];
}
To add a deal, we use the method crm.deal.add. We pass the $arDealFields array.
$resultDeal = CRest::call(
'crm.deal.add',
[
'fields' => $arDealFields
]
);
If the deal 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.deal.add.
{
"result": 1789,
}
Full Example of the Handler Code
<?php
require_once('crest.php');
$iRequisitePresetID = intval($_POST["REQ_TYPE"]);
$sTitle = htmlspecialchars($_POST["TITLE"]);
$sINN = htmlspecialchars($_POST["INN"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$arAddress = [];
foreach($_POST["ADDRESS"] as $key => $val){
$arAddress[$key] = htmlspecialchars($val);
}
$arAddress['TYPE_ID'] = 1; // 1 is actual address in CRest::call('crm.enum.addresstype');
$arAddress['ENTITY_TYPE_ID'] = 8; // 8 - is requisite in CRest::call('crm.enum.ownertype');
$arPhone = (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'WORK')) : array();
$result = CRest::call(
'crm.company.add',
[
'fields' => [
'TITLE' => $sTitle,
'COMPANY_TYPE' => 'CUSTOMER', // is Client in CRest::call('crm.status.list',['filter'=>['ENTITY_ID'=>'COMPANY_TYPE']])
'PHONE' => $arPhone,
]
]
);
if(!empty($result['result'])){
$resultRequisite = CRest::call(
'crm.requisite.add',
[
'fields' => [
'ENTITY_TYPE_ID' => 4, // 4 - is company in CRest::call('crm.enum.ownertype');
'ENTITY_ID' => $result['result'], // company id
'PRESET_ID' => $iRequisitePresetID,
'ACTIVE' => 'Y',
'NAME' => $sTitle,
'RQ_INN' => $sINN,
]
]
);
$arDealFields = [
'TITLE' => $sTitle,
'COMPANY_ID' => $result['result']
];
if(!empty($resultRequisite['result'])){
$arDealFields['REQUISITE_ID'] = $resultRequisite['result']; // add requisite to deal is analogue "crm.requisite.link.list"
$arAddress['ENTITY_ID'] = $resultRequisite['result']; // id requisite
$resultAddress = CRest::call(
'crm.address.add',
[
'fields' => $arAddress
]
);
}
$resultDeal = CRest::call(
'crm.deal.add',
[
'fields' => $arDealFields
]
);
echo json_encode(['message' => 'add']);
}elseif(!empty($result['error_description'])){
echo json_encode(['message' => 'not added: '.$result['error_description']]);
}else{
echo json_encode(['message' => 'not added']);
}
?>
Continue Learning
- Create a New Company crm.company.add
- Add Requisite crm.requisite.add
- Add Address crm.address.add
- Create a New Deal crm.deal.add
- Get Description of Address Fields crm.address.fields
- Get a list of requisites templates by filter crm.requisite.preset.list
- Get Address Types crm.enum.addresstype
- Get CRM Object Types crm.enum.ownertype