1C-Bitrix Integration with Russian Post Delivery Service
Russian Post is the only carrier with coverage across every locality in the country, making integration with it practically mandatory for stores selling to small towns and rural areas. The Russian Post API (Otpravka 2.0) is significantly better than the old one, but still requires an understanding of its specifics: address normalization, shipment types, batch mode, and cash on delivery.
Russian Post API: How It Works
Base URL: https://otpravka-api.pochta.ru. Authorization requires two tokens simultaneously — Authorization: AccessToken TOKEN and X-User-Authorization: Basic BASE64(login:password).
Key method groups:
-
/1.0/user/shipping-points— dispatch addresses (origin) -
/1.0/clean/address— address normalization -
/1.0/tariff— rate calculation -
/1.0/user/backlog— batch shipment loading -
/1.0/batch/{batchName}/shipment— creating shipments within a batch -
/1.0/shipment/search— tracking by barcode
Address Normalization
The main pain point with Russian Post is the quality of addresses entered by customers. The API requires valid addresses in FIAS format. Normalization is the first step before any operation:
private function normalizeAddress(string $rawAddress): array
{
$response = $this->apiPost('/1.0/clean/address', [
[
'id' => 'addr1',
'original-address' => $rawAddress,
]
]);
$normalized = $response[0] ?? [];
if (($normalized['quality-code'] ?? '') === 'GOOD') {
return $normalized;
}
// If quality is poor — return an error, do not create a shipment
throw new \RuntimeException(
'Address not normalized: ' . ($normalized['quality-code'] ?? 'unknown')
);
}
Quality codes: GOOD — fully normalized, POSTAL_BOX — PO box, ON_DEMAND — general delivery, UNDEF_* — various normalization issues. Only GOOD guarantees correct delivery.
Rate Calculation
private function calcTariff(
array $normalizedAddress,
int $weightGram,
string $mailType = 'POSTAL_PARCEL'
): float {
$response = $this->apiPost('/1.0/tariff', [
'object-type' => $mailType,
'mail-category' => 'ORDINARY',
'from-index' => $this->getOption('FROM_INDEX'), // dispatch postal code
'to-index' => $normalizedAddress['index'],
'mass' => $weightGram,
'dimension' => [
'height' => 200,
'length' => 300,
'width' => 200,
],
]);
return ($response['total-rate'] ?? 0) / 100; // kopecks → rubles
}
Russian Post returns the cost in kopecks — remember to divide by 100. Shipment types: POSTAL_PARCEL (parcel), EMS (express), EMS_OPTIMAL (optimal EMS), FIRST_CLASS (first class).
Batch Mode: Creating Shipments
Russian Post operates through batches. You cannot create a single shipment — you must create a batch, add shipments to it, and submit it for printing.
public function createShipment(\Bitrix\Sale\Shipment $shipment): string
{
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
// 1. Get or create a batch
$batchName = $this->getOrCreateBatch($shipment);
// 2. Create a shipment within the batch
$payload = [[
'address-type-to' => 'DEFAULT',
'mail-type' => 'POSTAL_PARCEL',
'mail-category' => 'ORDINARY',
'mass' => $this->getWeight($shipment),
'index-to' => $this->getNormalizedIndex($props),
'recipient-name' => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
'tel-address' => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
'str-index-to' => $this->getNormalizedIndex($props),
'order-num' => (string)$order->getId(),
'payment' => $this->getCashOnDelivery($order), // cash on delivery
]];
$response = $this->apiPost("/1.0/batch/{$batchName}/shipment", $payload);
$barcode = $response['result-ids'][0] ?? null;
if ($barcode) {
$props->getItemByOrderPropertyCode('POCHTA_BARCODE')?->setValue($barcode);
$order->save();
}
return $barcode ?? '';
}
Cash on Delivery
Cash on delivery (COD) is a key Russian Post feature for e-commerce. The payment field in the request contains the amount to be collected from the customer in kopecks. If COD is not required — pass 0.
With COD, Russian Post retains a commission (~2–3%) and transfers the remainder to the store's bank account. Transfer timelines are up to 10 business days.
Tracking via Russian Post API
public function trackShipment(string $barcode): array
{
$response = $this->apiGet('/1.0/shipment/search', ['query' => $barcode]);
$events = $response['trackingData']['trackingItem']['trackingHistoryItem'] ?? [];
$lastEvent = end($events);
return [
'status' => $lastEvent['humanStatus'] ?? '',
'date' => $lastEvent['eventDateTime'] ?? '',
'city' => $lastEvent['cityName'] ?? '',
'barcode' => $barcode,
];
}
Tracking via the main API is rate-limited. For high-traffic stores, a separate Tracking API with a different quota is used.
Printing Labels and Forms
After adding shipments to a batch, printing of form F7 (address label) and F107/F112 (accompanying documents) becomes available:
GET /1.0/forms/{barcode}/f7pdf — address label
GET /1.0/batch/{batchName}/checkin — batch handover to the post office
Timelines
| Scope | Timeline |
|---|---|
| Rate calculation + address normalization | 3–4 days |
| + Shipment creation (batch mode) | +2 days |
| + Cash on delivery + tracking | +2 days |
| + Label printing in admin panel | +1 day |







