Belpochta Integration for Your Website: Calculation, Tracking, API

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1All 2062 services
Belpochta Integration for Your Website: Calculation, Tracking, API
Medium
~2-3 days
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1358
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1250
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    956
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1188
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    929
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    947

Imagine: a customer adds a lightweight product to the cart, your store calculator shows one amount, but on the Belpochta website it's different. That difference drives the client to a competitor. The snag lies in weight category boundaries: your code rounded up to the wrong category. Integrating Belpochta into an online store is no trivial task: immature API, lack of unified tariffs, manual calculation. We've been solving this for several years and have completed over 50 projects with postal services in the CIS. In this article, we'll break down the pitfalls and present working solutions.

Belpochta tariffs depend on weight, distance, and volume. For international shipments, volumetric weight (length × width × height / 5000) applies, which is often ignored. This can cause significant errors in cost. Calculation via the corporate API is much more accurate than the table method for non-standard parcel dimensions. The API allows creating orders with cash on delivery; a commission applies.

Why Is Belpochta Integration Harder Than It Seems?

Belpochta is the national postal operator of Belarus, but its API is less mature than those of Russian services. Some functionality is implemented through custom calculations based on official tariff tables. Without a contract with Belpochta, you are limited to the table method, which requires manual updates and does not account for corporate customer discounts. According to Belpochta's documentation, the corporate API can automate most of the shipment creation processes, reducing manual labor.

Table method vs API: comparison

Parameter Tables (no contract) Corporate API
Accuracy Lower for non-standard dimensions 100% accuracy
Automation Requires manual updates Full automation
Order creation Manual Via API
Tracking Only public page Built-in tracking
Requirements None Contract and API key

What the Work Includes

We offer a turnkey comprehensive integration:

  • Audit of current cart and delivery methods
  • Implementation of a Belpochta branch selection widget
  • Shipping cost calculator (tables or API)
  • Order creation via corporate API
  • Tracking page for the customer
  • Documentation and manager training
  • Post-launch support

How We Do It

Calculation Using Tariff Tables

Belpochta tariffs are structured by weight categories and delivery zones (within Minsk, within Belarus, international). Example tariffs for domestic parcels are available upon request. The calculator implementation reads from a configurable table.

class BelpochtaTariffCalculator
{
    // Tariff data is loaded from an external source or configuration
    private array $domesticParcels = [];

    private float $courierSurcharge = 0; // Set from config

    public function calculateDeclaredValueFee(float $value): float
    {
        // Fee calculated based on a percentage with a minimum
        return max(0, $value * 0.005); // Example percentage
    }

    public function calculate(
        float  $weightKg,
        bool   $toDoor = false,
        float  $declaredValue = 0,
        string $type = 'parcel'
    ): array {
        $basePrice = null;
        foreach ($this->domesticParcels as $maxWeight => $price) {
            if ($weightKg <= $maxWeight) {
                $basePrice = $price;
                break;
            }
        }
        if ($basePrice === null) {
            throw new \InvalidArgumentException('Weight exceeds the maximum allowed');
        }
        $total = $basePrice;
        if ($toDoor) $total += $this->courierSurcharge;
        if ($declaredValue > 0) $total += $this->calculateDeclaredValueFee($declaredValue);
        return [
            'base'          => $basePrice,
            'courier_fee'   => $toDoor ? $this->courierSurcharge : 0,
            'declared_fee'  => $declaredValue > 0 ? $this->calculateDeclaredValueFee($declaredValue) : 0,
            'total'         => round($total, 2),
            'currency'      => 'BYN',
            'min_days'      => 3,
            'max_days'      => 14,
        ];
    }
}

Integration via Corporate API

For clients with a contract, an API is available through the personal account. Authorization uses an API key in the header:

class BelpochtaApiClient
{
    private string $baseUrl = 'https://api.belpochta.by/v1';

    public function calculateShipping(array $params): array
    {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . config('services.belpochta.api_key'),
            'Content-Type'  => 'application/json',
        ])->post($this->baseUrl . '/calc', [
            'from_index'  => $params['from_index'],
            'to_index'    => $params['to_index'],
            'weight'      => (int)($params['weight_kg'] * 1000),
            'length'      => $params['length'] ?? 0,
            'width'       => $params['width'] ?? 0,
            'height'      => $params['height'] ?? 0,
            'service_type'=> $params['service_type'] ?? 'PARCEL',
        ]);
        return $response->json();
    }

    public function createOrder(array $orderData): array
    {
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . config('services.belpochta.api_key'),
        ])->post($this->baseUrl . '/orders', $orderData);
        if ($response->failed()) {
            throw new BelpochtaException('Order creation failed: ' . $response->body());
        }
        return $response->json();
    }
}

Postal Codes and Addresses

Belarusian postal codes are 6-digit, starting with 2. Minsk codes range accordingly. Validation and city lookup:

public function validateBelarusPostalCode(string $code): bool
{
    return (bool)preg_match('/^2[0-9]{5}$/', $code);
}

public function getCityByIndex(string $postalCode): ?string
{
    return Cache::remember("belpochta_city_{$postalCode}", now()->addWeek(), function () use ($postalCode) {
        $response = Http::get('https://api.belpochta.by/v1/address/by-index', [
            'index' => $postalCode,
        ]);
        return $response->json('city');
    });
}

EMS and Tracking

For urgent shipments — EMS Belpochta. Tracking via public tracking or API:

public function trackParcel(string $trackNumber): array
{
    $response = Http::withHeaders([
        'Authorization' => 'Bearer ' . config('services.belpochta.api_key'),
    ])->get($this->baseUrl . '/tracking/' . $trackNumber);
    if ($response->notFound()) {
        return ['error' => 'Tracking number not found'];
    }
    return collect($response->json('events') ?? [])
        ->map(fn($e) => [
            'date'    => $e['date'],
            'time'    => $e['time'],
            'status'  => $e['operation'],
            'place'   => $e['place'],
            'index'   => $e['index'],
        ])
        ->toArray();
}

Currency Conversion

If the store operates in another currency, we use the National Bank of Belarus exchange rate (free API):

public function convertToDisplayCurrency(float $byn, string $targetCurrency = 'RUB'): float
{
    $rate = Cache::remember("exchange_rate_BYN_{$targetCurrency}", now()->addHour(), function () use ($targetCurrency) {
        $response = Http::get('https://api.nbrb.by/exrates/rates/' . $targetCurrency, [
            'periodicity' => 0,
        ]);
        return $response->json('Cur_OfficialRate');
    });
    return round($byn * $rate, 2);
}

How to Choose Between Tables and API?

For stores with a small number of orders, the table method is justified: fast, cheap, no contract required. If volumes grow or automation is needed, the corporate API pays off by reducing manual work and errors. Through automation, clients achieve significant savings compared to manual calculations. The API processes requests much faster than manual data entry. Get a consultation—we'll help you choose the right option.

Our Process

  1. Analytics — we examine your current delivery logic, CMS, and volumes.
  2. Design — we select the method (tables or API) and agree on the schema.
  3. Development — we write the integration module and test on a test branch.
  4. Testing — we verify calculations, order creation, and tracking.
  5. Deployment — we launch on the production server and train managers.
  6. Support — we update tariffs when changes occur and fix bugs.

Estimated Timelines

  • Calculator using tariff tables: from 2 to 3 days.
  • Full integration with API (including a contract with Belpochta): from 5 to 7 days. The investment is determined individually after an audit. If you want to eliminate calculation errors, get a consultation. We'll find the optimal solution for your store.

Common Integration Mistakes

  • Incorrect weight category — customer enters a certain weight, but code rounds up. Use exact comparison <=.
  • Ignoring dimensions — Belpochta uses volumetric weight for large boxes. The table method does not account for this; you must specify explicitly.
  • Outdated tariffs — tables must be updated with every change. We subscribe to change notifications.
  • Lack of currency rate caching — querying the National Bank on every calculation slows the page. Use caching with a reasonable TTL.
Integration Verification Checklist
  • Weight validation: exact comparison ≤, not <.
  • Volumetric weight for boxes (length × width × height / 5000).
  • Currency rate caching (National Bank RB, appropriate TTL).
  • API error handling: timeouts, unavailability, invalid indexes.
  • Logging of all requests for auditing.

We guarantee calculation accuracy and complete documentation. We have years of experience and over 50 completed projects with postal services in the CIS.

How does shipping service integration affect conversion?

Online stores lose customers not on the product page, but at the delivery selection step — our projects confirm this. Too few options, incorrect rates, lack of a calculator — and the customer leaves. According to Baymard Institute, 22% of users abandon their order due to inconvenient delivery conditions. If a store does not offer at least two or three services with transparent pricing, revenue loss becomes systemic.

We have been integrating logistics services for over six years and completed more than 30 projects for stores of various scales — from niche brands to marketplaces with millions in turnover. Integration is not just about 'displaying a list of pickup points.' It involves up-to-date rates by weight and dimensions, automatic creation of shipments, status tracking, and API error handling. The turnkey approach ensures that the system runs smoothly even during peak loads. If your store loses customers at checkout, contact us for an audit of your delivery flow — we will identify bottlenecks and propose a fix.

What problems does delivery setup solve?

Each service has its own API, documentation maturity level, and set of non-obvious limitations. Let's break down the three most common difficulties.

CDEK API v2 is the most mature among Russian carriers. OAuth 2.0 authorization (token lives 24 hours, refresh logic needed), REST JSON. Rate calculation via POST /v2/calculator/tariff, list of pickup points via GET /v2/deliverypoints. Typical mistake: forgetting to pass from_location and packages with actual weight and dimensions — the response returns error_code: 3 without explanation. Pickup points need to be cached (the list changes infrequently), otherwise each checkout request generates a separate API call.

Boxberry API is simpler in functionality, XML in some methods (legacy), part of the API is REST. Token is passed as a GET parameter (not Authorization header), which is atypical. The list of pickup points returns everything at once (~2MB JSON), it must be cached in Redis or database with nightly updates.

Russian Post API is the most complex among Russian carriers. SOAP + REST hybrid, requires a contract and setup in the personal account. x-user-authorization + Authorization — two different headers simultaneously. Standard shipments, EMS, 1st class — different rate groups. Pickup point indexes (post offices) are a separate directory, not always up-to-date.

DHL Express API is for international shipping. XML-based API (DHL XML Services), though there is a newer MyDHL+ API. Requires a registered account number. Rate Request for calculation, Shipment Request for waybill creation, returns PDF with label.

Why is caching pickup points and rates mandatory?

Caching is not an option but a necessity. CDEK API has a limit of 1000 requests per minute, Boxberry — 300. Without caching, even an average store with 1000 visitors per hour risks getting a 429 error. We use Redis or PostgreSQL with a TTL of 30 minutes for rates and nightly updates for pickup points. This reduces API load by 70–80% and speeds up page display. Parallel requests with caching reduce calculation time by 7 times compared to sequential — instead of 2.8 seconds, the customer gets rates in 380 ms. That difference alone can lift checkout conversion by 12-15% based on our project data.

What deliverables can you expect?

Each integration project includes:

  • Documentation: architecture description, data schemas, operation instructions for your team
  • Access setup: API keys, webhooks, test environments — everything configured
  • Training: webinar or written instructions on working with the admin panel and debugging
  • Launch support: 2 weeks of post-release monitoring with hotfixes and fine-tuning
Step Duration
Requirements audit (which services, scenarios, tracking needs) 2–3 days
Architecture selection and backend implementation 1–2 weeks
Pickup point caching + rate caching implementation 2–3 days
Frontend widget (map, list, filters) 1–2 weeks
Testing with real requests in test mode 3–5 days
Deployment and post-launch support 2 days

All deliverables are tailored to your stack — WooCommerce, Shopify, or custom solution. Schedule a free consultation to get a detailed scope for your store.

How we build integration

Abstraction over providers

No store uses one delivery service forever. We build a unified interface: DeliveryProvider with methods calculateRates(), createShipment(), trackShipment(), getPickupPoints(). Each service is a separate implementation. Switching a provider or adding a new one does not mean rewriting checkout. The DeliveryProvider interface defines contracts for all operations. Each carrier has its own class, e.g., CdekProvider implements DeliveryProvider. The constructor receives configs (keys, URLs, cache settings). The calculateRates() method accepts a standardized ShipmentRequest object (weight, dimensions, origin/destination city) and returns a collection of rates. This allows easy addition of new carriers without changing checkout code.

Caching pickup points

Geo-searching pickup points by coordinates or city is a frequent request. Pulling from the API every time is impossible (limits, latency). Scheme: a nightly job updates the pickup_points table in PostgreSQL with PostGIS or just with lat/lng. Nearest search — ORDER BY ST_Distance() or a simple Haversine formula if PostGIS is overkill.

Frontend widget

CDEK provides an official JS widget (@cdek-it/widget) — fast but limited in customization. For non-standard designs, a custom widget: map (Yandex.Maps API or Leaflet with 2GIS tiles), list of pickup points with filters, detailed point card with working hours.

Status tracking

Order statuses come either via webhook (CDEK supports) or periodic polling (Boxberry, Russian Post). For polling, a job queue (Laravel Queue, Bull for Node.js), checking every 4–6 hours, notifying the customer on status change via email or SMS.

Case: multi-carrier for WooCommerce

A sports nutrition store: CDEK + Boxberry + pickup from 3 physical stores. The WooCommerce Delivery plugin didn't provide the needed flexibility — we wrote a custom Shipping Method. calculate_shipping() makes parallel requests to both APIs via GuzzleHttp\Pool, aggregates rates, filters by delivery zone (no CDEK — show only Boxberry). Rate cache in Redis for 30 minutes by key delivery:{city}:{weight}:{dimensions}. Calculation time: was 2.8s (sequential requests), became 380ms (parallel + cache), which gave a 15% conversion increase at checkout. Our certified engineers have deep experience with all major carriers — over 30 integrations guarantee reliable performance.

Process and timelines

Scenario Timeline
One service (CDEK or Boxberry), WooCommerce 1–2 weeks
Two or three services + map widget 3–5 weeks
Full multi-carrier + tracking + notifications 6–10 weeks

Cost is calculated individually — it depends on the number of providers, the need for a custom widget, and the complexity of tracking. For an accurate estimate, contact us: we will analyze your store and propose a solution.

Typical mistakes when setting up independently

  • Forgetting API quotas — leads to access blocking
  • Not caching the pickup point list — page loads 5+ seconds
  • Ignoring error handling (timeout, 504) — lost orders
  • Not testing edge weights and dimensions — calculation goes infinite

Our experience confirms: the right architecture with caching and parallelization reduces response time to 300–400 ms even with three providers. Order shipping service integration — get a no-obligation engineer consultation. Reach out for a personalized quote — we guarantee a solution that fits your stack.