Integration of 1C-Bitrix with the Kazpost delivery service (Kazakhstan)

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Integration with Kazpost Delivery Service (Kazakhstan)

Kazpost is the national postal operator of Kazakhstan. Coverage spans all localities in the country, including hard-to-reach areas. For e-commerce targeting the Kazakhstani market, Kazpost is essential where private courier services do not operate. The API provides a REST interface with token-based authorization.

Kazpost API: Connection

Kazpost provides its API through the partner portal. Production base URL: https://api.kazpost.kz/api/v1/. Authorization via API key in the Authorization: Bearer TOKEN header.

private function apiRequest(string $method, string $path, array $data = []): array
{
    $url = 'https://api.kazpost.kz/api/v1' . $path;
    $ch = curl_init($method === 'GET' ? $url . '?' . http_build_query($data) : $url);

    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => [
            'Authorization: Bearer ' . $this->getOption('API_TOKEN'),
            'Content-Type: application/json',
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => $method !== 'GET' ? json_encode($data) : null,
    ]);

    $response = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($code >= 400) {
        throw new \RuntimeException("Kazpost API error {$code}: {$response}");
    }

    return json_decode($response, true) ?? [];
}

Cost Calculation

public function calcPrice(
    string $fromZip,
    string $toZip,
    int $weightGram,
    string $mailType = 'SMALL_PACKAGE'
): float {
    $response = $this->apiRequest('POST', '/tariff/calculate', [
        'fromZip'     => $fromZip,
        'toZip'       => $toZip,
        'weight'      => $weightGram,
        'mailType'    => $mailType, // SMALL_PACKAGE, PACKAGE, EMS
        'addServices' => [],
    ]);

    return (float)($response['totalCost'] ?? 0);
}

Shipment types: SMALL_PACKAGE (small packet, up to 2 kg), PACKAGE (parcel), EMS (express). Cost is calculated in Kazakhstani tenge.

Postal Code Lookup by Address

Calculation requires the recipient's postal code. Kazpost provides a postal code lookup API:

public function findZipByAddress(string $city, string $street, string $house): ?string
{
    $cacheKey = 'kazpost_zip_' . md5($city . $street . $house);
    $cached = \Bitrix\Main\Data\Cache::createInstance();

    if ($cached->startDataCache(86400 * 7, $cacheKey, '/kazpost')) {
        $response = $this->apiRequest('GET', '/address/search', [
            'city'   => $city,
            'street' => $street,
            'house'  => $house,
        ]);
        $zip = $response[0]['zip'] ?? null;
        $cached->endDataCache(['zip' => $zip]);
    }

    return $cached->getVars()['zip'];
}

The "Postal Code" field on the website can be filled in automatically: the customer enters an address, an AJAX request determines the postal code. Cache for one week — postal codes rarely change.

Creating a Postal Item

public function createMailItem(\Bitrix\Sale\Shipment $shipment): string
{
    $order = $shipment->getOrder();
    $props = $order->getPropertyCollection();

    $payload = [
        'mailType'       => 'PACKAGE',
        'weight'         => $this->getWeight($shipment),
        'declaredValue'  => (int)($order->getPrice() * 100), // in tiyn
        'cashOnDelivery' => 0,
        'sender' => [
            'name'    => $this->getOption('SENDER_NAME'),
            'zip'     => $this->getOption('SENDER_ZIP'),
            'address' => $this->getOption('SENDER_ADDRESS'),
            'phone'   => $this->getOption('SENDER_PHONE'),
        ],
        'recipient' => [
            'name'    => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
            'zip'     => $props->getItemByOrderPropertyCode('KAZPOST_ZIP')?->getValue(),
            'address' => $props->getItemByOrderPropertyCode('ADDRESS')?->getValue(),
            'phone'   => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
        ],
        'items' => $this->buildItems($order),
    ];

    $response = $this->apiRequest('POST', '/mail-items', $payload);
    $barcode = $response['barcode'] ?? '';

    $props->getItemByOrderPropertyCode('KAZPOST_BARCODE')?->setValue($barcode);
    $order->save();

    return $barcode;
}

The declared value (declaredValue) is passed in tiyn (1 tenge = 100 tiyn). This is a common feature of Kazakhstani APIs — account for the conversion.

Tracking

public function track(string $barcode): array
{
    $response = $this->apiRequest('GET', '/tracking/' . $barcode);
    $events = $response['events'] ?? [];
    $last = end($events);

    return [
        'status'   => $last['statusName'] ?? '',
        'date'     => $last['eventDate'] ?? '',
        'location' => $last['locationName'] ?? '',
    ];
}

Timelines

Scope Timeline
Cost calculation + postal code lookup 2–3 days
+ Shipment creation + tracking +2 days
+ Cash on delivery +1 day