# Balikobot API Balikobot API is a PHP library that provides a comprehensive implementation of the Balikobot API v2 for managing shipments with multiple delivery carriers in Czech Republic and Slovakia. The library offers services for creating packages, ordering shipments, tracking deliveries, and managing pickup points across dozens of supported carriers including Czech Post (CP), DPD, GLS, PPL, Zasilkovna, and many more. The library follows modern PHP practices with full type support, interfaces for all services, and factory patterns for model creation. It integrates seamlessly with popular PHP frameworks (Symfony, Laravel, Nette) and can also be used standalone. All API responses are normalized into strongly-typed model objects, making it easy to work with package data, tracking statuses, branches, and shipment orders. ## Client Setup The DefaultClient handles all HTTP communication with the Balikobot API, managing authentication and request validation. ```php use Inspirum\Balikobot\Client\DefaultClient; use Inspirum\Balikobot\Client\DefaultCurlRequester; use Inspirum\Balikobot\Client\Response\Validator; use Inspirum\Balikobot\Model\Label\DefaultLabelFactory; use Inspirum\Balikobot\Model\OrderedShipment\DefaultOrderedShipmentFactory; use Inspirum\Balikobot\Model\Package\DefaultPackageFactory; use Inspirum\Balikobot\Model\PackageData\DefaultPackageDataFactory; use Inspirum\Balikobot\Model\ProofOfDelivery\DefaultProofOfDeliveryFactory; use Inspirum\Balikobot\Model\Status\DefaultStatusFactory; use Inspirum\Balikobot\Model\TransportCost\DefaultTransportCostFactory; use Inspirum\Balikobot\Service\DefaultPackageService; use Inspirum\Balikobot\Service\DefaultTrackService; use Inspirum\Balikobot\Service\DefaultBranchService; // Initialize the API client with credentials $apiUser = getenv('BALIKOBOT_API_USER'); $apiKey = getenv('BALIKOBOT_API_KEY'); $requester = new DefaultCurlRequester($apiUser, $apiKey, sslVerify: true); $validator = new Validator(); $client = new DefaultClient($requester, $validator); // Create the package service $packageService = new DefaultPackageService( $client, new DefaultPackageDataFactory(), new DefaultPackageFactory($validator), new DefaultOrderedShipmentFactory(), new DefaultLabelFactory(), new DefaultProofOfDeliveryFactory($validator), new DefaultTransportCostFactory($validator), ); // Create the track service $trackService = new DefaultTrackService( $client, new DefaultStatusFactory($validator), ); ``` ## addPackages Creates new packages for a specific carrier. Packages are defined using PackageData objects collected in a PackageDataCollection, and the method returns a PackageCollection containing the created packages with their IDs, tracking URLs, and label URLs. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Currency; use Inspirum\Balikobot\Definitions\Service; use Inspirum\Balikobot\Model\PackageData\DefaultPackageData; use Inspirum\Balikobot\Model\PackageData\DefaultPackageDataCollection; // Create package collection for Czech Post carrier $packagesData = new DefaultPackageDataCollection(Carrier::CP); // Create first package with COD (cash on delivery) $packageData = new DefaultPackageData(); $packageData->setServiceType(Service::CP_NP); $packageData->setRecName('Josef Novak'); $packageData->setRecStreet('Ulice 123'); $packageData->setRecCity('Praha'); $packageData->setRecZip('11000'); $packageData->setRecCountry(Country::CZECH_REPUBLIC); $packageData->setRecPhone('776555888'); $packageData->setRecEmail('josef.novak@example.com'); $packageData->setCodPrice(1399.00); $packageData->setCodCurrency(Currency::CZK); $packageData->setPrice(1500.00); $packageData->setReturnFullErrors(); $packagesData->add($packageData); // Create second package without COD $packageData2 = new DefaultPackageData(); $packageData2->setServiceType(Service::CP_NP); $packageData2->setRecName('Jana Novakova'); $packageData2->setRecStreet('Jina Ulice 456'); $packageData2->setRecCity('Brno'); $packageData2->setRecZip('60200'); $packageData2->setRecCountry(Country::CZECH_REPUBLIC); $packageData2->setRecPhone('777666555'); $packageData2->setPrice(299.00); $packagesData->add($packageData2); // Upload packages to Balikobot $packages = $packageService->addPackages($packagesData); // Access package information echo "Labels URL: " . $packages->getLabelsUrl() . "\n"; echo "Package IDs: " . implode(', ', $packages->getPackageIds()) . "\n"; foreach ($packages as $package) { echo "Package ID: " . $package->getPackageId() . "\n"; echo "Carrier ID: " . $package->getCarrierId() . "\n"; echo "Track URL: " . $package->getTrackUrl() . "\n"; echo "Label URL: " . $package->getLabelUrl() . "\n"; } /* Output: Labels URL: https://pdf.balikobot.cz/cp/eNorMTIwt9A1NbYwMwVcMBAXAC9. Package IDs: 42718, 42719 Package ID: 42718 Carrier ID: NP1504102232M Track URL: https://www.postaonline.cz/trackandtrace/-/zasilka/cislo?parcelNumbers=NP1504102232M Label URL: https://pdf.balikobot.cz/cp/eNorMTIwt9A1NbYwMwVcMBAXAn4. */ ``` ## checkPackages Validates package data before submission without actually creating the packages. Throws an exception with detailed error messages if validation fails. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Service; use Inspirum\Balikobot\Exception\Exception; use Inspirum\Balikobot\Model\PackageData\DefaultPackageData; use Inspirum\Balikobot\Model\PackageData\DefaultPackageDataCollection; $packagesData = new DefaultPackageDataCollection(Carrier::CP); $packageData = new DefaultPackageData(); $packageData->setServiceType(Service::CP_NP); $packageData->setRecName('Josef Novak'); $packageData->setRecZip('11000'); $packageData->setRecCountry(Country::CZECH_REPUBLIC); $packageData->setReturnFullErrors(); $packagesData->add($packageData); try { $packageService->checkPackages($packagesData); echo "Package data is valid!\n"; } catch (Exception $exception) { echo "Validation failed!\n"; echo "Status code: " . $exception->getStatusCode() . "\n"; echo "Message: " . $exception->getMessage() . "\n"; foreach ($exception->getErrors() as $error) { echo "Error: " . json_encode($error) . "\n"; } } /* Output on validation failure: Validation failed! Status code: 400 Message: Invalid package data Error: {"attribute":"rec_street","message":"Recipient street is required"} */ ``` ## orderShipment Orders a shipment for previously added packages. Returns an OrderedShipment object containing the order ID, labels URL, and handover document URL. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Service; use Inspirum\Balikobot\Model\PackageData\DefaultPackageData; use Inspirum\Balikobot\Model\PackageData\DefaultPackageDataCollection; // First create packages $packagesData = new DefaultPackageDataCollection(Carrier::PPL); $packageData = new DefaultPackageData(); $packageData->setServiceType(Service::PPL_PARCEL_BUSSINESS_CZ); $packageData->setRecName('Josef Novak'); $packageData->setRecStreet('Ulice 123'); $packageData->setRecCity('Praha'); $packageData->setRecZip('11000'); $packageData->setRecCountry(Country::CZECH_REPUBLIC); $packageData->setRecPhone('776555888'); $packageData->setPrice(500.00); $packagesData->add($packageData); $packages = $packageService->addPackages($packagesData); // Order shipment for the packages $orderedShipment = $packageService->orderShipment($packages); echo "Order ID: " . $orderedShipment->getOrderId() . "\n"; echo "Labels URL: " . $orderedShipment->getLabelsUrl() . "\n"; echo "Handover URL: " . $orderedShipment->getHandoverUrl() . "\n"; echo "File URL: " . $orderedShipment->getFileUrl() . "\n"; echo "Carrier: " . $orderedShipment->getCarrier() . "\n"; echo "Package IDs: " . implode(', ', $orderedShipment->getPackageIds()) . "\n"; /* Output: Order ID: 2757 Labels URL: https://pdf.balikobot.cz/ppl/eNorMTIwt9A1NbYwMwVcMBAXAn4. Handover URL: https://pdf.balikobot.cz/ppl/eNorMTIwt9A1NbawtARcMBAhAoU. File URL: https://csv.balikobot.cz/ppl/eNorMTIwt9A1sjAyB1wwDZECRr.. Carrier: ppl Package IDs: 43619 */ ``` ## dropPackages / dropPackage Removes packages from Balikobot that have not yet been ordered for shipment. Useful for canceling packages before they are shipped. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Service; use Inspirum\Balikobot\Model\PackageData\DefaultPackageData; use Inspirum\Balikobot\Model\PackageData\DefaultPackageDataCollection; // Create packages $packagesData = new DefaultPackageDataCollection(Carrier::GLS); $packageData = new DefaultPackageData(); $packageData->setServiceType(Service::GLS_BUSINESS); $packageData->setRecName('Josef Novak'); $packageData->setRecStreet('Ulice 123'); $packageData->setRecCity('Praha'); $packageData->setRecZip('11000'); $packageData->setRecCountry(Country::CZECH_REPUBLIC); $packageData->setPrice(250.00); $packagesData->add($packageData); $packages = $packageService->addPackages($packagesData); // Drop a single package $packageService->dropPackage($packages[0]); echo "Single package dropped successfully\n"; // Or drop all packages in collection $packages2 = $packageService->addPackages($packagesData); $packageService->dropPackages($packages2); echo "All packages dropped successfully\n"; // Drop by package ID directly $packageService->dropPackageByPackageId(Carrier::GLS, '42718'); echo "Package dropped by ID\n"; // Drop multiple packages by IDs $packageService->dropPackagesByPackageIds(Carrier::GLS, ['42719', '42720']); echo "Multiple packages dropped by IDs\n"; ``` ## trackPackage / trackPackageLastStatus Tracks package delivery status. trackPackage returns full status history while trackPackageLastStatus returns only the most recent status. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Status; // Track full package history $statuses = $trackService->trackPackage($packages[0]); echo "Carrier: " . $statuses->getCarrier() . "\n"; echo "Carrier ID: " . $statuses->getCarrierId() . "\n"; foreach ($statuses->getStates() as $status) { echo "Status ID: " . $status->getId() . "\n"; echo "Status Name: " . $status->getName() . "\n"; echo "Description: " . $status->getDescription() . "\n"; echo "Date: " . $status->getDate()->format('Y-m-d H:i:s') . "\n"; echo "Type: " . $status->getType() . "\n"; echo "---\n"; } // Track only the last status $lastStatus = $trackService->trackPackageLastStatus($packages[0]); echo "Last Status ID: " . $lastStatus->getId() . "\n"; echo "Last Status Name: " . $lastStatus->getName() . "\n"; // Check delivery status using Status helper methods if (Status::isDelivered($lastStatus->getId())) { echo "Package has been delivered!\n"; } if (Status::isError($lastStatus->getId())) { echo "Package delivery encountered an error!\n"; } if (Status::isBeingDelivered($lastStatus->getId())) { echo "Package is in transit\n"; } if ($lastStatus->getId() === Status::COD_PAID) { echo "Cash on delivery has been credited to sender's account\n"; } // Track by carrier ID directly $statusById = $trackService->trackPackageLastStatusById(Carrier::CP, 'NP1504102232M'); echo "Status: " . $statusById->getName() . "\n"; /* Output: Carrier: cp Carrier ID: NP1504102232M Status ID: 2.2 Status Name: Package delivered to recipient Description: Package delivery. (77072 - Depot Olomouc 72) Date: 2024-01-15 09:15:01 Type: event --- Last Status ID: 2.2 Last Status Name: Package delivered to recipient Package has been delivered! */ ``` ## trackPackages / trackPackagesLastStatuses Track multiple packages at once for better performance when dealing with many shipments. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Status; // Track all packages in a collection $statusesCollection = $trackService->trackPackages($packages); foreach ($statusesCollection as $statuses) { echo "Package Carrier ID: " . $statuses->getCarrierId() . "\n"; $lastState = $statuses->getStates()->getIterator()->current(); if ($lastState) { echo "Current Status: " . $lastState->getName() . "\n"; } } // Track last statuses for all packages $lastStatuses = $trackService->trackPackagesLastStatuses($packages); foreach ($lastStatuses as $status) { echo "Carrier ID: " . $status->getCarrierId() . "\n"; echo "Status: " . $status->getName() . "\n"; if (Status::isClosed($status->getId())) { echo "Delivery process completed\n"; } } // Track by carrier IDs directly $statusesByIds = $trackService->trackPackagesLastStatusesByIds( Carrier::CP, ['NP1504102232M', 'NP1504102233M', 'NP1504102234M'] ); foreach ($statusesByIds as $status) { echo $status->getCarrierId() . ": " . $status->getName() . "\n"; } ``` ## getBranches / getBranchesForCarrier Retrieves pickup point branches for carriers. Uses PHP Generators for memory-efficient iteration over large datasets. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Service; // Get all branches for a specific carrier $branches = $branchService->getBranchesForCarrier(Carrier::ZASILKOVNA); foreach ($branches as $branch) { echo "Branch ID: " . $branch->getBranchId() . "\n"; echo "Name: " . $branch->getName() . "\n"; echo "City: " . $branch->getCity() . "\n"; echo "Street: " . $branch->getStreet() . "\n"; echo "ZIP: " . $branch->getZip() . "\n"; echo "Country: " . $branch->getCountry() . "\n"; echo "UID: " . $branch->getUid() . "\n"; echo "---\n"; // Process only first 10 branches for demonstration static $count = 0; if (++$count >= 10) break; } // Get branches for specific carrier and service type $branches = $branchService->getBranchesForCarrierService( Carrier::CP, Service::CP_NB ); // Get branches filtered by countries $branches = $branchService->getBranchesForCarrierAndCountries( Carrier::ZASILKOVNA, [Country::CZECH_REPUBLIC, Country::SLOVAKIA] ); foreach ($branches as $branch) { echo $branch->getName() . " - " . $branch->getCity() . ", " . $branch->getCountry() . "\n"; } /* Output: Branch ID: 10000 Name: Hradec Kralove, Dukelska tr. 1713/7 (OC Atrium - Traficon) City: Hradec Kralove Street: Dukelska tr. 1713/7 ZIP: 50002 Country: CZ UID: VMCZ-zasilkovna-branch-10000 --- */ ``` ## getBranchesForLocation Searches for branches near a specific location with optional radius filtering. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; // Find branches near a specific location $branches = $branchService->getBranchesForLocation( carrier: Carrier::ZASILKOVNA, country: Country::CZECH_REPUBLIC, city: 'Praha', zipCode: '11000', street: 'Vaclavske namesti', maxResults: 5, radius: 2.0, // 2 km radius type: 'branch' ); foreach ($branches as $branch) { echo "Name: " . $branch->getName() . "\n"; echo "Address: " . $branch->getStreet() . ", " . $branch->getCity() . "\n"; echo "ZIP: " . $branch->getZip() . "\n"; echo "Type: " . $branch->getType() . "\n"; // Access additional branch info if available if ($branch->getOpeningHours()) { echo "Opening Hours: " . json_encode($branch->getOpeningHours()) . "\n"; } if ($branch->getLatitude() && $branch->getLongitude()) { echo "GPS: " . $branch->getLatitude() . ", " . $branch->getLongitude() . "\n"; } echo "---\n"; } ``` ## getLabels Retrieves PDF label URLs for packages. Labels can be printed and attached to shipments. ```php use Inspirum\Balikobot\Definitions\Carrier; // Get labels for packages in a collection $labelsUrl = $packageService->getLabels($packages); echo "Labels URL: " . $labelsUrl . "\n"; // Get labels by package IDs directly $labelsUrl = $packageService->getLabelsByPackageIds( Carrier::CP, ['42718', '42719', '42720'] ); echo "Labels URL: " . $labelsUrl . "\n"; /* Output: Labels URL: https://pdf.balikobot.cz/cp/eNorMTIwt9A1NbYwMwVcMBAXAC9. */ ``` ## getOverview Retrieves all packages that have been added but not yet ordered for shipment. ```php use Inspirum\Balikobot\Definitions\Carrier; // Get overview of unshipped packages for Czech Post $pendingPackages = $packageService->getOverview(Carrier::CP); echo "Pending packages count: " . count($pendingPackages) . "\n"; foreach ($pendingPackages as $package) { echo "Package ID: " . $package->getPackageId() . "\n"; echo "Carrier ID: " . $package->getCarrierId() . "\n"; echo "Label URL: " . $package->getLabelUrl() . "\n"; } // Get overview for multiple carriers $carriers = [Carrier::CP, Carrier::PPL, Carrier::GLS, Carrier::DPD]; foreach ($carriers as $carrier) { $pending = $packageService->getOverview($carrier); echo "Carrier {$carrier}: " . count($pending) . " pending packages\n"; } ``` ## getPackageInfo Retrieves complete information about a package including all attributes used during creation. ```php use Inspirum\Balikobot\Definitions\Carrier; // Get package info by package object $packageInfo = $packageService->getPackageInfo($packages[0]); echo "Service Type: " . $packageInfo->getServiceType() . "\n"; echo "Recipient: " . $packageInfo->getRecName() . "\n"; echo "Address: " . $packageInfo->getRecStreet() . ", " . $packageInfo->getRecCity() . "\n"; echo "ZIP: " . $packageInfo->getRecZip() . "\n"; echo "Country: " . $packageInfo->getRecCountry() . "\n"; // Get package info by package ID $packageInfo = $packageService->getPackageInfoByPackageId(Carrier::CP, '42718'); // Get package info by carrier ID (tracking number) $packageInfo = $packageService->getPackageInfoByCarrierId(Carrier::CP, 'NP1504102232M'); echo "COD Price: " . $packageInfo->getCodPrice() . "\n"; echo "Price: " . $packageInfo->getPrice() . "\n"; ``` ## getProofOfDelivery Retrieves PDF link with signed consignment delivery document by the recipient. ```php use Inspirum\Balikobot\Definitions\Carrier; // Get proof of delivery for a single package $podUrl = $packageService->getProofOfDelivery($packages[0]); echo "Proof of Delivery URL: " . $podUrl . "\n"; // Get proof of delivery for multiple packages $podUrls = $packageService->getProofOfDeliveries($packages); foreach ($podUrls as $index => $url) { echo "Package {$index} POD: {$url}\n"; } // Get proof of delivery by carrier ID $podUrl = $packageService->getProofOfDeliveryByCarrierId(Carrier::CP, 'NP1504102232M'); echo "POD URL: " . $podUrl . "\n"; // Get multiple PODs by carrier IDs $podUrls = $packageService->getProofOfDeliveriesByCarrierIds( Carrier::CP, ['NP1504102232M', 'NP1504102233M'] ); ``` ## getTransportCosts Calculates the price of carriage for packages before creating them. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Service; use Inspirum\Balikobot\Model\PackageData\DefaultPackageData; use Inspirum\Balikobot\Model\PackageData\DefaultPackageDataCollection; $packagesData = new DefaultPackageDataCollection(Carrier::PPL); $packageData = new DefaultPackageData(); $packageData->setServiceType(Service::PPL_PARCEL_BUSSINESS_CZ); $packageData->setRecZip('11000'); $packageData->setRecCountry(Country::CZECH_REPUBLIC); $packageData->setWeight(2.5); // kg $packagesData->add($packageData); // Calculate transport costs $costs = $packageService->getTransportCosts($packagesData); foreach ($costs as $cost) { echo "Carrier: " . $cost->getCarrier() . "\n"; echo "Total Cost: " . $cost->getTotalCost() . " " . $cost->getCurrency() . "\n"; echo "Base Cost: " . $cost->getBaseCost() . "\n"; } /* Output: Carrier: ppl Total Cost: 125.00 CZK Base Cost: 125.00 */ ``` ## orderPickup Orders a package pickup from your location on a specific date and time. ```php use Inspirum\Balikobot\Definitions\Carrier; // Order a pickup $packageService->orderPickup( carrier: Carrier::PPL, dateFrom: new DateTimeImmutable('2024-01-20 09:00:00'), dateTo: new DateTimeImmutable('2024-01-20 17:00:00'), weight: 15.5, // Total weight in kg packageCount: 3, message: 'Please call before arrival' ); echo "Pickup ordered successfully!\n"; ``` ## getOrder Retrieves complete information about an ordered shipment by its order ID. ```php use Inspirum\Balikobot\Definitions\Carrier; // Get order details $order = $packageService->getOrder(Carrier::CP, '2757'); echo "Order ID: " . $order->getOrderId() . "\n"; echo "Carrier: " . $order->getCarrier() . "\n"; echo "Labels URL: " . $order->getLabelsUrl() . "\n"; echo "Handover URL: " . $order->getHandoverUrl() . "\n"; echo "Package IDs: " . implode(', ', $order->getPackageIds()) . "\n"; ``` ## Status Constants The Status class provides constants and helper methods for checking package delivery status. ```php use Inspirum\Balikobot\Definitions\Status; // Status constants echo Status::ORDERED; // -1.0 - Ordered echo Status::PICKED_UP_FROM_SENDER; // 2.1 - Picked up at the sender echo Status::TRANSIT; // 2.2 - In transit echo Status::READY_TO_PICK_UP; // 2.3 - Ready to pick up echo Status::SEND_BACK_TO_SENDER; // 2.4 - Back on the way to sender echo Status::HANDED_TO_FINAL_CARRIER; // 2.5 - Handed to final carrier echo Status::CANCELLATION_BY_CARRIER; // 3.1 - Cancellation by carrier echo Status::CANCELLATION_BY_RECIPIENT; // 3.2 - Cancellation by recipient echo Status::CANCELLATION_BY_SENDER; // 3.3 - Cancellation by sender echo Status::DELIVERED_BACK_TO_SENDER; // 4.0 - Delivered back to sender echo Status::COD_PAID; // 5.0 - COD credited to sender's account echo Status::ERROR_CARRIER; // 0.1 - Carrier error echo Status::ERROR_RECIPIENT; // 0.2 - Recipient error echo Status::ERROR_SENDER; // 0.3 - Sender error echo Status::PICKUP_ON_DELIVERY_POINT; // 1.1 - Picked up at delivery point echo Status::DELIVERED_TO_ADDRESS; // 1.2 - Delivered to address // Helper methods for status checking $statusId = 1.2; if (Status::isDelivered($statusId)) { echo "Package delivered (pickup point or address)\n"; } if (Status::isError($statusId)) { echo "Delivery error occurred\n"; } if (Status::isBeingDelivered($statusId)) { echo "Package is in delivery process\n"; } if (Status::isClosed($statusId)) { echo "Delivery process is complete\n"; } ``` ## Carrier and Service Definitions Helper classes provide constants for all supported carriers and their service types. ```php use Inspirum\Balikobot\Definitions\Carrier; use Inspirum\Balikobot\Definitions\Service; use Inspirum\Balikobot\Definitions\Country; use Inspirum\Balikobot\Definitions\Currency; // Carrier constants echo Carrier::CP; // 'cp' - Czech Post echo Carrier::DPD; // 'dpd' - DPD echo Carrier::DHL; // 'dhl' - DHL Express echo Carrier::GLS; // 'gls' - GLS echo Carrier::PPL; // 'ppl' - PPL + DHL Freight echo Carrier::ZASILKOVNA; // 'zasilkovna' - Zasilkovna echo Carrier::INTIME; // 'intime' - WE DO echo Carrier::TOPTRANS; // 'toptrans' - Toptrans echo Carrier::UPS; // 'ups' - UPS echo Carrier::SP; // 'sp' - Slovak Post // Get all available carriers $allCarriers = Carrier::all(); echo "Total carriers: " . count($allCarriers) . "\n"; // Service types echo Service::CP_NP; // 'NP' - Czech Post business package echo Service::CP_RR; // 'RR' - Registered mail echo Service::PPL_PARCEL_BUSSINESS_CZ; // 'PARCEL_BUSSINESS_CZ' echo Service::GLS_BUSINESS; // 'BUSINESS' echo Service::DPD_CLASSIC; // '1' echo Service::ZASILKOVNA_VMCZ; // 'VMCZ' // Get services for a specific carrier $cpServices = Service::getForCarrier(Carrier::CP); print_r($cpServices); // Get all services grouped by carrier $allServices = Service::getForCarriers(); // Country constants (ISO 3166-1 alpha-2) echo Country::CZECH_REPUBLIC; // 'CZ' echo Country::SLOVAKIA; // 'SK' echo Country::GERMANY; // 'DE' echo Country::AUSTRIA; // 'AT' echo Country::POLAND; // 'PL' // Currency constants echo Currency::CZK; // 'CZK' echo Currency::EUR; // 'EUR' echo Currency::PLN; // 'PLN' ``` ## Exception Handling The library provides detailed exception handling with access to API error responses. ```php use Inspirum\Balikobot\Exception\Exception; use Inspirum\Balikobot\Exception\BadRequestException; use Inspirum\Balikobot\Exception\UnauthorizedException; try { $packages = $packageService->addPackages($packagesData); } catch (UnauthorizedException $e) { echo "Authentication failed - check your API credentials\n"; echo "Status code: " . $e->getStatusCode() . "\n"; } catch (BadRequestException $e) { echo "Invalid request data\n"; echo "Status code: " . $e->getStatusCode() . "\n"; echo "Message: " . $e->getMessage() . "\n"; // Get detailed errors for each package foreach ($e->getErrors() as $packageIndex => $errors) { echo "Package {$packageIndex} errors:\n"; foreach ($errors as $attribute => $message) { echo " - {$attribute}: {$message}\n"; } } // Get raw API response $response = $e->getResponse(); echo "Raw response: " . $e->getResponseAsString() . "\n"; } catch (Exception $e) { echo "API error: " . $e->getMessage() . "\n"; } /* Output on validation error: Invalid request data Status code: 400 Message: Invalid package data Package 0 errors: - rec_street: Recipient street is required - rec_city: Recipient city is required */ ``` ## Summary Balikobot API provides a comprehensive solution for e-commerce businesses and logistics companies in Czech Republic and Slovakia to integrate multiple delivery carriers through a single unified interface. The library covers the complete shipment lifecycle: creating packages with all carrier-specific attributes, validating data before submission, ordering shipments, generating labels and handover documents, tracking delivery status, and retrieving proof of delivery. The library is designed for production use with strong typing, interface-based architecture for easy testing and dependency injection, and memory-efficient iterators for handling large datasets like branch lists. It integrates seamlessly with major PHP frameworks through official packages while remaining usable standalone. Error handling provides detailed feedback from the API, making it easy to diagnose and fix issues with package data. For development and testing, the library provides test API credentials that can be used to experiment with all features without affecting production systems.