Development of Custom Approval Processes in Bitrix24
Bitrix24's standard workflow builder handles simple linear routes. A contract for approval: lawyer → finance director → CEO. That works. But business is more complex: the contract amount determines who approves; lawyer on vacation—pass to deputy; multiple approvers simultaneously, need at least two "yes" votes; on rejection—automatic return to initiator with comment and iteration counter. That's where custom development begins.
When Standard Builder Isn't Enough
The native Bitrix24 workflow designer has limitations: complex conditional routes (more than 3–4 branches) become unreadable diagrams. Dynamic participants (approval list determined dynamically based on document data) require PHP code in "Execute Code" block. Integration with external systems (fetch from ERP, write result to 1C)—only via HTTP requests from the same block. Workflow versioning (old running instances follow old rules, new ones follow new)—doesn't exist.
Custom solutions are built on one of two foundations:
- Extended workflow in designer—add custom activity blocks implementing needed logic
- Smart processes in CRM—use as container for approvals with robots and triggers
- Fully custom application—proprietary approval system integrated with Bitrix24 via REST API
Custom Activity Blocks
Activity is a PHP class implementing \Bitrix\Bizproc\Activity\Base. It appears in workflow designer as standard block but contains arbitrary logic.
Custom activity structure:
class SendToErpActivity extends \Bitrix\Bizproc\Activity\Base
{
public function execute(\CBPActivity $activity): \CBPActivityExecutionStatus
{
$dealId = $activity->getDealId(); // get parameter from workflow
$erpClient = new ErpApiClient();
$result = $erpClient->createApprovalRequest($dealId);
if ($result->isSuccess()) {
$activity->setVariable('ERP_REQUEST_ID', $result->getId());
return \CBPActivityExecutionStatus::Closed;
}
// Error—can return Faulting for workflow handling
return \CBPActivityExecutionStatus::Faulting;
}
}
Block is registered in bitrix/activities/ or /local/activities/. After registration, appears in designer as standard element and supports parameter configuration via form.
Dynamic Participants
An approval list determined by document data—common request. For example: deal sum up to 500,000 rubles—approved by department head, 500,000 to 2,000,000—plus finance director, above that—plus CEO. And each division has its own matrix.
Implementation: "Determine Approvers" activity block calculates user list based on document data and authority matrix. Authority matrix stored in HL-block or separate database table. Result—user_id array passed to next "Approval" block as parameter.
// HL-block "Approval Authorities"
// Fields: DEPARTMENT_ID, AMOUNT_FROM, AMOUNT_TO, APPROVER_USER_ID, APPROVER_ROLE
$approvers = ApprovalMatrixTable::getList([
'filter' => [
'DEPARTMENT_ID' => $departmentId,
'<=AMOUNT_FROM' => $amount,
'>=AMOUNT_TO' => $amount,
],
]);
Substitutes and Delegation
Approver on vacation or business trip—process shouldn't hang. Two options:
Automatic delegation. Before sending task for approval, check user status (via user.get or custom profile field "substitutes"). If user absent—task goes to substitute.
Time-based delegation. If task not completed in X hours—also goes to substitute. Implemented via "Pause" block in workflow + condition: if task not completed when pause ends—transition via delegation branch.
Maintain substitution matrix in HL-block: USER_ID, SUBSTITUTE_USER_ID, DATE_FROM, DATE_TO. Activity block checks current substitute at execution time.
Parallel Approval with Threshold
Three approvers simultaneously, need two "yes" votes:
[Parallel Block]
├── Task: Approver 1
├── Task: Approver 2
└── Task: Approver 3
[Wait Block: 2 of 3 completed with "Approved" result]
[Condition: result?]
├── Yes → Next stage
└── No → Rejected
In standard designer, implemented via "Parallel Activity" + custom "Vote Aggregation" activity. Activity monitors answer accumulation in workflow variable and returns Closed only when threshold reached.
Approval History and Audit
Each approver action (approved, rejected, returned for revision) is logged:
- In document comment via
crm.timeline.comment.add - In custom history field (multiline text with append)
- In separate HL-block "Approval History" with fields: date, user, action, comment, document version
Last option preferred—enables reporting: average document cycles through approvals, which approver most often rejects, average approval time by document types.
Escalation and SLA
For each stage, set SLA (completion time). If deadline breached:
- Notification to approver ("You didn't respond to approval request, deadline passed")
- Notification to their manager ("Your subordinate didn't approve document on time")
- After second threshold—automatic default decision (auto-approval or escalate higher)
Implemented via Bitrix agents or scheduler in custom application.
Integration with External Systems in Process
On approval start and status change—notify external systems:
- 1C:EDO—on final approval, send document to electronic document management system
- ERP—on purchase agreement approval, create supplier order
- Email/Telegram—notify external party ("Your contract approved")
Development Stages
| Stage | Content | Timeline |
|---|---|---|
| Analysis | Route maps, authority matrix, SLA | 1 week |
| Custom activities | Blocks for specific logic | 1–2 weeks |
| Approver matrix | HL-block, participant determination logic | 3–5 days |
| Substitution and delegation | Substitution matrix, automation | 3–5 days |
| History and audit | Step-by-step logging | 3–5 days |
| Escalation and SLA | Agents, notifications | 3–5 days |
| Testing | All route branches, edge cases | 1 week |
A mature approval system isn't a configured workflow in designer, but a combination of custom blocks, routing rules, and audit database. Such systems live for years and require minimal intervention on business rule changes—just update the authority matrix.







