beziworld / laravel-globkurier
GlobKurier.pl REST API v1 client for Laravel: product search and quotes, add-ons, orders, best price orders, labels, protocols, courier pickups, tracking, points and dictionaries.
Requires
- php: ^8.3
- ext-json: *
- guzzlehttp/guzzle: ^7.8
- illuminate/cache: ^12.0|^13.0
- illuminate/console: ^12.0|^13.0
- illuminate/contracts: ^12.0|^13.0
- illuminate/events: ^12.0|^13.0
- illuminate/http: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.18
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.7|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
- phpstan/phpstan-strict-rules: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-10 18:47:29 UTC
README
GlobKurier.pl REST API v1 client for Laravel. GlobKurier compares and books domestic and international shipments with InPost, DPD, ORLEN Paczka, FedEx, UPS, Poczta Polska and many more carriers:
- login with e-mail and password, cached token, automatic new login after HTTP 401
- product search with prices (guest or account prices), cheapest product, add-ons with COD and insurance ranges
- order validation, order price, payment methods and order creation
- simplified best price orders (quote only or order passed to the carrier at once)
- labels (A4 or Zebra) and handover protocols as PDF, courier pickup windows and re-ordered pickups
- order details by hash or number, cancellation, tracking of one or many orders
- drop-off and pick-up points, countries (ISO codes resolved to GlobKurier ids), states, cities, carriers, agreements
- several accounts (named connections or runtime credentials) and a tracking poller with events
Why this package
There is no PHP or Laravel package for GlobKurier on Packagist; the existing integrations are shop plugins
(PrestaShop, WooCommerce). This package covers the full integration path of the official documentation at
developer.globkurier.pl: products, add-ons, prices, orders, labels and tracking,
with immutable DTOs (amounts as decimal strings, dates in Europe/Warsaw), typed exceptions with field errors,
safe retries of GET requests only and tests on Http::fake().
Installation
composer require beziworld/laravel-globkurier
php artisan vendor:publish --tag=globkurier-config # optional
GLOBKURIER_EMAIL=shop@example.com # GlobKurier.pl account GLOBKURIER_PASSWORD=... GLOBKURIER_SANDBOX=false # true = test.api.globkurier.pl (production account at least one day old) GLOBKURIER_LANGUAGE=pl # pl | en GLOBKURIER_PAYMENT_ID=3 # 3 or 9: prepaid balance, the waybill is generated at once GLOBKURIER_CACHE_STORE=redis # token and country list cache (default store when empty)
Without credentials only public resources work: countries, guest product search, points and tracking. Every order
is sent with the consents from config('globkurier.agreements') (receiveElectronicBills, processingPersonalData)
unless the order defines its own; check the current list with GlobKurier::agreements('order').
Find a product and its add-ons
use Beziworld\GlobKurier\Data\ProductQuery; use Beziworld\GlobKurier\Enums\CollectionType; use Beziworld\GlobKurier\Facades\GlobKurier; $query = new ProductQuery( length: 30, width: 20, height: 10, weight: 1.5, senderCountry: 'PL', receiverCountry: 'PL', // ISO codes or GlobKurier ids senderPostCode: '00-001', receiverPostCode: '30-001', collectionTypes: [CollectionType::Pickup], deliveryTypes: [CollectionType::Point], addonCategories: ['CASH_ON_DELIVERY'], ); $products = GlobKurier::products($query); // list<Product>, every delivery time group $product = GlobKurier::cheapestProduct($query, 'DPD'); $product->id; // productId for add-ons, points, prices and the order $product->grossPrice; // "12.40" with the fuel surcharge $addons = GlobKurier::addons($product->id, $query, cashOnDeliveryValue: 149.99, insuranceValue: 149.99); $cod = $addons->cheapestFor('CASH_ON_DELIVERY', 149.99); $insurance = $addons->cheapestFor('INSURANCE', 149.99); // required together with COD
Place an order
use Beziworld\GlobKurier\Data\Address; use Beziworld\GlobKurier\Data\AddonSelection; use Beziworld\GlobKurier\Data\OrderRequest; use Beziworld\GlobKurier\Data\Pickup; $sender = new Address('ACME Sp. z o.o.', 'Prosta', '1', '00-001', 'Warszawa', '500600700', 'shop@example.com'); $receiver = new Address('Anna Kowalska', 'Długa', '5', '30-001', 'Kraków', '600700800', 'anna@example.com', pointId: 'KRA01M'); $windows = GlobKurier::pickupTimeRanges($product->id, $sender, $receiver, today(), weight: 1.5); $request = new OrderRequest( productId: $product->id, length: 30, width: 20, height: 10, weight: 1.5, sender: $sender, receiver: $receiver, content: 'Books', collectionType: CollectionType::Pickup, deliveryType: CollectionType::Point, pickup: Pickup::fromWindow($windows[0]), addons: [ AddonSelection::insurance($insurance->id, 149.99), AddonSelection::cashOnDelivery($cod->id, 149.99, 'PL61109010140000071219812874', 'ACME Sp. z o.o.', 'Prosta 1, 00-001 Warszawa'), ], referenceNumber: 'ORDER-1001', ); GlobKurier::validateOrder($request); // ApiException with fieldErrors() when invalid $price = GlobKurier::orderPrice($request, cashOnDeliveryValue: 149.99, insuranceValue: 149.99); $order = GlobKurier::createOrder($request); // never repeated automatically $order->number; // "GK260520647801", used for tracking $order->hash; // used for labels, protocols, cancellation and GET /order $order->price?->totalGross; $pdf = GlobKurier::labels($order->hash); // LabelFormat::ZebraPrinter for label printers $protocol = GlobKurier::protocol([$order->hash]);
Use GlobKurier::customRequiredFields($productId, 'PL', 'DE') to learn whether a product needs points, states,
the declared value or the purpose, and pass the customs declaration in customs for shipments outside the EU.
Best price orders
The simplified endpoint finds the cheapest offer of a carrier itself; it takes integration names, ISO country codes and add-on categories:
$order = [ 'shipment' => ['length' => 10, 'width' => 10, 'height' => 10, 'weight' => 1, 'quantity' => 1, 'integrationName' => 'inPost-Paczkomaty'], 'senderAddress' => $sender, 'receiverAddress' => $receiver, 'content' => 'Books', 'collectionType' => 'PICKUP', 'deliveryType' => 'POINT', 'addons' => ['INSURANCE' => ['value' => 100]], ]; $quote = GlobKurier::bestPriceQuote($order); // Price $placed = GlobKurier::bestPriceOrder($order); // createFully: the carrier gets the order at once $placed->trackingNumber; $placed->label; // PDF when the carrier returned it
Orders, pickups and tracking
$details = GlobKurier::order($hash); // or orderByNumber('GK...') when logged in $details->status; // OrderStatus::InTransit $details->documentLink('WAYBILL'); $details->cashOnDelivery(); // COD add-on with its payout status GlobKurier::orderPickup($hash); // order the courier again GlobKurier::cancelOrder($hash); // poll order() until the status is CANCELED $tracking = GlobKurier::tracking('GK260520647801'); $tracking->latest?->type; // e.g. "IN_TRANSIT" $tracking->waybillNumber(); $many = GlobKurier::trackingMany(['GK1', 'GK2']); // one request
GlobKurier has no webhooks. Schedule the tracking command for orders in transit and listen to
ShipmentStatusChanged:
Schedule::command('globkurier:track', $openOrderNumbers)->hourly(); Event::listen(function (\Beziworld\GlobKurier\Events\ShipmentStatusChanged $event) { $event->tracking->number; $event->tracking->latest?->type; $event->previousStatus; });
app(TrackingPoller::class)->poll($numbers) does the same from your own job.
Points and dictionaries
use Beziworld\GlobKurier\Enums\PointAddressType; GlobKurier::points($product->id, ['city' => 'Kraków'], PointAddressType::Receiver); GlobKurier::points('inPost-Paczkomaty', ['postCode' => '30-001', 'serviceCode' => 'APM']); GlobKurier::point($product->id, 'KRA01M'); GlobKurier::countries(); // cached for a day GlobKurier::countryId('DE'); // 23 GlobKurier::cities('PL', '30-001'); GlobKurier::carriers(deliveryTypes: [CollectionType::Point], addonCategories: ['CASH_ON_DELIVERY']); GlobKurier::contents(); GlobKurier::request('GET', 'user/stats'); // any other endpoint
Several accounts
// config/globkurier.php: 'connections' => ['default' => [...], 'second' => ['email' => ..., 'password' => ...]] GlobKurier::connection('second')->products($query); GlobKurier::using(['email' => $tenant->gk_email, 'password' => $tenant->gk_password])->createOrder($request);
Errors
| Exception | When |
|---|---|
ApiException |
HTTP errors: httpStatus(), fieldErrors() (field => message), messages(), payload(), isValidationError(), isUnauthorized(), isNotFound(), isRateLimited() with retryAfter(); transport errors; non-PDF label responses |
AuthenticationException |
wrong e-mail or password |
InvalidConfiguration |
e-mail without password (or the other way round), unknown connection, unknown ISO country code |
All exceptions extend GlobKurierException. GET requests are repeated after connection errors and HTTP 5xx
(GLOBKURIER_RETRIES); POST, PUT and DELETE requests never are.
Development
composer install
composer ci # pint --test, phpstan (level 8), pest
Author
Created and maintained by Kamil Ćwiertnia, beziworld.eu.
- E-mail: biuro@beziworld.eu
- Issues: GitHub issues
Need an integration? Get in touch through beziworld.eu.
Other packages by the author
laravel-apaczka · laravel-furgonetka · laravel-polkurier · laravel-inpost · laravel-dpd
License
MIT. See LICENSE.md. This package is not affiliated with GlobKurier.pl.