1C-Bitrix Integration with Boxberry Delivery Service
Boxberry is a courier service with an extensive network of pickup points (PVZ) across Russia. The main e-commerce use case is pickup point delivery, which is cheaper than door-to-door delivery. The Boxberry API is quite specific: authentication is via a token passed as a query parameter (not in the header), some methods work via GET with JSON in the query string. There are nuances in cost calculation and passing product data.
Boxberry API Specifics
The Boxberry API works through a single endpoint: https://api.boxberry.ru/json.php. The method is passed as the method parameter, the token as the token parameter. Response format — JSON.
Key methods:
-
ListPoints— full list of pickup points -
ListPointsShort— short list of pickup points (faster) -
DeliveryCosts— delivery cost calculation -
ParselCreate— create a shipment -
ParselCheck— shipment status by tracking number
A non-standard detail: data for ParselCreate is sent via POST, but the parameters are URL-encoded, not JSON. This must be accounted for when building requests.
Delivery Cost Calculation
private function calcDeliveryCost(
string $pvzCode,
int $weightGram,
float $orderSum
): float {
$params = [
'token' => $this->token,
'method' => 'DeliveryCosts',
'zip' => $pvzCode,
'weight' => ceil($weightGram / 1000 * 1000), // in grams
'ordersum' => $orderSum,
'api_version' => '1.0',
];
$url = 'https://api.boxberry.ru/json.php?' . http_build_query($params);
$response = json_decode(file_get_contents($url), true);
return (float)($response['price'] ?? 0);
}
Boxberry returns the cost in rubles in the price field. If the pickup point is not found or delivery is not available for it — the response contains an err field. Always check for the error before using the price.
Delivery Service Class
class BoxberryDeliveryService extends \Bitrix\Sale\Delivery\Services\Base
{
protected function calculateConcrete(
\Bitrix\Sale\Shipment $shipment
): \Bitrix\Sale\Delivery\CalculationResult {
$result = new \Bitrix\Sale\Delivery\CalculationResult();
$pvzCode = $this->getSelectedPvzCode($shipment);
if (!$pvzCode) {
$result->addError(new \Bitrix\Main\Error('Please select a pickup point'));
return $result;
}
$weight = max($this->getShipmentWeight($shipment), 50);
$orderSum = $shipment->getOrder()->getPrice();
$cost = $this->calcDeliveryCost($pvzCode, $weight, $orderSum);
if ($cost <= 0) {
$result->addError(new \Bitrix\Main\Error('Unable to calculate delivery cost'));
return $result;
}
$result->setDeliveryPrice($cost);
return $result;
}
}
The selected pickup point code is stored in the session or in the order property BOXBERRY_PVZ_CODE — added at checkout via the widget.
Pickup Point Selection Widget
Boxberry provides a JavaScript widget for displaying pickup points on a map:
<script type="text/javascript" src="https://points.boxberry.ru/js/boxberry.js"></script>
<script>
boxberry.open(function(result) {
if (result && result.id) {
document.getElementById('boxberry_pvz').value = result.id;
document.getElementById('boxberry_pvz_name').value = result.name + ', ' + result.address;
// Update delivery cost via AJAX
recalculateDelivery();
}
}, 'TOKEN_HERE', 'Moscow', '', 0, 'e');
</script>
The function accepts a callback, token, default city, and additional parameters. result.id — the pickup point code for the API.
Creating a Shipment
private function createParsel(\Bitrix\Sale\Shipment $shipment): string
{
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$parselData = [
'token' => $this->token,
'method' => 'ParselCreate',
'senderName' => $this->getOption('SENDER_NAME'),
'weight' => $this->getShipmentWeight($shipment),
'price' => $order->getPrice(),
'delivery_sum' => $shipment->getPrice(),
'vid' => 1, // 1-to pickup point
'PVZ' => $props->getItemByOrderPropertyCode('BOXBERRY_PVZ_CODE')?->getValue(),
'customerName' => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
'customerPhone' => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
'customerEmail' => $props->getItemByOrderPropertyCode('EMAIL')?->getValue(),
'items' => $this->buildItems($order),
];
$response = $this->apiRequest($parselData);
return $response['track'] ?? '';
}
The vid field: 1 — delivery to a pickup point, 2 — door-to-door delivery. The tracking number from the response (track) is saved to the order property BOXBERRY_TRACK for subsequent tracking.
Shipment Tracking
public function checkStatus(string $trackCode): array
{
$params = [
'token' => $this->token,
'method' => 'ParselCheck',
'ImId' => $trackCode,
];
$url = 'https://api.boxberry.ru/json.php?' . http_build_query($params);
$data = json_decode(file_get_contents($url), true);
return [
'status' => $data[0]['Name'] ?? 'Unknown',
'date' => $data[0]['Date'] ?? '',
'city' => $data[0]['CityName'] ?? '',
];
}
Boxberry does not support webhooks — only polling. A Bitrix agent checks the status of active shipments once per hour. When the status changes to "Delivered to recipient", the order is moved to its final status.
Boxberry Status Mapping
| Boxberry Status | Action in Bitrix |
|---|---|
| Accepted at Boxberry warehouse | Transferred to delivery |
| In transit | Dispatched |
| Arrived at destination pickup point | Arrived at pickup point |
| Issued to recipient | Delivered |
| Return to sender | Return |
Timeline
| Scope | Duration |
|---|---|
| Calculation + pickup widget + shipment creation | 4–5 days |
| + Status polling + mapping | +2 days |
| + Shipping label printing | +1 day |







