PHPackages                             laraditz/courier - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. laraditz/courier

ActiveLibrary[API Development](/categories/api)

laraditz/courier
================

A unified interface for multiple courier and shipping carrier services in Laravel.

v1.0.0(yesterday)001MITPHPPHP ^8.1

Since Jun 18Pushed yesterdayCompare

[ Source](https://github.com/laraditz/courier)[ Packagist](https://packagist.org/packages/laraditz/courier)[ RSS](/packages/laraditz-courier/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (4)Versions (2)Used By (1)

Laravel Courier
===============

[](#laravel-courier)

A unified interface for multiple courier and shipping carrier services in Laravel.

Overview
--------

[](#overview)

This package provides a driver-based abstraction layer for courier integrations. Define your shipments once using strongly-typed DTOs — the driver handles the carrier-specific API calls and returns normalized results.

Each carrier ships as a separate Composer package. Install only what you need.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10, 11, 12, or 13

Installation
------------

[](#installation)

```
composer require laraditz/courier
```

The service provider is auto-discovered. Publish the config:

```
php artisan vendor:publish --tag=courier-config
```

Available Drivers
-----------------

[](#available-drivers)

PackageCarrier[laraditz/courier-sfexpress](https://github.com/laraditz/courier-sfexpress)SF ExpressConfiguration
-------------

[](#configuration)

`config/courier.php`:

```
return [
    'default' => env('COURIER_DRIVER', 'sfexpress'),

    'drivers' => [
        'sfexpress' => [
            'account' => env('SFEXPRESS_ACCOUNT'),
            'key'     => env('SFEXPRESS_KEY'),
            'secret'  => env('SFEXPRESS_SECRET'),
            'sandbox' => env('SFEXPRESS_SANDBOX', false),
        ],
    ],
];
```

Available Methods
-----------------

[](#available-methods)

MethodParametersReturnsDescription`createShipment``ShipmentPayload $payload``ShipmentResult`Book a new shipment and get a waybill number`track``string $trackingNumber``TrackingResult`Get current status and full tracking history`getRates``RatePayload $payload``RateCollection`Fetch available service options and prices for a route`cancelShipment``string $waybillNumber``CancelResult`Cancel an existing shipment`getLabel``string $waybillNumber``LabelResult`Retrieve the shipping label (base64 PDF or ZPL)`getAvailability``AvailabilityPayload $payload``ServiceCollection`List services available between two locations### Result DTOs

[](#result-dtos)

DTOKey Properties`ShipmentResult``waybillNumber`, `status`, `estimatedDelivery`, `meta()``TrackingResult``waybillNumber`, `status`, `estimatedDelivery`, `events[]`, `meta()``TrackingEvent``timestamp`, `location`, `description`, `status``RateCollection``items[]` → `RateOption``RateOption``serviceCode`, `serviceName`, `price`, `currency`, `estimatedDays``CancelResult``success`, `message`, `meta()``LabelResult``waybillNumber`, `format`, `content`, `meta()``ServiceCollection``items[]` → `ServiceOption``ServiceOption``code`, `name`, `description`, `estimatedDays`### Payload DTOs

[](#payload-dtos)

DTOProperties`ShipmentPayload``sender: Address`, `recipient: Address`, `parcel: Parcel`, `serviceCode: string`, `remarks: ?string``RatePayload``origin: Location`, `destination: Location`, `parcel: Parcel``AvailabilityPayload``origin: Location`, `destination: Location``Address``name`, `phone`, `email`, `line1`, `line2`, `line3`, `city`, `state`, `postcode`, `country``Location``postcode`, `city`, `state`, `country``Parcel``weight`, `length`, `width`, `height`, `declaredValue`, `description`, `quantity`---

Usage
-----

[](#usage)

### Create a Shipment

[](#create-a-shipment)

```
use Laraditz\Courier\Facades\Courier;
use Laraditz\Courier\DTOs\Shared\Address;
use Laraditz\Courier\DTOs\Shared\Parcel;
use Laraditz\Courier\DTOs\Payloads\ShipmentPayload;

$result = Courier::createShipment(new ShipmentPayload(
    sender: new Address(
        name: 'Raditz Farhan',
        phone: '+60123456789',
        email: null,
        line1: 'No 1 Jalan Test',
        line2: null,
        line3: null,
        city: 'Kuala Lumpur',
        state: 'Wilayah Persekutuan',
        postcode: '50000',
        country: 'MY',
    ),
    recipient: new Address(/* ... */),
    parcel: new Parcel(
        weight: 1.5,
        length: 20.0,
        width: 15.0,
        height: 10.0,
        declaredValue: 100.0,
        description: 'Goods',
        quantity: 1,
    ),
    serviceCode: 'STANDARD',
));

$result->waybillNumber; // 'SF1234567890'
$result->status;        // 'pending'
```

### Track a Shipment

[](#track-a-shipment)

```
$result = Courier::track('SF1234567890');

$result->waybillNumber;  // 'SF1234567890'
$result->status;         // 'in_transit'
$result->events;         // TrackingEvent[]

foreach ($result->events as $event) {
    $event->timestamp;   // Carbon
    $event->location;    // 'Kuala Lumpur Hub'
    $event->description; // 'Package picked up'
    $event->status;      // 'picked_up'
}
```

### Get Rates

[](#get-rates)

```
use Laraditz\Courier\DTOs\Shared\Location;
use Laraditz\Courier\DTOs\Payloads\RatePayload;

$rates = Courier::getRates(new RatePayload(
    origin: new Location('50000', 'Kuala Lumpur', 'Wilayah Persekutuan', 'MY'),
    destination: new Location('10000', 'Georgetown', 'Pulau Pinang', 'MY'),
    parcel: new Parcel(1.5, 20, 15, 10, 100, 'Goods', 1),
));

foreach ($rates->items as $option) {
    $option->serviceCode;    // 'STANDARD'
    $option->serviceName;    // 'Standard Delivery'
    $option->price;          // 12.50
    $option->currency;       // 'MYR'
    $option->estimatedDays;  // 3
}
```

### Other Operations

[](#other-operations)

```
// Cancel
$result = Courier::cancelShipment('SF1234567890');
$result->success;  // true

// Get label (returns base64-encoded PDF or ZPL)
$result = Courier::getLabel('SF1234567890');
$result->format;   // 'pdf'
$result->content;  // base64 string

// Check service availability by route
$services = Courier::getAvailability(new AvailabilityPayload(
    origin: new Location('50000', 'Kuala Lumpur', 'Wilayah Persekutuan', 'MY'),
    destination: new Location('10000', 'Georgetown', 'Pulau Pinang', 'MY'),
));
```

### Switching Drivers

[](#switching-drivers)

```
// Use a specific driver explicitly
Courier::driver('sfexpress')->track('SF1234567890');
```

### Testing

[](#testing)

Use `Courier::fake()` to mock courier calls in tests:

```
use Laraditz\Courier\Facades\Courier;

$fake = Courier::fake();

// Your code under test runs here...
$this->service->bookShipment($order);

$fake->assertShipmentCreated(1);
$fake->assertShipmentCreated(fn ($payload) => $payload->serviceCode === 'STANDARD');
$fake->assertTracked('SF1234567890');
$fake->assertCancelled('SF1234567890');
$fake->assertRatesFetched();
$fake->assertLabelFetched('SF1234567890');
$fake->assertNothingSent();
```

Provide preset responses:

```
use Laraditz\Courier\DTOs\Results\ShipmentResult;

$fake = Courier::fake([
    'createShipment' => new ShipmentResult('CUSTOM-001', 'pending', null),
]);
```

Normalized Status Vocabulary
----------------------------

[](#normalized-status-vocabulary)

All drivers map their carrier-specific statuses to these values:

StatusMeaning`pending`Shipment created, not yet picked up`picked_up`Collected by courier`in_transit`Moving through the network`out_for_delivery`On the delivery vehicle`delivered`Successfully delivered`failed_delivery`Delivery attempt failed`returned`Returned to sender`cancelled`Shipment cancelled`unknown`Status not recognizedBuilding a Custom Driver
------------------------

[](#building-a-custom-driver)

Implement `Laraditz\Courier\Contracts\CourierDriver` and register it:

```
// In your ServiceProvider
$this->app->make('courier')->extend('mycarrier', function ($app, $config) {
    return new MyCarrierDriver($config);
});
```

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

1d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1203676?v=4)[Raditz Farhan](/maintainers/raditzfarhan)[@raditzfarhan](https://github.com/raditzfarhan)

---

Top Contributors

[![raditzfarhan](https://avatars.githubusercontent.com/u/1203676?v=4)](https://github.com/raditzfarhan "raditzfarhan (16 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/laraditz-courier/health.svg)

```
[![Health](https://phpackages.com/badges/laraditz-courier/health.svg)](https://phpackages.com/packages/laraditz-courier)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[laravel/ai

The official AI SDK for Laravel.

9782.1M157](/packages/laravel-ai)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

815320.5k3](/packages/defstudio-telegraph)[moonshine/moonshine

Laravel administration panel

1.3k239.9k74](/packages/moonshine-moonshine)[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

721160.4k12](/packages/tallstackui-tallstackui)[simplestats-io/laravel-client

Analytics for Laravel. Track visitors, registrations, and payments. Discover which channels actually drive revenue, not just traffic. Server-side, GDPR compliant, ad-blocker proof.

5019.3k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
