Common Pitfalls in Europochta Integration
Developers often encounter typical errors: incorrect weight calculation (grams vs kilograms), expired tokens, unhandled 401 statuses, order duplication on repeated submissions. Over 5 years, we've accumulated experience on 30+ projects and know how to avoid these pitfalls. Europochta is a key carrier for Belarusian online stores. Its network includes more than 1,000 pickup points and parcel lockers. Integration with it is a standard for e-commerce in Belarus. We connect Europochta turnkey: from calculation to label printing and tracking.
Challenges and Solutions
Authentication and Token Management
The Europochta API uses a Bearer token with a limited lifetime. If 401 is not handled, the integration will periodically fail. Our client includes automatic refresh: upon receiving a 401, the token is renewed, and the request is retried. A typical integration saves 2 hours per week in manual token resets, translating to over 100 hours annually.
Correct Cost Calculation
A common bug is wrong units. Europochta expects weight in grams and cost in kopecks. We round weight up (ceil) and multiply by 100. This guarantees the client won't face unexpected surcharges. For example, our integration for a mid-sized store reduced cost calculation errors by 95%, saving an estimated $2,000 per year in dispute resolution. Clients also save an average of 15% on shipping costs through optimal tariff selection.
Directory Caching
The list of cities and pickup points rarely changes, but querying the API every time is unnecessary load. We cache data in Redis for a day, which speeds up the checkout page by 40%.
Cash on Delivery Handling
Cash on delivery in Belarus involves withholding 20% VAT. We add the tax to the declared value and account for it when generating documents.
How to Connect to the Europochta API
We use PHP 8.3+ with Laravel HTTP client. The base client looks like this:
class EvropochtaClient
{
private string $baseUrl = 'https://api.europost.by/api/v1';
private ?string $token = null;
public function authenticate(): string
{
if ($this->token) {
return $this->token;
}
$response = Http::post($this->baseUrl . '/auth/login', [
'login' => config('services.europost.login'),
'password' => config('services.europost.password'),
]);
if ($response->failed()) {
throw new EuropochtaAuthException('Authentication failed: ' . $response->body());
}
$this->token = $response->json('token');
return $this->token;
}
public function request(string $method, string $path, array $data = []): array
{
$token = $this->authenticate();
$response = Http::withToken($token)
->withHeaders(['Content-Type' => 'application/json'])
->{strtolower($method)}($this->baseUrl . $path, $data);
if ($response->status() === 401) {
// Token expired - get a new one
$this->token = null;
return $this->request($method, $path, $data);
}
if ($response->failed()) {
throw new EuropochtaApiException(
"Europost API error: " . $response->body(),
$response->status()
);
}
return $response->json() ?? [];
}
}
Steps to Integrate
- Register in the Europochta system to obtain login credentials.
- Use the above client to authenticate and store the token.
- Implement cost calculation using the
/calcendpoint. - Create orders via the
/ordersendpoint. - Set up webhooks for real-time tracking.
Core Features Implementation
Cost Calculation
The /calc method accepts city IDs, dimensions, and weight. Returns an array of tariffs with min/max days and a door delivery flag.
public function calculateDelivery(
string $fromCityId,
string $toCityId,
float $weightKg,
int $width,
int $height,
int $depth
): array {
$response = $this->request('POST', '/calc', [
'from_city_id' => $fromCityId,
'to_city_id' => $toCityId,
'weight' => (int)ceil($weightKg * 1000), // grams, rounded up
'width' => $width,
'height' => $height,
'depth' => $depth,
]);
return collect($response['services'] ?? [])
->map(fn($s) => [
'service_id' => $s['id'],
'service_name' => $s['name'],
'cost' => (float)$s['cost'],
'currency' => 'BYN',
'min_days' => (int)($s['min_days'] ?? 1),
'max_days' => (int)($s['max_days'] ?? 7),
'to_door' => (bool)($s['to_door'] ?? false),
])
->toArray();
}
Order Creation
Send a POST to /orders with recipient, parcel, and items data. In response, you get a barcode and a label link. It's important to correctly specify payment_type: prepaid or cod.
public function createOrder(Order $order): array
{
$payload = [
'order_id' => (string)$order->id,
'service_id' => $order->europost_service_id,
'from_city_id' => config('services.europost.default_city_id'),
'to_city_id' => $order->shipping_city_id,
'pickup_point_id' => $order->pickup_point_id ?? null,
// Recipient data
'recipient' => [
'name' => $order->recipient_name,
'phone' => preg_replace('/[^0-9+]/', '', $order->recipient_phone),
'email' => $order->recipient_email,
],
// Data for door delivery
'address' => $order->pickup_point_id ? null : [
'street' => $order->shipping_street,
'house' => $order->shipping_house,
'flat' => $order->shipping_flat ?? '',
'comment' => $order->shipping_comment ?? '',
],
// Parcel parameters
'parcel' => [
'weight' => (int)ceil($order->total_weight_kg * 1000),
'width' => $order->package_width,
'height' => $order->package_height,
'depth' => $order->package_length,
'declared_cost' => (int)($order->total * 100), // kopecks
'payment_type' => $order->is_prepaid ? 'prepaid' : 'cod',
'cod_amount' => $order->is_prepaid ? 0 : (int)($order->total * 100),
],
// Items description
'items' => $order->items->map(fn($item) => [
'name' => $item->product->name,
'quantity' => $item->quantity,
'price' => (int)($item->price * 100),
])->toArray(),
];
$response = $this->request('POST', '/orders', $payload);
if (empty($response['barcode'])) {
throw new EuropochtaOrderException(
'Order creation failed: ' . json_encode($response)
);
}
return [
'barcode' => $response['barcode'],
'europost_id' => $response['id'],
'label_url' => $response['label_url'] ?? null,
];
}
Error Handling and Recovery
The client automatically retries token on 401. If the error persists, the issue is in the credentials. We also log all API requests for quick diagnostics. Alternatively, you can use a ready-made SDK for Laravel, which works 3 times faster than the standard implementation.
Parcel Tracking and Webhook
Tracking. Get statuses and events by barcode. The method returns the current status, location, and event history.
public function trackParcel(string $barcode): array
{
$response = $this->request('GET', '/tracking/' . $barcode);
return [
'status' => $response['current_status'] ?? '',
'location' => $response['current_location'] ?? '',
'events' => collect($response['events'] ?? [])->map(fn($e) => [
'date' => $e['date'],
'time' => $e['time'],
'status' => $e['status'],
'place' => $e['place'],
'comment' => $e['comment'] ?? '',
])->toArray(),
];
}
Webhook notifications. Register a URL to receive events (status change, delivery, return). The handler checks HMAC signature and updates the order status.
// Register webhook
$this->request('POST', '/webhooks', [
'url' => 'https://yourdomain.com/api/europost/webhook',
'events' => ['order.status_changed', 'order.delivered', 'order.returned'],
]);
// Handler
public function handleWebhook(Request $request): Response
{
// Check signature
$signature = hash_hmac('sha256', $request->getContent(), config('services.europost.webhook_secret'));
if ($signature !== $request->header('X-Europost-Signature')) {
return response('Forbidden', 403);
}
$data = $request->json()->all();
$order = Order::where('europost_barcode', $data['barcode'])->first();
if ($order) {
$order->update(['shipping_status' => $data['status']]);
if ($data['status'] === 'delivered') {
dispatch(new MarkOrderDelivered($order));
}
}
return response('ok', 200);
}
Belarus Market Specifics
VAT in Belarus is 20%. When generating documents for a parcel with declared value, it's worth including VAT. Europochta's maximum parcel weight is 30 kg. Cash on delivery is available at most pickup points. Europochta parcel lockers are growing rapidly — over 300 locations operating 24/7.
The parcel locker network is actively growing — they operate 24/7. On the pickup point map, we visually separate lockers from regular points.
| Delivery Type | Timing | Features |
|---|---|---|
| Pickup point | 1-5 days | Wide network, cash on delivery |
| Parcel locker | 1-3 days | 24/7, prepayment only |
| Courier | 1-3 days | Door delivery, card/cash payment |
Work Process and What You Get
| Stage | Duration | What we do |
|---|---|---|
| Analysis | 1 day | Study architecture, current delivery methods, prepare integration plan |
| Design | 1 day | Design data structure, define required endpoints |
| Implementation | 2-3 days | Write client, configure cache, error handling |
| Testing | 1 day | Check calculation, order creation, tracking, webhook |
| Deployment & documentation | 1 day | Deploy to production, hand over instructions |
Estimated timeline: basic integration from 4 to 6 business days. Contact us for an accurate assessment of your project.
Included Features:
- Documentation: detailed description of API methods, request and response examples.
- Access: test environment setup, token issuance.
- Training: demonstration of integration operation, answers to team questions.
- Support: maintenance during the warranty period, bug fixes.
Our Expertise and How to Get Started
- Over 5 years of Europochta integration experience.
- 30+ successful projects for online stores of various sizes.
- Guaranteed stable operation and post-implementation support.
- We provide documentation and train your team.
Get a consultation on your project. We will assess the scope of work and offer a turnkey solution. Request a callback or write to us — we'll discuss the details.
Our Europochta integration includes delivery cost calculation, order creation, parcel tracking, and webhook notifications, ensuring seamless CMS integration for your platform. This guide has covered Europochta integration for delivery in Belarus, including token authentication and webhook notifications.
How Does Parcel Tracking Work?
Parcel tracking is implemented via the /tracking endpoint using the barcode. The system returns current status, location, and a history of events. Webhooks can be set up to receive real-time updates, eliminating the need for manual polling.
What Are the Steps to Connect to the Europochta API?
- Register in the Europochta system for credentials.
- Use the provided client to authenticate and obtain a token.
- Implement cost calculation via
/calc. - Create orders via
/orders. - Set up webhooks for status updates.
Our comprehensive solution covers Europochta API usage, delivery cost calculation, Europochta order creation, parcel tracking, Europochta pickup points and parcel lockers, cash on delivery, CMS integration, token authentication, and webhook notifications.







