mavit / deliveo-php-api
PHP client for the Deliveo API.
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.9
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1|^2.0
Requires (Dev)
- pestphp/pest: ^3.0|^4.0
This package is not auto-updated.
Last update: 2026-07-30 07:32:47 UTC
README
Framework-independent PHP client for the Deliveo API.
The package requires PHP 8.2 or newer. It uses PSR-18 and PSR-17 contracts, ships with Guzzle as the default implementation, and has no Laravel or Illuminate runtime dependency.
Installation
composer require mavit/deliveo-php-api
Basic Usage
use Mavit\Deliveo\Deliveo;
$deliveo = new Deliveo(
licence: 'demo',
apiKey: 'api-key',
options: [
'source' => 'My Application',
],
);
$deliveries = $deliveo->deliveries()->list();
The constructor calls GET /test immediately. Invalid credentials, transport
failures, HTTP errors, invalid JSON, and Deliveo type=error responses throw
DeliveoApiException.
The available constructor options are:
| Option | Default | Description |
|---|---|---|
base_url | https://api.deliveo.eu | Deliveo API base URL |
source | PHP | Value sent in the x-source request header |
timeout | 30 | Timeout in seconds for the default Guzzle client |
Credentials must be passed explicitly as constructor arguments or as
licence and api_key options. The package does not read application
configuration or environment variables.
The /test response is also available through the client:
$deliveo->isAdministrative();
$deliveo->isClient();
$deliveo->apiKeyType();
$deliveo->customerId();
$deliveo->testResponse();
Custom PSR-18 Client
The final three constructor arguments accept any compatible PSR-18 client and PSR-17 factories:
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use Mavit\Deliveo\Deliveo;
$httpClient = new Client([
'timeout' => 10,
'http_errors' => false,
]);
$httpFactory = new HttpFactory();
$deliveo = new Deliveo(
licence: 'demo',
apiKey: 'api-key',
options: [
'base_url' => 'https://api.deliveo.eu',
'source' => 'My Application',
],
httpClient: $httpClient,
requestFactory: $httpFactory,
streamFactory: $httpFactory,
);
When a custom client is injected, its timeout and transport configuration are the caller's responsibility.
Request and Response Conventions
GET query parameters use RFC 3986 encoding. POST payloads are sent as
application/x-www-form-urlencoded. Nested arrays are flattened to Deliveo
field names such as packages[0][weight], and boolean values are sent as 0
or 1.
JSON list and detail endpoints return decoded arrays. Data-only list helpers
return their data rows. Simple write endpoints return DeliveoResponse;
package creation returns DeliveoPackageResponse. Label, signature, and MPL
PDF helpers return Psr\Http\Message\ResponseInterface.
Array payloads must use field names from the Deliveo API specification.
Write Response Wrappers
Simple write endpoints return DeliveoResponse:
use Mavit\Deliveo\Data\DeliveoResponse;
/** @var DeliveoResponse $response */
$response = $deliveo->stock()->create([
'item_id' => 'SKU-001',
'item_name' => 'Product',
]);
$response->isSuccess();
$response->isWarning();
$response->message();
$response->errorCode();
$response->data();
$response->warnings();
$response->raw();
Package creation returns DeliveoPackageResponse, whose package-specific
helpers are shown in the next section.
Create a Package
Package creation accepts a typed DeliveoPackage:
use Mavit\Deliveo\Data\DeliveoAddress;
use Mavit\Deliveo\Data\DeliveoItem;
use Mavit\Deliveo\Data\DeliveoPackage;
$package = new DeliveoPackage(
sender: new DeliveoAddress(
name: 'Nagy Adam',
country: 'HU',
zip: '1234',
city: 'Budapest',
address: 'Hungaria krt. 1.',
phone: '+36123456789',
),
consignee: new DeliveoAddress(
name: 'Alex Muller',
country: 'DE',
zip: '12345',
city: 'Berlin',
address: 'Treskowallee 1',
phone: '+491234567890',
),
delivery: 4,
items: [
new DeliveoItem(
weight: 5,
x: 20,
y: 30,
z: 40,
itemNo: 'ABC-001',
customCode: 'CUSTOM-001',
),
],
comment: 'Handle carefully',
);
$response = $deliveo->packages()->create($package);
$response->isSuccess();
$response->isWarning();
$response->ids();
$response->firstId();
$response->message();
$response->warnings();
$response->raw();
Both type=success and type=warning package responses represent created
packages. Warnings remain available through warnings().
Query and Update Packages
use Mavit\Deliveo\Data\DeliveoPackageAssignment;
use Mavit\Deliveo\Data\DeliveoPackagePickup;
use Mavit\Deliveo\Data\DeliveoPackageStatusChange;
use Mavit\Deliveo\Enums\PackageStatusPaymentMethod;
$package = $deliveo->packages()->find('DELI-123456789');
$packages = $deliveo->packages()->list(
filters: [
'last_modified' => [
'geq' => '2020-01-01 00:00:00',
],
],
fields: ['deliveo_id', 'sender', 'last_modified'],
limit: 100,
offset: 0,
);
$allPackages = $deliveo->packages()->listAll(
filters: [
'last_modified' => [
'geq' => '2020-01-01 00:00:00',
],
],
fields: ['deliveo_id', 'sender'],
);
$log = $deliveo->packages()->log('DELI-123456789');
$updated = $deliveo->packages()->edit('DELI-123456789', [
'comment' => 'Updated comment',
]);
$status = $deliveo->packages()->status(
'DELI-123456789',
new DeliveoPackageStatusChange(
state: 0,
receivedBy: 'Beru Lars',
date: '2026-07-15 14:10:33',
payment: PackageStatusPaymentMethod::Card,
),
);
$assigned = $deliveo->packages()->assignTo(
'DELI-123456789',
new DeliveoPackageAssignment(pickedUpLocationId: 44),
);
$pickedUp = $deliveo->packages()->pickup(
'DELI-123456789',
new DeliveoPackagePickup(
locationId: 22,
datetime: '2026-07-15 14:10:33',
),
);
// Destructive: call only when deletion is intentional.
// $deleted = $deliveo->packages()->delete('DELI-123456789');
listAll() uses batches of up to 10,000 records and stops according to the
response max and total metadata.
Stock
use Mavit\Deliveo\Data\DeliveoStockItem;
$items = $deliveo->stock()->list(limit: 1000, offset: 0);
$allItems = $deliveo->stock()->listAll();
$item = $deliveo->stock()->find('SKU-001');
$created = $deliveo->stock()->create(new DeliveoStockItem(
itemId: 'SKU-001',
itemName: 'Product',
itemWeight: 1.5,
itemEan: '5991234567890',
));
$updated = $deliveo->stock()->edit('SKU-001', new DeliveoStockItem(
itemName: 'Updated product',
itemStockCorrection: 10,
itemStockCorrectionReason: 'Inventory correction',
));
// Raw arrays remain supported.
$deliveo->stock()->create([
'item_id' => 'SKU-002',
'item_name' => 'Second product',
]);
Locations
Location operations require an administrative API key.
use Mavit\Deliveo\Data\DeliveoLocation;
$locations = $deliveo->locations()->list();
$created = $deliveo->locations()->create(new DeliveoLocation(
type: 0,
name: 'Main warehouse',
alias: 'MAIN',
));
Addresses
use Mavit\Deliveo\Data\DeliveoSavedAddress;
$addresses = $deliveo->addresses()->list(
limit: 1000,
offset: 0,
filter: 'Bud',
);
$allAddresses = $deliveo->addresses()->listAll(filter: 'Bud');
$address = $deliveo->addresses()->find(123);
$created = $deliveo->addresses()->create(new DeliveoSavedAddress(
name: 'Office',
zip: '1111',
city: 'Budapest',
address: 'Fo utca 1.',
phone: '+3612345678',
country: 'HU',
email: 'office@example.com',
));
// Filtering by customer ID requires an administrative API key.
$customerAddresses = $deliveo->addresses()->list(customerId: 131);
Customers
Customer operations require an administrative API key.
use Mavit\Deliveo\Data\DeliveoCustomer;
$customers = $deliveo->customers()->list();
$allCustomers = $deliveo->customers()->listAll();
$customer = $deliveo->customers()->find(131);
$created = $deliveo->customers()->create(new DeliveoCustomer(
name: 'Acme Kft',
zip: '1111',
city: 'Budapest',
address: 'Fo utca 1.',
phone: '+3612345678',
country: 'HU',
email: 'billing@example.com',
));
Quotes and Lookup Data
use Mavit\Deliveo\Data\DeliveoQuote;
$deliveryOptions = $deliveo->deliveries()->list();
$unsuccessfulReasons = $deliveo->unsuccessful()->list();
$quote = $deliveo->quotes()->create(new DeliveoQuote(
sender: 'Sender Kft',
senderCountry: 'HU',
senderZip: '1111',
senderCity: 'Budapest',
senderAddress: 'Fo utca 1.',
consignee: 'Consignee GmbH',
consigneeCountry: 'DE',
consigneeZip: '10115',
consigneeCity: 'Berlin',
consigneeAddress: 'Street 1',
delivery: 4,
cod: 0,
shopId: 'PP_159',
totalWeight: 5,
totalVolume: 10,
));
PDF Responses
use Mavit\Deliveo\Enums\LabelSize;
$label = $deliveo->getLabel('DEV26050441371', LabelSize::A4);
$multiLabel = $deliveo->getLabel(['DEV1', 'DEV2'], LabelSize::A6);
$signature = $deliveo->getSignature('DEV26050441371');
$mpl = $deliveo->getMplSending(['DEV1', 'DEV2']);
file_put_contents('label.pdf', (string) $label->getBody());
The raw helpers inspect JSON error payloads even if the server omits a JSON content type. Successful response bodies remain readable after inspection.
Error Handling
Package-generated exception and validation messages are always English. The
original Deliveo msg value is retained separately and is not used as the
exception's main message.
use Mavit\Deliveo\Exceptions\DeliveoApiException;
use Mavit\Deliveo\Exceptions\ValidationException;
use Mavit\Deliveo\Data\DeliveoLocation;
try {
$deliveo->packages()->find('DELI-123456789');
} catch (DeliveoApiException $exception) {
$englishMessage = $exception->getMessage();
$httpStatus = $exception->status;
$errorCode = $exception->deliveoErrorCode;
$originalApiMessage = $exception->deliveoMessage;
$responseBody = $exception->responseBody;
}
try {
(new DeliveoLocation(type: 0, name: ''))->toDeliveoPayload();
} catch (ValidationException $exception) {
$englishMessage = $exception->getMessage();
$fieldErrors = $exception->errors();
}
Endpoint Coverage
| Endpoint | Public API | Admin-only | Request type | Response type |
|---|---|---|---|---|
GET /test | constructor, testResponse() | No | none | array helper |
GET /delivery | deliveries()->list() | No | none | data array |
GET /unsuccessful | unsuccessful()->list() | No | none | data array |
GET /item | stock()->list(), stock()->listAll() | No | limit, offset | data array |
POST /item | stock()->create() | No | array or DeliveoStockItem | DeliveoResponse |
GET /item/{item_id} | stock()->find() | No | path ID | array |
POST /item/{item_id}/edit | stock()->edit() | No | array or DeliveoStockItem | DeliveoResponse |
GET /locations | locations()->list() | Yes | limit, offset | data array |
POST /locations/create | locations()->create() | Yes | array or DeliveoLocation | DeliveoResponse |
GET /package | packages()->list(), packages()->listAll() | No | filters, fields, limit, offset | array |
GET /package/{deliveo_id} | packages()->find() | No | path ID | array |
POST /package/create | packages()->create() | No | DeliveoPackage | DeliveoPackageResponse |
POST /package/{deliveo_id}/edit | packages()->edit() | No | array | DeliveoResponse |
POST /package/{deliveo_id}/status | packages()->status() | Yes | array or DeliveoPackageStatusChange | DeliveoResponse |
POST /package/{deliveo_id}/assignto | packages()->assignTo() | Yes | array or DeliveoPackageAssignment | DeliveoResponse |
POST /package/{deliveo_id}/pickup | packages()->pickup() | Yes | array or DeliveoPackagePickup | DeliveoResponse |
GET /package_log/{deliveo_id} | packages()->log() | No | path ID | array |
POST /package/{deliveo_id}/delete | packages()->delete() | API decides | path ID | DeliveoResponse |
GET /label | getLabel() | No | ID(s), LabelSize, language | PSR-7 ResponseInterface |
GET /signature/{deliveo_id} | getSignature() | No | path ID | PSR-7 ResponseInterface |
GET /address | addresses()->list(), addresses()->listAll() | Only with customerId | limit, offset, filter, customerId | data array |
POST /address/create | addresses()->create() | No | array or DeliveoSavedAddress | DeliveoResponse |
GET /address/{address_id} | addresses()->find() | No | path ID | array |
GET /customer | customers()->list(), customers()->listAll() | Yes | limit, offset | data array |
POST /customer/create | customers()->create() | Yes | array or DeliveoCustomer | DeliveoResponse |
GET /customer/{customer_id} | customers()->find() | Yes | path ID | array |
POST /mpl_sending | getMplSending() | No | ID(s) | PSR-7 ResponseInterface |
POST /quote | quotes()->create() | No | array or DeliveoQuote | DeliveoResponse |
Migrating from the Laravel Package
The resource and DTO method names remain the same. Update imports from
Mavit\LaravelDeliveo\... to Mavit\Deliveo\... and pass credentials
explicitly.
Raw document methods now return Psr\Http\Message\ResponseInterface:
// Before:
// $contents = $response->body();
// Now:
$contents = (string) $response->getBody();
DTO validation now throws
Mavit\Deliveo\Exceptions\ValidationException. All framework-independent
validation messages are English and available through errors().