Search by

beziworld / laravel-globkurier

kamcw

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.

Package info

github.com/Beziworld/laravel-globkurier

Homepage

Issues

pkg:composer/beziworld/laravel-globkurier

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

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

This package is auto-updated.

Last update: 2026-11-10 18:47:29 UTC


README

tests Latest Version License

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

Polska wersja dokumentacji

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.

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.