When launching online booking in a medical center on 1C-Bitrix, one common issue arises: 1C:Medicina doesn't provide real-time data. Doctors manage schedules in 1C, but on the website it updates only after hours. Synchronization via file exchange or direct database queries to 1C leads to errors and delays. We solve this through HTTP services — a modern protocol that ensures seamless system interaction.
1C:Medicina is a family of configurations for medical organizations: "Hospital", "Polyclinic", "Medical Laboratory". These configurations run on the 1C:Enterprise 8 platform and, unlike most other MIS, are well-known to developers working in the 1C ecosystem. Our experience includes over 10 years of 1C-Bitrix integrations with MIS, with more than 50 projects implemented in medical institutions. The development cost depends on the complexity of the configuration and the number of synchronized directories, but a properly designed integration allows reducing a clinic's operational costs through booking automation.
Why HTTP Services are Better Than COM Object?
COM object — a direct call to 1C from PHP via new COM(...). It only works on a Windows server and scales poorly. With parallel requests (5+ patients simultaneously), lockups occur, resulting in a 3–5 times performance drop compared to HTTP services. HTTP services are not tied to the OS, support asynchronous processing, and caching on the Bitrix side. Intermediate database — an alternative if 1C already exports data to PostgreSQL/MySQL, but it does not provide bidirectional online exchange. HTTP services are the preferred option.
| Method | Speed | Reliability | Complexity |
|---|---|---|---|
| 1C HTTP services | High | High | Medium |
| COM object | Medium (degrades under load) | Low (lockups) | Low |
| Intermediate DB | Low (asynchronous) | High | High |
HTTP Service in 1C:Medicina
In the 1C configurator, an HTTP service is created (Common → HTTP Services):
Name: MedicalAPI
RootURL: /medapi
Version: 1.0.0
Methods (URL templates):
-
GET /medapi/doctors— list of doctors -
GET /medapi/schedule/{doctorId}/{date}— doctor's schedule -
POST /medapi/appointments— create an appointment -
DELETE /medapi/appointments/{id}— cancel an appointment
Handler method 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 to the schedule register
Query1C = New Query();
Query1C.Text = "
|SELECT
| DoctorSchedule.StartTime,
| DoctorSchedule.EndTime,
| DoctorSchedule.CellStatus,
| DoctorSchedule.ClinicRoom
|FROM
| AccumulationRegister.DoctorSchedule AS DoctorSchedule
|WHERE
| DoctorSchedule.Doctor.UniqueIdentifier = &DoctorID
| AND DoctorSchedule.Date = &Date
| AND DoctorSchedule.CellStatus = Enum.CellStatuses.Free";
Query1C.SetParameter("DoctorID", DoctorID);
Query1C.SetParameter("Date", SessionDate);
Result = Query1C.Execute().Select();
Slots = New Array();
While Result.Next() Loop
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);
EndLoop;
Response.SetBodyFromString(WriteJSON(Slots));
Return Response;
EndFunction
PHP Client for 1C:Medicina HTTP Service
class OneCMedicinaClient
{
private string $baseUrl; // http://1c-server:8080/medicina/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:Medicina API error {$httpCode}");
}
return json_decode($json, true) ?? [];
}
}
Important: 1C:Enterprise by default does not support parallel requests to a single infobase without client connection licenses. Under high load, a connection pool or caching on the Bitrix side is required.
How to Synchronize Directories Without Duplicates?
The list of doctors, their specializations, rooms — we sync from 1C to a Bitrix infoblock. The key parameter is the doctor's unique identifier (GUID) from 1C. It is stored in the infoblock property, and during re-synchronization we do not create duplicates but update existing elements. A typical mistake is losing the link between records when the identifier changes in 1C. We use the internal property DOCTYPE_GUID and a lookup logic based on it.
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]));
}
}
}
}
What Data is Synchronized Between 1C:Medicina and Bitrix?
| Data | Direction | Frequency |
|---|---|---|
| Doctors (name, specialization, room) | 1C → Bitrix | On event (change in 1C) |
| Schedule (time slots) | 1C → Bitrix | Less often: every 5-15 minutes |
| New patient appointment | Bitrix → 1C | Instant (online) |
| Appointment cancellation | Bitrix → 1C | Instant |
| Services and prices | 1C → Bitrix | Scheduled (once a day) |
What's Included in the Work
- Analysis of the specific 1C:Medicina configuration and available registers
- Development of the HTTP service on the 1C side (jointly with a 1C developer)
- PHP client for the HTTP service with caching (tagged caching)
- Synchronization of the doctor directory to the Bitrix infoblock
- Online booking component with a form (validation, slot selection)
- Patient notifications via SMS/email after booking
- Integration documentation and training
- 3 months of warranty support
Checklist of Typical Project Phases
- Audit of the 1C:Medicina configuration and data schema
- Design of the REST API (HTTP service)
- Development and testing of the HTTP service in 1C
- Creation of the PHP client and Bitrix components
- Integration testing (up to 2 weeks)
- Launch and support (3 months warranty)
Timeline: 6–10 weeks when a 1C developer is on the team. Development of the HTTP service on the 1C side takes 2–4 weeks, the PHP part takes 3–6 weeks. A properly designed integration saves budget on support and reduces administration costs. Get a preliminary assessment of your project — we will analyze the configuration and propose a solution. Contact us.







