Integrating 1C-Bitrix with 1C:Medicine
1C:Medicine is a family of configurations for medical organisations: "Hospital", "Polyclinic", "Medical Laboratory". The configurations run on the 1C:Enterprise 8 platform and, unlike most other MIS systems, are well known to developers working within the 1C ecosystem. Integration with 1C-Bitrix is implemented via 1C HTTP services, COM objects, or exchange through an intermediate database.
Integration Methods
1C HTTP services (preferred). An HTTP service is created in the 1C:Medicine configuration that accepts REST requests from 1C-Bitrix. This is the most modern and manageable approach.
COM object (Windows server only). Direct invocation of 1C from PHP via COM — fast for low volumes, but ties you to Windows and creates concurrency issues.
Intermediate database. 1C:Medicine writes data (schedules, test results) to a shared PostgreSQL/MySQL database; 1C-Bitrix reads from there. An asynchronous approach that requires no changes to 1C if it already supports data export.
HTTP services are treated as the primary method.
HTTP Service in 1C:Medicine
An HTTP service is created in the 1C Configurator (General → HTTP Services):
Name: MedicalAPI
RootURL: /medapi
Version: 1.0.0
Methods (URL templates):
-
GET /medapi/doctors— list of physicians -
GET /medapi/schedule/{doctorId}/{date}— physician schedule -
POST /medapi/appointments— create appointment -
DELETE /medapi/appointments/{id}— cancel appointment
Method handler in 1C (built-in language):
Function GetSchedule(Request)
Response = New HTTPServiceResponse(200);
Response.Headers["Content-Type"] = "application/json; charset=utf-8";
DoctorId = Request.URLParameters["doctorId"];
SessionDate = Date(Request.URLParameters["date"]);
// Query the schedule register
Query = New Query();
Query.Text = "
|SELECT
| DoctorSchedule.StartTime,
| DoctorSchedule.EndTime,
| DoctorSchedule.SlotStatus,
| DoctorSchedule.ClinicRoom
|FROM
| InformationRegister.DoctorSchedule AS DoctorSchedule
|WHERE
| DoctorSchedule.Doctor.UniqueIdentifier = &DoctorId
| AND DoctorSchedule.Date = &Date
| AND DoctorSchedule.SlotStatus = Enum.SlotStatuses.Free";
Query.SetParameter("DoctorId", DoctorId);
Query.SetParameter("Date", SessionDate);
Result = Query.Execute().Choose();
Slots = New Array();
While Result.Next() Do
SlotData = New Structure("start,end,cabinet");
SlotData.start = Format(Result.StartTime, "DF=HH:mm");
SlotData.end = Format(Result.EndTime, "DF=HH:mm");
SlotData.cabinet = Result.ClinicRoom.Number;
Slots.Add(SlotData);
EndDo;
Response.SetBodyFromString(WriteJSON(Slots));
Return Response;
EndFunction
PHP Client for the 1C:Medicine HTTP Service
class OneCMedicinaClient
{
private string $baseUrl; // http://1c-server:8080/medicine/hs/medapi
private string $username;
private string $password;
public function getSchedule(string $doctorGuid, string $date): array
{
return $this->request('GET', "/schedule/{$doctorGuid}/{$date}");
}
public function createAppointment(array $data): array
{
return $this->request('POST', '/appointments', [
'slotDate' => $data['date'],
'slotTime' => $data['time'],
'doctorGuid' => $data['doctor_guid'],
'patient' => [
'lastName' => $data['last_name'],
'firstName' => $data['first_name'],
'middleName' => $data['middle_name'] ?? '',
'birthDate' => $data['birth_date'],
'phone' => $data['phone'],
'email' => $data['email'],
'snils' => $data['snils'] ?? '',
],
'serviceCode' => $data['service_code'] ?? '',
]);
}
private function request(string $method, string $path, array $body = []): array
{
$ch = curl_init($this->baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_USERPWD => "{$this->username}:{$this->password}", // Basic Auth in 1C
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
CURLOPT_POSTFIELDS => $body ? json_encode($body, JSON_UNESCAPED_UNICODE) : null,
CURLOPT_TIMEOUT => 10,
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \RuntimeException("1C:Medicine API error {$httpCode}");
}
return json_decode($json, true) ?? [];
}
}
Important: 1C:Enterprise does not natively support parallel requests to a single infobase without client connection licences. Under high load, a connection pool or caching on the 1C-Bitrix side is required.
Directory Synchronisation
The list of physicians, their specialisations, and rooms is synchronised from 1C into a 1C-Bitrix infoblock:
class OneCMedicDoctorSync
{
public function syncDoctors(): void
{
$doctors = $this->onecClient->request('GET', '/doctors');
foreach ($doctors as $doctor) {
$existingId = $this->findDoctorByGuid($doctor['guid']);
$fields = [
'NAME' => $doctor['fullName'],
'ACTIVE' => $doctor['active'] ? 'Y' : 'N',
'IBLOCK_ID' => DOCTORS_IBLOCK_ID,
'IBLOCK_SECTION_ID' => $this->getSpecializationSectionId($doctor['specialization']),
];
$props = [
'DOCTOR_GUID' => $doctor['guid'],
'SPECIALIZATION' => $doctor['specialization'],
'CABINET_NUMBER' => $doctor['cabinet'],
'EXPERIENCE_YEARS' => $doctor['experienceYears'],
'ACADEMIC_DEGREE' => $doctor['academicDegree'],
];
if ($existingId) {
$el = new \CIBlockElement();
$el->Update($existingId, $fields);
\CIBlockElement::SetPropertyValuesEx($existingId, DOCTORS_IBLOCK_ID, $props);
} else {
$el = new \CIBlockElement();
$newId = $el->Add(array_merge($fields, ['PROPERTY_VALUES' => $props]));
}
}
}
}
Scope of Work
- Analysis of the specific 1C:Medicine configuration and available registers
- Development of an HTTP service on the 1C side (jointly with a 1C developer)
- PHP client for the HTTP service with caching
- Physician directory synchronisation into the 1C-Bitrix infoblock
- Online appointment component with form
- Patient notifications after booking
Timeline: 6–10 weeks with a 1C developer in the team. HTTP service development on the 1C side — 2–4 weeks; PHP part — 3–6 weeks.







