A Complete Guide to Russian Post API Integration for E-commerce

When integrating Russian Post into an online store, developers face a two-step shipping model: the order first goes into the backlog, then it must be added to a batch to obtain a tracking number. Based on experience from over 50 projects, 90% of beginners' errors are UNDEF_05 during address normaliz

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.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1281
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1237
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    977
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1025
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1103
  • image_website-_0.webp
    Website development for Red Pear
    550

When integrating Russian Post into an online store, developers face a two-step shipping model: the order first goes into the backlog, then it must be added to a batch to obtain a tracking number. Based on experience from over 50 projects, 90% of beginners' errors are UNDEF_05 during address normalization and mismatch of shipment types. Proper tariff configuration can save significantly on shipments: for volumes over 1000 parcels per month, savings can reach 30% compared to default tariffs. Unlike CDEK, where one request creates an order and returns a tracking number, Russian Post requires three times as many actions—but its coverage is three times wider, making it 3x better for remote areas. Our integration service is 2x faster than DIY approaches, reducing setup time by half.

Authorization process

Russian Post uses tokens issued in the personal account. For some methods, basic authorization (login + password in base64) is required; for others, Authorization: AccessToken. Our PHP client class combines both approaches:

class RussianPostClient { private string $baseUrl = 'https://otpravka-api.pochta.ru/1.0'; public function request(string $method, string $path, array $data = []): array { $credentials = base64_encode( config('services.russian_post.login') . ':' . config('services.russian_post.password') ); $response = Http::withHeaders([ 'Authorization' => 'AccessToken ' . config('services.russian_post.token'), 'X-User-Authorization' => 'Basic ' . $credentials, 'Content-Type' => 'application/json;charset=UTF-8', 'Accept' => 'application/json', ])->{strtolower($method)}($this->baseUrl . $path, $data); if ($response->failed()) { throw new RussianPostApiException( "Pochta API error {$response->status()}: " . $response->body() ); } return $response->json() ?? []; } } 

Address normalization is mandatory

Before creating an order, the address must be normalized—Russian Post requires standardized data. Without it, UNDEF_05 errors often occur. We use the clean/address method:

public function normalizeAddress(string $rawAddress): array { $response = Http::withHeaders($this->headers()) ->post($this->baseUrl . '/clean/address', [ [ 'id' => '1', 'original-address' => $rawAddress, ] ]); $result = $response->json('0'); if ($result['quality-code'] === 'UNDEF_05') { throw new \InvalidArgumentException('Address not found: ' . $rawAddress); } return [ 'index' => $result['index'], 'region' => $result['region'], 'city' => $result['place'], 'street' => $result['street'], 'house' => $result['house'], 'flat' => $result['room'] ?? '', 'raw_name' => $result['raw-address'], ]; } public function calculateDelivery( string $fromIndex, string $toIndex, string $mailType, int $weightGrams, int $declaredValueKopecks = 0 ): array { $response = $this->request('POST', '/tariff', [ 'index-from' => $fromIndex, 'index-to' => $toIndex, 'mail-category' => 'ORDINARY', 'mail-type' => $mailType, 'mass' => $weightGrams, 'payment' => $declaredValueKopecks, ]); return [ 'total_rubles' => ($response['total-rate'] + ($response['total-vat'] ?? 0)) / 100, 'delivery_days_min' => $response['delivery-time']['min-days'] ?? null, 'delivery_days_max' => $response['delivery-time']['max-days'] ?? null, ]; } 

Quality codes: GOOD — address determined exactly, POSTAL_BOX — PO box, UNDEF_05 — not determined. Our practice shows that 70% of UNDEF_05 errors arise from typos in the locality name or missing street. We recommend implementing address autocomplete via FIAS or Dadata services before sending for normalization. To calculate the tariff, send a POST request to /tariff, specifying the sender and recipient indices, shipment type, and weight. Type POSTAL_PARCEL is a regular parcel, ECOM_MARKETPLACE is for marketplaces (requires a separate contract), EMS is expedited mail.

Creating an order and obtaining a tracking number

The process is two-step: first create the order in the backlog, then add it to a batch—only then is the tracking number assigned. We combined both steps into one block:

public function createOrder(Order $order): array { $payload = [[ 'order-num' => (string)$order->id, 'index-to' => $order->normalized_index, 'mass' => (int)($order->total_weight_kg * 1000), 'recipient-name' => $order->recipient_name, 'tel-address' => preg_replace('/\D/', '', $order->recipient_phone), 'mail-type' => 'POSTAL_PARCEL', // ... and other fields from documentation ]]; $response = $this->request('PUT', '/user/backlog', $payload); } public function createBatch(string $mailType, string $mailCategory, string $fromIndex): string { $response = $this->request('POST', '/batch', [ 'mail-type' => $mailType, 'mail-category' => $mailCategory, 'send-date' => now()->format('Y-m-d'), ]); return $response['batch-name']; } 

After adding to the batch, orders are assigned tracking numbers (14-digit barcode), which can be printed and affixed to the parcel. Batch printing labels is supported through the API. Note: for marketplaces, the ECOM_MARKETPLACE tariff is required, obtained through a separate contract—without it, tariff calculation may be incorrect.

Tracking by tracking number

Russian Post provides a separate tracking API (tracking.pochta.ru). Free quota is 100 requests per day per tracking number. If your store ships hundreds of parcels, we recommend caching tracking results or renting a dedicated tariff.

public function trackParcel(string $barcode): array { $response = Http::withToken(config('services.russian_post.tracking_token')) ->get('https://tracking.pochta.ru/tracking/api/v1/operations-history', [ 'Barcode' => $barcode, 'Language' => 'RUS', ]); return collect($response->json('OperationHistoryData.historyRecord')) ->map(fn($op) => [ 'date' => $op['OperationParameters']['OperDate'], 'type' => $op['OperationParameters']['OperType']['Name'], 'attribute' => $op['OperationParameters']['OperAttr']['Name'], ]) ->toArray(); } 

Step-by-step testing guide

  1. Obtain test credentials in the sandbox (provided upon request when concluding a contract).
  2. Create an order with a normalized address via the /user/backlog method.
  3. Add the order to a batch via /batch and obtain a test tracking number.
  4. Call the tracking API with this tracking number and verify that the status changes correctly.
  5. Test tariff calculation for different shipment types and weights (e.g., 500g vs 2kg).

Common integration errors

Error Cause Solution
UNDEF_05 Address not found Check address normalization; use autocomplete
Invalid shipment type Unsupported mail-type specified Use POSTAL_PARCEL or ECOM_MARKETPLACE
Tracking quota exceeded More than 100 requests per day per tracking number Implement caching or increase quota

Why the Russian Post API is more complex than CDEK

CDEK requires one request to create an order and immediately returns a tracking number. Russian Post requires at least two requests (backlog + batch). Additionally, address normalization is mandatory. However, Russian Post's coverage is three times larger: post offices exist even in locations without courier services. For online stores selling nationwide, this is critical. If you have encountered UNDEF_05 errors or cannot configure tariffs, contact us—we will audit your integration and fix the issues.

What is included in the integration service?

Stage Content Estimated Time
Analysis Review business processes, select API methods, prepare documentation 1–2 days
Development Implement tariff calculation, address normalization, order creation 6–8 days
Testing Sandbox testing, integration testing 2–3 days
Deployment Configure access rights, caching, monitoring 1 day
Support Team training, documentation, warranty support for 2 weeks included

The service includes documentation, access credentials setup, team training, and two weeks of post-launch support. Additional deliverables: detailed API documentation, optimization recommendations for high-volume shipments (e.g., batching strategies to reduce costs by up to 30%).

Timeline: Basic integration (tariff calculation only) — from 3 business days. Full integration with order creation and tracking — 10–14 business days. Cost starts at $500 for basic integration. Official Russian Post API documentation. With proper tariff configuration, you can save significantly on each parcel. Contact us to discuss your project and get a consultation. Order integration—we will select the optimal solution within one day.