Integration of 1C-Bitrix with Kuranty Delivery Service (Belarus)
Integrating the Kuranty delivery service with 1C-Bitrix is a task faced by Belarusian online stores when standard modules don't fit. Kuranty's API requires JWT authorization and proper status handling. Our team has implemented several such integrations—from a simple calculator to a full cycle with pickup points and tracking. Here's how to do it right and what's important to consider.
Why Choose Kuranty for Delivery in Belarus?
Kuranty is a Belarusian logistics company specializing in courier delivery and a network of pickup points across the country. Compared to large federal operators, Kuranty offers more flexible tariffs for small and medium e-commerce. For example, delivery within Minsk is often 15–20% cheaper, and times are 1 day faster than traditional postal services. The API is provided to partners through a personal account after signing a contract.
How Does the Kuranty API Work?
The API is REST with JWT authorization. Base URL: https://api.kuranty.by/v2. A token is obtained via POST /auth/token with login and password, and lives for 24 hours. We cache the token for 23 hours to avoid hitting the API on every calculation.
Main methods:
-
POST /delivery/cost— cost calculation -
POST /delivery/create— create delivery -
GET /delivery/{uuid}/status— delivery status -
GET /pickup-points— list of pickup points
Cost Calculation
We implement a handler class extending \Bitrix\Sale\Delivery\Services\Base. In the calculateConcrete method, we get the recipient's city from order properties, send a request with weight and order total. The response includes cost and delivery time.
class KurantyHandler extends \Bitrix\Sale\Delivery\Services\Base
{
private function getAuthToken(): string
{
$cache = \Bitrix\Main\Data\Cache::createInstance();
if ($cache->initCache(3600 * 23, 'kuranty_token', '/kuranty/')) {
return $cache->getVars();
}
$response = $this->apiPost('/auth/token', [
'login' => $this->getOption('LOGIN'),
'password' => $this->getOption('PASSWORD'),
]);
$token = $response['token'] ?? '';
$cache->startDataCache();
$cache->endDataCache($token);
return $token;
}
protected function calculateConcrete(
\Bitrix\Sale\Shipment $shipment
): \Bitrix\Sale\Delivery\CalculationResult {
$result = new \Bitrix\Sale\Delivery\CalculationResult();
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$city = $this->getOrderCity($props);
if (!$city) {
$result->addError(new \Bitrix\Main\Error('Delivery city not defined'));
return $result;
}
$response = $this->apiPost('/delivery/cost', [
'from_city' => $this->getOption('SENDER_CITY'),
'to_city' => $city,
'weight' => max($shipment->getWeight() / 1000, 0.1),
'sum' => round($order->getPrice()),
'type' => $this->getOption('DELIVERY_TYPE', 'pickup'), // pickup or courier
], $this->getAuthToken());
if (!empty($response['cost'])) {
$result->setDeliveryPrice((float)$response['cost']);
$days = $response['days_min'] . '–' . $response['days_max'];
$result->setPeriodDescription("{$days} days");
}
return $result;
}
}
An important nuance: if the delivery city is not defined (e.g., the user didn't select a locality), an error is returned. In practice, this rarely happens, but we always add validation on the checkout form side.
Creating a Delivery
After order placement, a delivery must be created in the Kuranty system. The createDelivery method builds a payload: weight, total, cash on delivery, address, and contact data. The response contains the UUID of the order in Kuranty, which we save in an order property.
public function createDelivery(\Bitrix\Sale\Shipment $shipment): string
{
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$payload = [
'external_id' => 'bx_' . $order->getId(),
'type' => $this->getOption('DELIVERY_TYPE', 'pickup'),
'from_city' => $this->getOption('SENDER_CITY'),
'to_city' => $this->getOrderCity($props),
'pickup_point' => $props->getItemByOrderPropertyCode('KURANTY_POINT')?->getValue(),
'recipient' => [
'name' => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
'phone' => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
],
'address' => $props->getItemByOrderPropertyCode('ADDRESS')?->getValue(),
'weight' => max($shipment->getWeight() / 1000, 0.1),
'sum' => round($order->getPrice()),
'cod' => $order->isPaid() ? 0.0 : round($order->getPrice()),
'comment' => 'Order #' . $order->getId(),
];
$response = $this->apiPost('/delivery/create', $payload, $this->getAuthToken());
return (string)($response['uuid'] ?? '');
}
Pickup Points on the Site
To display pickup points on a map, we use the /pickup-points API. We cache the data for 6 hours—Kuranty updates the list infrequently. The response includes coordinates (lat, lon), allowing us to plot points on Yandex Maps with custom markers.
public function getPickupPoints(?string $city = null): array
{
$cacheKey = 'kuranty_pvz_' . md5((string)$city);
$cache = \Bitrix\Main\Data\Cache::createInstance();
if ($cache->initCache(3600 * 6, $cacheKey, '/kuranty/')) {
return $cache->getVars();
}
$params = $city ? ['city' => $city] : [];
$points = $this->apiGet('/pickup-points', $params, $this->getAuthToken());
$cache->startDataCache();
$cache->endDataCache($points ?? []);
return $points ?? [];
}
Tracking
Kuranty does not provide webhooks—delivery status must be polled manually. We implement a Bitrix agent that queries status for each active order every 2–3 hours and updates it in order properties. The getStatus method accepts a UUID and returns the current status array.
public function getStatus(string $uuid): array
{
return $this->apiGet("/delivery/{$uuid}/status", [], $this->getAuthToken()) ?? [];
}
What's Included in the Integration
| Task | Description |
|---|---|
| Current system audit | Analyze infoblock structure, order properties, delivery settings |
| Calculator development | Implement handler class for cost calculation with token caching |
| Order creation | Write code to send orders to Kuranty after checkout |
| Pickup point display | Integrate pickup points list with map on the site |
| Tracking and notifications | Set up agent for status updates and email notifications to customers |
| Testing and documentation | Test all scenarios, create admin instruction |
Comparison of Kuranty with Other Belarusian Delivery Services
| Parameter | Kuranty | Europochetta | Belpochta |
|---|---|---|---|
| Delivery time in Minsk | 1 day | 1–2 days | 2–3 days |
| Delivery time to regions | 1–3 days | 2–4 days | 3–7 days |
| Pickup points | 200+ | 100+ | none (only post office) |
| API | REST with JWT | REST with key | outdated XML |
Kuranty wins on speed in cities and number of pickup points but loses to Belpochta on cost. For high-volume online stores, combining services is more advantageous.
Timeline Estimates
| Component | Duration |
|---|---|
| Cost calculation + order creation | 3–4 days |
| + Pickup points on map | +2 days |
| + Tracking + notifications | +2 days |
| + Cash on delivery | +1 day |
Why Commission Our Integration?
Our team brings over 5 years of experience with 1C-Bitrix and more than 50 successful projects integrating delivery services. We provide a warranty on the code and post-launch support. All our specialists are vendor-certified. You'll receive a detailed quote and roadmap within 1 day after contacting us.
Order a turnkey integration—contact us to evaluate your project.







