A production-ready PHP client for the Shipway shipping API.
- PHP 8.1+
- Composer
composer require mimicak/shipway-php-sdkShipway uses HTTP Basic Auth. Your credentials are:
| Field | Where to find |
|---|---|
user_email |
Your Shipway registered email |
api_key |
Shipway dashboard → Profile → Manage Profile → License Key |
use MimicAk\ShipwayPhpSdk\Shipway;
$shipway = Shipway::create('you@example.com', 'your-license-key');SHIPWAY_USER_EMAIL=you@example.com
SHIPWAY_API_KEY=your-license-key$shipway = Shipway::createFromEnv();use MimicAk\ShipwayPhpSdk\Models\Order;
use MimicAk\ShipwayPhpSdk\Models\Product;
$product = new Product();
$product->product = 'Blue T-Shirt';
$product->price = '499.00';
$product->product_quantity = '2';
$product->product_code = 'SKU-001';
$order = new Order();
$order->order_id = 'ORD-20240501-001';
$order->products = [$product];
// Billing address
$order->billing_firstname = 'Ravi';
$order->billing_lastname = 'Kumar';
$order->billing_address = '12, MG Road';
$order->billing_city = 'Bangalore';
$order->billing_state = 'Karnataka';
$order->billing_country = 'India';
$order->billing_zipcode = '560001';
$order->billing_phone = '9876543210';
// Shipping address
$order->shipping_firstname = 'Ravi';
$order->shipping_lastname = 'Kumar';
$order->shipping_address = '12, MG Road';
$order->shipping_city = 'Bangalore';
$order->shipping_state = 'Karnataka';
$order->shipping_country = 'India';
$order->shipping_zipcode = '560001';
$order->shipping_phone = '9876543210';
$order->payment_type = 'P'; // P = Prepaid, C = COD
$order->order_total = '998.00';
$order->email = 'ravi@example.com';
// Optional dimensions
$order->order_weight = '0.5'; // kg
$order->box_length = '20'; // cm
$order->box_breadth = '15';
$order->box_height = '10';
$response = $shipway->orders()->create($order);
if ($response->success) {
echo 'Order created. AWB: ' . $response->getAwbNumber();
echo 'Label URL: ' . $response->getShippingLabelUrl();
}$order->carrier_id = 3411; // from courier()->list()
$order->warehouse_id = 101; // from warehouse dashboard
$order->return_warehouse_id = 101;
$response = $shipway->orders()->createWithLabel($order);use MimicAk\ShipwayPhpSdk\Models\Request\ShipmentBooking\GetOrdersRequest;
use MimicAk\ShipwayPhpSdk\Models\Request\ShipmentBooking\ShipmentStatus;
$request = new GetOrdersRequest();
$request->date_from = '2024-05-01';
$request->date_to = '2024-05-31';
$request->shipment_status = ShipmentStatus::STATUS_IN_TRANSIT;
$request->page = 1;
$response = $shipway->orders()->getOrders($request);
foreach ($response->getOrders() as $order) {
echo $order->order_id . ' — ' . $order->tracking_number . PHP_EOL;
}// By AWB number
$tracking = $shipway->orders()->track('1333110020164');
// By your order ID
$tracking = $shipway->orders()->trackByOrderId('ORD-20240501-001');
// With full scan history
$tracking = $shipway->orders()->track('1333110020164', trackingHistory: 1);
foreach ($tracking->shipments as $shipment) {
echo $shipment->tracking_details->shipment_status . PHP_EOL;
echo $shipment->tracking_details->track_url . PHP_EOL;
foreach ($shipment->tracking_details->shipment_details as $detail) {
echo $detail->courier_name . PHP_EOL;
echo $detail->current_status . PHP_EOL;
}
}use MimicAk\ShipwayPhpSdk\Models\Request\ShipmentBooking\ManifestRequest;
$request = new ManifestRequest(['ORD-001', 'ORD-002', 'ORD-003']);
$response = $shipway->orders()->createManifest($request);
echo $response->manifest_ids;$request = new ManifestRequest(['ORD-001', 'ORD-002']);
$response = $shipway->orders()->cancelOrders($request);
echo 'Cancelled: ' . $response->success_count . PHP_EOL;
echo 'Failed: ' . $response->failure_count . PHP_EOL;$request = new ManifestRequest(['ORD-001']);
$response = $shipway->orders()->onHoldOrders($request);// Single AWB
$response = $shipway->orders()->cancelShipment('1333110020164');
// Multiple AWBs
$response = $shipway->orders()->cancelShipment(['1333110020164', '1333110020165']);
echo $response->shipment_success_tracking_numbers;
echo $response->shipment_failed_tracking_numbers;$response = $shipway->courier()->list();
foreach ($response->carriers as $carrier) {
echo $carrier->id . ' — ' . $carrier->carrier_title . PHP_EOL;
echo 'Supports RTO: ' . ($carrier->reverse_status ? 'yes' : 'no') . PHP_EOL;
}// All payment types
$response = $shipway->courier()->getPincodeAvailability('560001');
// COD only
$response = $shipway->courier()->getPincodeAvailability('560001', 'C');
foreach ($response->carriers as $carrier) {
echo $carrier->name . ' (' . $carrier->payment_type . ')' . PHP_EOL;
}use MimicAk\ShipwayPhpSdk\Models\Request\Carriers\GetCarrierRates;
$rateRequest = new GetCarrierRates();
$rateRequest->fromPincode = 110001;
$rateRequest->toPincode = 560001;
$rateRequest->paymentType = 'prepaid';
$rateRequest->weight = 0.5; // kg
$rateRequest->length = 20; // cm
$rateRequest->breadth = 15;
$rateRequest->height = 10;
$rateRequest->cummulativePrice = 999; // required for COD
$response = $shipway->courier()->getCarrierRates($rateRequest);
foreach ($response->carriers as $carrier) {
echo $carrier->carrier_title . PHP_EOL;
echo 'Delivery: Rs. ' . $carrier->delivery_charge . PHP_EOL;
echo 'RTO: Rs. ' . $carrier->rto_charge . PHP_EOL;
echo 'Zone: ' . $carrier->zone . PHP_EOL;
}use MimicAk\ShipwayPhpSdk\Models\Request\Warehouses\CreateWarehouse;
$warehouse = new CreateWarehouse();
$warehouse->name = 'Main Fulfilment Centre';
$warehouse->phone = '9876543210';
$warehouse->address = '15, Industrial Area, Phase 1';
$warehouse->city = 'Delhi';
$warehouse->state = 'Delhi';
$warehouse->country = 'India';
$warehouse->pincode = '110020';
$warehouse->email = 'warehouse@example.com';
$warehouse->gstin = '07AAACB2894L1ZX';
$response = $shipway->warehouse()->create($warehouse);
echo 'Warehouse ID: ' . $response->warehouseId;All SDK methods throw typed exceptions. Catch the most specific type you need:
use MimicAk\ShipwayPhpSdk\Exceptions\ValidationException;
use MimicAk\ShipwayPhpSdk\Exceptions\AuthenticationException;
use MimicAk\ShipwayPhpSdk\Exceptions\RateLimitException;
use MimicAk\ShipwayPhpSdk\Exceptions\ApiException;
use MimicAk\ShipwayPhpSdk\Exceptions\ShipwayException;
try {
$response = $shipway->orders()->create($order);
} catch (ValidationException $e) {
// Missing/invalid request fields (HTTP 422)
foreach ($e->getErrors() as $field => $message) {
echo "{$field}: {$message}" . PHP_EOL;
}
} catch (AuthenticationException $e) {
// Bad credentials (HTTP 401/403)
echo $e->getSuggestedAction();
} catch (RateLimitException $e) {
// Throttled (HTTP 429)
sleep($e->getRetryAfter() ?? 60);
} catch (ApiException $e) {
// Any other HTTP error
echo 'HTTP ' . $e->getStatusCode() . ': ' . $e->getMessage();
} catch (ShipwayException $e) {
// Network/config errors
echo $e->getMessage();
}ShipwayException
└── ApiException
├── AuthenticationException (401, 403)
├── ValidationException (422)
├── RateLimitException (429)
├── ResourceException (404, 409)
└── NetworkException (connection errors)
$shipway = Shipway::create('email', 'key', [
'base_url' => 'https://app.shipway.com/', // default
'timeout' => 30, // seconds, default 30
'retry_attempts' => 3, // default 3 (exponential back-off)
'debug' => false, // default false; true enables Guzzle debug output
'partner_code' => null, // optional X-Partner-Code header
'webhook_secret' => null, // for webhook signature verification
]);| Code | Description |
|---|---|
O |
New order |
A |
Processing |
E |
Manifested |
G |
Dispatched |
| Code | Description |
|---|---|
DEL |
Delivered |
INT |
In Transit |
UND |
Undelivered |
RTO |
RTO In Transit |
RTD |
RTO Delivered |
CAN |
Cancelled |
SCH |
Shipment Booked |
ONH |
On Hold |
OOD |
Out for Delivery |
NFI |
Status Pending |
RSCH |
Pickup Scheduled |
ROOP |
Out for Pickup |
RPKP |
Shipment Picked Up |
RDEL |
Return Delivered |
RINT |
Return In Transit |
PCAN |
Pickup Cancelled |
RPF |
Pickup Failed |
composer testCoverage report:
composer test-coverageMIT