Add a Deal and Company with Requisites

Scope: crm

Who 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.

  1. Prepare the fields and place the web form on the page.

  2. 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 ID and NAME. 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 $arRequisiteType array. 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, the required attribute 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 identifier REQ_TYPE to an integer.

  • $sTitle, $sINN, $sPhone — safely processes data from TITLE, INN, PHONE to avoid XSS attacks.

  • $arAddress — stores data from the array with address fields ADDRESS.

Prepare Data

Add two required system fields to the $arAddress array.

$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 specify CUSTOMER — 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_IDCRM object type identifier. We pass 4 — 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 specify Y.

$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

  1. Add the ENTITY_ID field to the $arAddress array — the requisites identifier. We pass $resultRequisite, which we obtained when creating the requisites.

    $arAddress['ENTITY_ID'] = $resultRequisite['result'];
            
  2. Use the method crm.address.add. We need to pass the $arAddress array.

    $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