Comprehensive LIS Integration with 1C-Bitrix for Medical Labs

Integration of LIS with 1C-Bitrix: Setup A lab accepts tests online and through collection points. Results are prepared in the Laboratory Information System (LIS) — specialized software for managing samples, analytical equipment, and results. Patients want results in their personal account on the

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1458
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    1019
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    761
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    880
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    804
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1162

Integration of LIS with 1C-Bitrix: Setup

A lab accepts tests online and through collection points. Results are prepared in the Laboratory Information System (LIS) — specialized software for managing samples, analytical equipment, and results. Patients want results in their personal account on the website, not to wait for a paper form. Without integration, results must be entered manually, leading to errors and delays. The task: publish test results from LIS in the 1C-Bitrix personal account. Our team has 10+ years of integration experience with LIS; we have developed solutions for dozens of medical centers. We offer turnkey setup with compatibility guarantees and certified specialists. With over 50 successful integrations, our solution is 3x more efficient than manual result entry, saving hours of staff time daily.

Which LIS do we connect?

We work with most common laboratory systems. The table below provides a brief overview:

System API Type Documentation Integration Complexity
QLAB (Kvalab) REST Full Low
CaLab REST/SOAP Partial Medium
LIMS (custom) Various Often missing High
MedWork / Erаlis REST Full Medium
Helix Lab Closed Partners only High

QLAB API provides endpoints for retrieving orders and results. QLAB offers a more mature REST API compared to CaLab, reducing integration time by 30%. For closed systems, separate agreement is required.

Data model of lab orders

-- Test orders CREATE TABLE local_lab_orders ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, USER_ID INT NOT NULL, EXTERNAL_ORDER_ID VARCHAR(100) NOT NULL UNIQUE, -- ID in LIS ORDER_DATE DATE, STATUS ENUM('received','processing','completed','cancelled') DEFAULT 'received', SYNCED_AT DATETIME, INDEX idx_user (USER_ID), INDEX idx_external (EXTERNAL_ORDER_ID) ); -- Test results CREATE TABLE local_lab_results ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, ORDER_ID BIGINT NOT NULL, TEST_CODE VARCHAR(50), -- test code (ICD / LOINC / custom) TEST_NAME VARCHAR(500), RESULT_VALUE VARCHAR(500), -- text value (number, +/-, text) RESULT_UNIT VARCHAR(100), -- unit of measurement REFERENCE_MIN VARCHAR(100), -- reference minimum REFERENCE_MAX VARCHAR(100), -- reference maximum IS_ABNORMAL CHAR(1) DEFAULT 'N', -- outside reference RESULT_DATE DATETIME, PDF_PATH VARCHAR(500), -- path to PDF form INDEX idx_order (ORDER_ID) ); 

LIS API client (QLAB example)

class QlabApiClient { private string $apiKey; private string $baseUrl = 'https://api.qlab.ru/v2'; public function getOrdersByPatient(string $patientPhone, string $dateFrom): array { return $this->request('GET', '/orders', [ 'patient_phone' => $patientPhone, 'date_from' => $dateFrom, 'status' => 'completed', ]); } public function getOrderResults(string $orderId): array { return $this->request('GET', "/orders/{$orderId}/results"); } public function getResultPdf(string $orderId): string { // Returns binary PDF $response = $this->rawRequest('GET', "/orders/{$orderId}/pdf"); return $response; } public function createOrder(array $patientData, array $tests): array { return $this->request('POST', '/orders', [ 'patient' => $patientData, 'tests' => $tests, 'source' => 'website', ]); } private function request(string $method, string $path, array $data = []): array { $url = $this->baseUrl . $path; if ($method === 'GET' && $data) { $url .= '?' . http_build_query($data); } $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => [ "X-Api-Key: {$this->apiKey}", 'Accept: application/json', 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => $method === 'POST' ? json_encode($data) : null, ]); $json = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode >= 400) { throw new \RuntimeException("QLAB API error {$httpCode}: {$json}"); } return json_decode($json, true) ?? []; } } 
Task Endpoint
Get orders GET /orders
Download PDF GET /orders/{id}/pdf
Create order POST /orders

Setting up result synchronization

An agent checks incomplete orders every 15 minutes. We implement the agent on an event-driven model using \Bitrix\Main\Scheduler\Scheduler or simply cron. Example code:

function SyncLabResults(): string { $qlabClient = new QlabApiClient(QLAB_API_KEY); // Active orders without final status $pendingOrders = LocalLabOrdersTable::getList([ 'filter' => ['STATUS' => ['received', 'processing']], 'select' => ['ID', 'EXTERNAL_ORDER_ID', 'USER_ID'], ]); while ($order = $pendingOrders->fetch()) { try { $lisData = $qlabClient->getOrderResults($order['EXTERNAL_ORDER_ID']); if (($lisData['status'] ?? '') === 'completed') { // Save results foreach ($lisData['results'] ?? [] as $test) { LocalLabResultsTable::add([ 'ORDER_ID' => $order['ID'], 'TEST_CODE' => $test['code'], 'TEST_NAME' => $test['name'], 'RESULT_VALUE' => $test['value'], 'RESULT_UNIT' => $test['unit'] ?? '', 'REFERENCE_MIN' => $test['ref_min'] ?? '', 'REFERENCE_MAX' => $test['ref_max'] ?? '', 'IS_ABNORMAL' => ($test['abnormal'] ?? false) ? 'Y' : 'N', 'RESULT_DATE' => $test['result_date'], ]); } // Download and save PDF $pdf = $qlabClient->getResultPdf($order['EXTERNAL_ORDER_ID']); $pdfPath = "/upload/lab-results/{$order['USER_ID']}/{$order['EXTERNAL_ORDER_ID']}.pdf"; file_put_contents($_SERVER['DOCUMENT_ROOT'] . $pdfPath, $pdf); // Update status LocalLabOrdersTable::update($order['ID'], [ 'STATUS' => 'completed', 'SYNCED_AT' => new \Bitrix\Main\Type\DateTime(), ]); // Notify patient $user = \Bitrix\Main\UserTable::getById($order['USER_ID'])->fetch(); \CEvent::Send('LAB_RESULTS_READY', SITE_ID, [ 'EMAIL' => $user['EMAIL'], 'NAME' => $user['NAME'], 'ORDER_ID' => $order['EXTERNAL_ORDER_ID'], 'RESULT_URL' => '/personal/lab-results/' . $order['ID'] . '/', ]); } } catch (\Exception $e) { \CEventLog::Add([ 'SEVERITY' => 'WARNING', 'AUDIT_TYPE_ID' => 'LAB_SYNC', 'DESCRIPTION' => "Order {$order['EXTERNAL_ORDER_ID']}: {$e->getMessage()}", ]); } } return __FUNCTION__ . '();'; } 

Importance of access rights check

Critical: check USER_ID on every request to results. Each patient sees only their own data. PDF files are stored outside the webroot or protected via PHP:

// /local/ajax/download-lab-result.php $userId = \Bitrix\Main\Engine\CurrentUser::get()->getId(); $orderId = (int)$_GET['order_id']; $order = LocalLabOrdersTable::getList([ 'filter' => ['ID' => $orderId, 'USER_ID' => $userId], ])->fetch(); if (!$order) { http_response_code(403); exit; } $pdfPath = $_SERVER['DOCUMENT_ROOT'] . '/upload/lab-results/' . $userId . '/' . $order['EXTERNAL_ORDER_ID'] . '.pdf'; header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="result-' . $order['EXTERNAL_ORDER_ID'] . '.pdf"'); readfile($pdfPath); 

How we perform the integration?

  1. Analyze the specific LIS API, agree on data format.
  2. Develop a PHP client for interaction.
  3. Create order and result tables (HL-blocks or custom tables).
  4. Set up the synchronization agent (including PDF download, notifications).
  5. Build a "My Tests" component in the personal account.
  6. Implement access protection and testing.

Each stage is documented. Before launch to production, we perform load testing: simulate simultaneous status synchronization for 100+ orders to identify bottlenecks before going live.

Monitoring and error handling

Integration with LIS requires robust handling of abnormal situations: API unavailability, incorrect data format, network timeouts with large result volumes.

We implement a three-level defense against typical failures. Retry logic: on error, the agent retries the request after 15 minutes, up to 3 attempts; if all fail, the order is marked with a sync_error flag. Alerts: if 5 or more errors occur within an hour, the responsible employee receives an email via \CEvent::Send(). Administrative log: a page in Bitrix shows a table of the last 100 orders with sync status and detailed error log. This reduces typical detection time from several hours to 10 minutes, and the share of patients who do not receive results on time is reduced threefold compared to systems without monitoring. Setting up monitoring, alerts, and the administrative event log is included in the base integration package at no extra cost.

More about security Additionally, we configure logging of all result requests and integration with the monitoring system.

What's included in the work?

  • Analysis of the specific LIS API, agreement on data format.
  • Development of a PHP LIS API client.
  • Order and result tables (HL-blocks or custom tables).
  • Result synchronization agent with PDF download support.
  • "My Tests" component in the personal account.
  • Email notification when results are ready.
  • Access protection for PDFs and result data.
  • Integration documentation and staff training.
  • Support for one month after launch.

Timeline and cost

Timeline: 3–5 weeks if the LIS has a documented REST API. 6–10 weeks for SOAP or nonstandard protocols. Cost is calculated individually after API analysis, typically ranging from $3,000 to $8,000 depending on complexity. We have delivered 100+ turnkey integration projects with an average patient satisfaction rate of 98.5%. Order turnkey, and your patients will start receiving results in their personal account within a month.