Search by

beziworld / laravel-polkurier

kamcw

Polkurier.pl WebService API client for Laravel: carriers, price valuation, orders, labels, handover protocols, courier pickups, tracking, COD details, parcel points and address book.

Package info

github.com/Beziworld/laravel-polkurier

Homepage

Issues

pkg:composer/beziworld/laravel-polkurier

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

v1.0.0 2026-11-10 18:14 UTC

This package is auto-updated.

Last update: 2026-11-10 18:14:39 UTC


README

tests Latest Version License

Polkurier.pl WebService API client for Laravel. Polkurier ships parcels, envelopes and pallets with DPD, InPost, DHL, UPS, Raben and other carriers on Polkurier's prices:

  • carriers with their services, shipment types, pickup rules and carrier specific fields
  • price valuation of every carrier (order_valuation_v2) and a cheapest-offer helper
  • orders with COD, insurance, additional services, cover address, points and external order ids
  • labels and handover protocols (PDF), cancellation
  • courier pickup hours, pickup days and multi-order pickups
  • status, order details with waybills, payment state, itemised price and COD settlement history
  • courier points and parcel lockers, countries, localities by postal code, points map token
  • address book, COD bank accounts (with two-factor confirmation) and pack templates
  • several accounts (named connections or runtime credentials) and a status poller with events

Polska wersja dokumentacji

Why this package

The official polkurier/polkurier-sdk is a framework-agnostic PHP 5.6 SDK built on raw cURL with mutable setter objects. This package talks to the same API through the Laravel HTTP client, so every call can be faked with Http::fake(), and adds immutable DTOs (amounts as decimal strings, dates in Europe/Warsaw), typed exceptions with the API error codes, safe retries of read-only methods, configuration, a facade, multiple accounts and a scheduler-friendly status poller. Request shapes follow the official PDF documentation (version 1.14) and the SDK.

Installation

composer require beziworld/laravel-polkurier
php artisan vendor:publish --tag=polkurier-config   # optional
POLKURIER_LOGIN=123456          # account id
POLKURIER_TOKEN=...             # Panel klienta > Ustawienia > Token API
POLKURIER_SANDBOX=false         # true = api-sandbox.polkurier.pl (access from api@polkurier.pl)

Prices and carriers

use Beziworld\Polkurier\Data\Address;
use Beziworld\Polkurier\Data\OrderRequest;
use Beziworld\Polkurier\Data\Pack;
use Beziworld\Polkurier\Enums\Service;
use Beziworld\Polkurier\Facades\Polkurier;

$carriers = Polkurier::carriers(details: true);         // list<Carrier>
$dpd = Polkurier::carrier('DPD');
$dpd?->supportsCod();
$dpd?->supportsService('ROD');
$dpd?->additionalFields();                               // carrier specific order fields

$quote = new OrderRequest(
    sender: Address::postcode('63-400'),
    recipient: Address::postcode('60-001'),
    packs: [new Pack(length: 30, width: 20, height: 10, weight: 2.5)],
    services: [Service::SmsNotification],
);

foreach (Polkurier::valuation($quote) as $price) {
    $price->carrier;        // "DPD"
    $price->priceGross;     // "14.76"
    $price->available;      // false with $price->unavailableMessage when the carrier cannot take it
}

$best = Polkurier::cheapest($quote);

Orders, labels and protocols

use Beziworld\Polkurier\Data\Cod;
use Beziworld\Polkurier\Data\Pickup;
use Beziworld\Polkurier\Enums\CodReturnTime;

$order = Polkurier::createOrder(new OrderRequest(
    sender: new Address('Jan Kowalski', 'Kurierska', '1', '63-400', 'Ostrów Wielkopolski', '500600700', 'shop@example.com', company: 'ACME'),
    recipient: new Address('Anna Nowak', 'Poznańska', '12', '60-001', 'Poznań', '600700800', 'anna@example.com', pointId: 'POZ01M'),
    packs: [new Pack(30, 20, 10, 2.5)],
    courier: 'INPOST_PACZKOMAT',
    description: 'Books',
    cod: new Cod('149.99', 'PL61109010140000071219812874', CodReturnTime::OneDay),
    insurance: 200,
    pickup: Pickup::dropOff(),                 // or Pickup::at('2026-11-12', '10:00', '14:00') or Pickup::multi()
    externalApplicationId: 'my-shop',
    externalOrderId: 'A-1001',
));

$order->orderNumber;   // "1234-10"
$order->waybill();     // "13299300045383"
$order->priceGross;    // "12.30"

$pdf = Polkurier::label($order->orderNumber);              // or label(['1234-10', '1234-11']) merged into one PDF
$protocol = Polkurier::protocol(['1234-10', '1234-11']);

Polkurier::cancelOrder('1234-10');                         // orders waiting for payment or confirmed

createOrder(), cancelOrder(), multiPickup() and the save and delete methods are never repeated automatically. Read-only methods are repeated after connection errors and HTTP 5xx (POLKURIER_RETRIES).

Pickups

use Beziworld\Polkurier\Enums\ShipmentType;

$day = Polkurier::pickupHours('DPD', '2026-11-12', '63-400');     // PickupDate: available, windows
$days = Polkurier::pickupDates('DPD', ShipmentType::Box, '63-400'); // next five working days

// Orders created with Pickup::multi() share one courier pickup:
$waiting = Polkurier::orders(['status' => 'PZ']);
$result = Polkurier::multiPickup(['1234-56', '1234-78'], '2026-11-12', '10:00', '15:00');
$result->failed;   // ['1234-78' => 'error message']

Tracking, order details and COD

$status = Polkurier::status('1234-10');
$status->code;            // OrderStatus::InTransit
$status->trackingUrl;

$details = Polkurier::order('1234-10');
$details->waybills;       // default waybill first
$details->isPaid;
$details->items;          // itemised price
$details->cod?->status;   // CodStatus::Paid
$details->cod?->operations;  // payouts, compensations and fees
$details->cod?->paidOut();   // "70.00"

$page = Polkurier::orders(['date_from' => now()->subWeek(), 'courier' => 'DPD'], page: 1, pageSize: 100);

Polkurier has no webhooks. Schedule the poller to receive OrderStatusChanged events:

// routes/console.php
Schedule::command('polkurier:poll-statuses --pages=2')->everyFifteenMinutes();

// a listener
Event::listen(function (\Beziworld\Polkurier\Events\OrderStatusChanged $event) {
    $event->order->number;
    $event->order->statusCode;     // new status
    $event->previousStatus;        // e.g. "OC"
});

Points, countries and dictionaries

use Beziworld\Polkurier\Enums\PointFunction;

$lockers = Polkurier::points('INPOST_PACZKOMAT', search: 'Poznań', functions: [PointFunction::Cod], limit: 50);
$point = Polkurier::point('INPOST_PACZKOMAT', 'POZ01M');

Polkurier::countries('UPS_EX');       // ['DE' => 'Niemcy', ...]
Polkurier::supportedCountries();      // list<Country> with provinces
Polkurier::cities('63-400');          // ['Ostrów Wielkopolski', ...]
Polkurier::mapToken();                // JWT for the Polkurier points map widget (valid 4 hours)

Account data

use Beziworld\Polkurier\Data\AddressBookEntry;
use Beziworld\Polkurier\Data\BankAccount;
use Beziworld\Polkurier\Enums\AddressType;

Polkurier::addresses(AddressType::Sender);
Polkurier::saveAddress(new AddressBookEntry(AddressType::Sender, $address, name: 'Warehouse', default: true));

$session = Polkurier::requestTwoFactorCode();          // SMS code to the account phone
Polkurier::saveBankAccount(new BankAccount('PL61109010140000071219812874', 'Main'), $session->token, $codeFromUser);

Polkurier::packTemplates();

Several accounts

// config/polkurier.php: 'connections' => ['default' => [...], 'second' => ['login' => ..., 'token' => ...]]
Polkurier::connection('second')->createOrder($request);

// credentials stored per tenant
Polkurier::using(['login' => $tenant->polkurier_login, 'token' => $tenant->polkurier_token])->valuation($quote);

Any other method: Polkurier::call('get_couriers_messages', ['courier' => 'DPD']) returns the response part.

Errors

Exception When
ApiException the envelope status is error: errorCode() (e.g. ERROR_AUTH_DATA), statusCode() (e.g. 7), validationErrors(), method(), isAuthenticationError(), isRateLimited() with retryAfter() (60 s), isMaintenance(), isNotFound(); also transport errors and HTTP errors without an envelope
InvalidConfiguration missing login or token, unknown connection

All exceptions extend PolkurierException. Business errors such as missing funds or a refusal by the carrier come with the message only (errorCode() is null). The API accepts 500 requests per minute per IP address; after TOO_MANY_REQUESTS pause every request for at least 60 seconds.

Development

composer install
composer ci   # pint --test, phpstan (level 8), pest

Author

Created and maintained by Kamil Ćwiertnia, beziworld.eu.

Need an integration? Get in touch through beziworld.eu.

Other packages by the author

laravel-apaczka · laravel-furgonetka · laravel-globkurier · laravel-inpost · laravel-dpd

License

MIT. See LICENSE.md. This package is not affiliated with Polkurier.pl.