Integration of 1C-Bitrix with Route Optimization Services
Route optimization services — specialized APIs that accept a list of delivery points and return the optimal order of visits. Popular ones: Yandex.Routing, Route4Me, Routific, OptimoRoute, Google OR-Tools (self-hosted). Integration with Bitrix — a two-way pipeline: order data goes to optimizer, ready routes come back.
Choosing an optimization service
| Service | Features | Pricing model |
|---|---|---|
| Yandex.Routing | Russian infrastructure, good geocoding database | Requests + courier depot |
| Route4Me | Flexible API, time window support, multi-depot | Subscription |
| Routific | Simple API, suitable for small fleet | Subscription from 5 vehicles |
| OptimoRoute | Priority support, driver competencies | Subscription |
| OR-Tools | Free, self-hosted, requires Python server | Your servers |
Integration architecture
The workflow looks like this:
- Morning agent collects today's orders with "To deliver" status from
b_sale_order - Forms list of points with addresses, coordinates and time windows
- Sends API request to optimizer
- Saves routes to
bl_delivery_routes - Assigns drivers through CRM or manually
- On delivery completion, webhook from optimizer updates order statuses
Common interface for working with optimizers
Implement adapter pattern — one interface, multiple implementations:
interface RouteOptimizerInterface
{
public function optimize(array $depot, array $vehicles, array $orders): array;
}
class YandexRouteOptimizer implements RouteOptimizerInterface
{
public function optimize(array $depot, array $vehicles, array $orders): array
{
$payload = [
'depot' => $depot,
'vehicles' => $vehicles,
'orders' => array_map(fn($o) => [
'id' => (string)$o['order_id'],
'point' => ['lat' => $o['lat'], 'lon' => $o['lon']],
'time_window' => [$o['time_from'], $o['time_to']],
'service_duration' => 300, // 5 minutes per point
], $orders),
];
$http = new \Bitrix\Main\Web\HttpClient();
$http->setHeader('Content-Type', 'application/json');
$http->setHeader('X-Ya-Courier-Request-Id', uniqid());
$response = $http->post(
'https://courier.yandex.ru/api/v1/companies/' . $this->companyId . '/routes',
json_encode($payload)
);
return json_decode($response, true);
}
}
class Route4MeOptimizer implements RouteOptimizerInterface
{
public function optimize(array $depot, array $vehicles, array $orders): array
{
// Route4Me-specific logic
}
}
Concrete implementation is selected via factory method, configured in b_option.
Transforming order data
Key point — correct transformation of Bitrix data into optimizer API format. Address must be geocoded to coordinates (if not done at order), time windows — converted to optimizer format:
function buildOrderPoint(\Bitrix\Sale\Order $order): array
{
$props = $order->getPropertyCollection();
return [
'order_id' => $order->getId(),
'lat' => (float)$props->getItemByOrderPropertyCode('LAT')?->getValue(),
'lon' => (float)$props->getItemByOrderPropertyCode('LON')?->getValue(),
'time_from' => $this->toUnix($props->getItemByOrderPropertyCode('DELIVERY_TIME_FROM')?->getValue()),
'time_to' => $this->toUnix($props->getItemByOrderPropertyCode('DELIVERY_TIME_TO')?->getValue()),
'weight_kg' => $this->getBasketWeight($order->getBasket()),
'volume_m3' => $this->getBasketVolume($order->getBasket()),
'priority' => (int)$props->getItemByOrderPropertyCode('DELIVERY_PRIORITY')?->getValue(),
];
}
Saving and displaying routes
Structure of bl_delivery_routes table:
route_id — ID from optimizer
route_date — delivery date
vehicle_id — vehicle ID
driver_id — CRM contact of driver
stops_json — JSONB ordered list of stops
total_distance — total mileage in km
estimated_time — estimated time in minutes
status — planned / in_progress / completed
created_at
Route is displayed on map in admin section via Yandex.Maps API or Leaflet.js. Driver — link with waypoints.
Updating order statuses
On delivery completion at a point, optimizer (or driver via mobile app) sends event. Bitrix webhook updates specific order status:
// /bitrix/route_webhook.php
$data = json_decode(file_get_contents('php://input'), true);
foreach ($data['completed_stops'] as $stop) {
$order = \Bitrix\Sale\Order::load((int)$stop['order_id']);
if ($order) {
$order->setField('STATUS_ID', 'F');
$order->save();
// Send customer delivery notification email
}
}
Implementation timelines by scale
| Scale | Features | Timeline |
|---|---|---|
| Small (1–3 vehicles) | Single adapter, manual driver assignment | 3–5 days |
| Medium (5–20 vehicles) | Auto assignment, route map, status webhooks | 8–12 days |
| Large (20+ vehicles) | Multi-depot, driver competencies, real-time tracking | 20–35 days |
What we configure
-
RouteOptimizerInterfacewith adapters for needed services - Agent for collecting orders and sending to optimizer on business day morning
-
bl_delivery_routestable for storing routes and statuses - Route map in admin section
- Webhook for updating order statuses on delivery completion







