1C-Bitrix Integration with Ukrposhta Delivery Service (Ukraine)
Ukrposhta is the state postal operator of Ukraine. Like Russian Post, it is indispensable for delivery to small towns and rural areas. The API is modern (REST, OAuth 2.0), but has a number of specific requirements: mandatory address normalization, strict data formats. For stores covering all of Ukraine, integration with Ukrposhta often runs in parallel with Nova Poshta.
Ukrposhta API: OAuth 2.0
Base URL: https://www.ukrposhta.ua/ecom/0.0.1/. Authorization: Bearer token. The token is obtained via OAuth 2.0 with the client_credentials grant type.
private function getToken(): string
{
$cacheKey = 'ukrposhta_token';
$cached = \Bitrix\Main\Data\Cache::createInstance();
if ($cached->startDataCache(3000, $cacheKey, '/ukrposhta')) {
$ch = curl_init('https://www.ukrposhta.ua/oauth/token');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'grant_type' => 'client_credentials',
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
]),
CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
$token = $response['access_token'] ?? '';
$cached->endDataCache(['token' => $token]);
}
return $cached->getVars()['token'];
}
The token is cached for 3000 seconds (token TTL is 3600 seconds, leaving a buffer).
Cost Calculation
public function calcPostcardPrice(
string $fromPostcode,
string $toPostcode,
int $weightGram,
string $type = 'PARCEL'
): float {
$response = $this->apiGet('/delivery360/calculate', [
'from_postcode' => $fromPostcode,
'to_postcode' => $toPostcode,
'weight' => $weightGram,
'length' => 300,
'width' => 200,
'height' => 100,
'type' => $type, // PARCEL, DOCUMENT, LETTER
]);
return (float)($response['deliveryPrice'] ?? 0);
}
Calculation requires dispatch and delivery postal codes. To obtain a postal code from an address, use the address search method: GET /addresses/search?street=...&city=....
Address Normalization and Search
public function searchAddress(string $city, string $street, string $house = ''): array
{
$response = $this->apiGet('/addresses/search', [
'street' => $street,
'city' => $city,
'houseNumber' => $house,
'language' => 'UA',
]);
return $response['addresses'] ?? [];
}
The response contains an array of addresses with postcode — the postal code needed for calculation and shipment creation. If the address is not found or is ambiguous — show the customer a list of options for clarification.
Shipment Creation
public function createShipment(\Bitrix\Sale\Shipment $shipment): string
{
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$addressRef = $props->getItemByOrderPropertyCode('UKRPOSHTA_ADDRESS_ID')?->getValue();
$payload = [
'type' => 'PARCEL',
'sender' => [
'name' => $this->getOption('SENDER_NAME'),
'phone' => $this->getOption('SENDER_PHONE'),
'postcode' => $this->getOption('SENDER_POSTCODE'),
],
'recipient' => [
'name' => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
'phone' => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
'postcode' => $props->getItemByOrderPropertyCode('UKRPOSHTA_POSTCODE')?->getValue(),
'addressId' => $addressRef,
],
'weight' => $this->getWeight($shipment),
'length' => 300,
'width' => 200,
'height' => 100,
'declaredPrice' => $order->getPrice(),
'postPay' => 0, // cash on delivery (0 = no COD)
];
$response = $this->apiPost('/shipments', $payload);
$barcode = $response['barcode'] ?? '';
$props->getItemByOrderPropertyCode('UKRPOSHTA_BARCODE')?->setValue($barcode);
$order->save();
return $barcode;
}
Tracking
public function trackShipment(string $barcode): array
{
$response = $this->apiGet('/statuses/shipments', [
'barcode' => $barcode,
]);
$event = end($response['eventHistory'] ?? []);
return [
'status' => $event['eventName'] ?? '',
'date' => $event['date'] ?? '',
'postcode' => $event['postcode'] ?? '',
];
}
No push notifications. Polling via agent every 4–6 hours (Ukrposhta delivery times are 2–7 days, frequent polling is excessive).
Cash on Delivery
Ukrposhta supports cash on delivery (postPay). The amount is specified in hryvnias. Upon delivery, the customer pays the amount, Ukrposhta retains a commission and transfers the remainder to the store's account details from the contract.
Timelines
| Scope | Timeline |
|---|---|
| OAuth + cost calculation | 2–3 days |
| + Shipment creation + tracking | +2 days |
| + Address/postcode search at checkout | +1 day |







