Developing a Bitrix24 Contract Template System
Preparing a contract manually takes 30–60 minutes of copy-pasting data from CRM into Word, editing details, re-saving, and forwarding. Multiplied by 50 contracts per month, that is a full-time employee's workload. A contract template system in Bitrix24 reduces contract generation to 2 minutes.
Built-in Functionality: CRM Document Generator
Bitrix24 includes a built-in CRM → Documents module for generating documents from templates. Templates are created in DOCX format with variable placeholders that are replaced with data from the CRM card.
Built-in variables for a deal:
{=Document.TITLE} - Deal name
{=Document.OPPORTUNITY} - Deal amount
{=Document.CONTACT.NAME} - Contact name
{=Document.COMPANY.TITLE} - Company name
{=Document.UF_CRM_XXXXX} - Custom field
Limitations of the built-in module: no conditional formatting (different text depending on the contract type), no loops over line items, no complex calculations.
Extended System via an External Generator
For serious contract requirements (multiple types, conditional blocks, specifications), an external generator is needed — a PHP script or service that produces DOCX/PDF from a template with extended logic.
Stack for DOCX generation: PhpWord (open-source library) + a custom template preprocessor.
use PhpOffice\PhpWord\TemplateProcessor;
function generateContract($dealId, $templatePath) {
// Retrieve deal data from Bitrix24
$deal = CRest::call('crm.deal.get', ['id' => $dealId])['result'];
$contact = CRest::call('crm.contact.get',
['id' => $deal['CONTACT_ID']])['result'];
$company = CRest::call('crm.company.get',
['id' => $deal['COMPANY_ID']])['result'];
$template = new TemplateProcessor($templatePath);
// Substitute data
$template->setValue('CONTRACT_NUMBER', generateContractNumber($dealId));
$template->setValue('CONTRACT_DATE', date('d.m.Y'));
$template->setValue('CLIENT_NAME', $company['TITLE']);
$template->setValue('CLIENT_INN', $company['UF_CRM_INN']);
$template->setValue('AMOUNT', number_format($deal['OPPORTUNITY'], 2, '.', ' '));
$template->setValue('AMOUNT_WORDS', amountToWords($deal['OPPORTUNITY']));
// Conditional block: VAT or VAT-exempt
if ($deal['UF_CRM_VAT'] === 'Y') {
$template->setValue('VAT_BLOCK', 'including VAT 20%: ' .
number_format($deal['OPPORTUNITY'] * 0.2, 2));
} else {
$template->setValue('VAT_BLOCK', 'VAT not applicable');
}
$outputPath = '/tmp/contract_' . $dealId . '.docx';
$template->saveAs($outputPath);
return $outputPath;
}
Integration with the CRM Card
A "Generate contract" button in the deal card — via a placement application:
// Bitrix24 JS SDK in placement CRM_DEAL_TOOLBAR
BX24.callMethod('crm.deal.get', {id: currentDealId}, function(result) {
const deal = result.data();
// Call your generation endpoint
fetch('/api/generate-contract', {
method: 'POST',
body: JSON.stringify({dealId: deal.ID, templateId: selectedTemplate})
})
.then(r => r.blob())
.then(blob => {
// Save the generated document back to the deal
uploadFileToDeal(blob, deal.ID);
});
});
After generation, the file is attached to the deal via crm.deal.update with the UF_CRM_FILES field, and a "Contract generated" activity is created simultaneously in the timeline.
Electronic Signature and Approval
The next step after generation is the approval and signing process. Two options:
Internal approval via a business process: legal → CFO → CEO. Triggered automatically when the contract status changes in CRM.
Electronic signature via integration with SBIS, Kontur.Sign, or DocuSign. The contract is sent to the client for signing, and the status (signed/rejected) is synchronized back to CRM.
The template system pays for itself in 2–3 months purely through time savings. Additionally, it eliminates manual data entry errors — which carry reputational risk when contracts are signed with incorrect details.







