Your first shipment

From zero to shipment in less than 50 lines of code

Getting Started

In this example, we will use Guzzle, a popular HTTP client written in PHP.

First, start with installing Guzzle to your project using Composer. At time of writing, version 7.0 is the latest stable. If you're using Laravel, a popular PHP framework, then Guzzle is already installed and Laravel actually provides an expressive API on top of it.

composer require guzzlehttp/guzzle:^7.0

Once you're done, start a new php file:

my_first_shipment.php
<?php

Pre-requisites

Before you can start issuing commands and creating shipments! we need you to have the following ready:

  • Your API Token: that long string of random characters, which you need to keep handy and safe at the same time. You can view/obtain new token from eshipAPI page

Your API token is a JSON Web Token, which a standard and secure form of authentication and authorization

Your API token is considered as sensitive as your password, do not share it or save it in your source code system

  • Your Service Variables: Depending on your account type, contract, available rates and your geo location, there are one or more services available for you. Refer to eshipAPI page for more details. Every request must have at least one "Base Product" associated. The value section represent the UUID or unique identifier of the service you want to request, which you will need later

UUIDs or Universally Unique IDentifiers are unique values we use to represent a certain element in our systems. These values rarely change, and it's safe to cache and re-use them

  • Collection Address: Every address you enter to our system will be given a unique identifier, using the same UUID format explained above. Many customers have only a single collection address. The value of that address is also unique, and it doesn't change with minor modifications. However, if you're planning to change your collection address completely, please create a new one.

Other considerations

To be updated

Setting up the client

Now that we have the initial variables handy, let's create the HTTP client object:

my_first_shipment.php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$api_base = 'https://ubex-clients.apis.delivery/api/v2';
$api_token = getenv('API_TOKEN');

$client = new Client([
    'base_uri' => $api_base,
    'headers' => [
        'Authorization' => sprintf('Bearer %s', $api_token),
        'Content-Type' => 'application/json'
    ],
]);

A few observations

  • $api_base is the main API URL, you can get this value from the API Docs, for the majority of the customers, it's the one mentioned above

  • $api_token is the variable holding your API Token, you can inject it the way you want, including hardcoding it temporarily

  • base_uri allows us to tell the client about the main URL and use relative endpoints thereafter

  • headers is where we configure the client to use the default method of auth for all subsequent requests, using the Authorization header, and make sure to send JSON requests to all endpoints.

The first test

Next, we'll make the very first request, which will return back the account info and confirm that we're able to connect and authenticate:

$response = $client->get('account/info');

A typical response to this request is something along these lines:

{
	"data": {
		"first_name": "First Name",
		"last_name": "Last Name",
		"fullname": "First Name Last Name",
		"mobile": "39000000",
		"country_code": "973",
		"country": "BH",
		"email": "example@ubex.co",
		"business_name": "My Business",
		"ref": "C000000",
		"addresses": [{
			"uuid": "36fbd762-8679-48a1-bff3-a84a59a6d051",
			"title": "My office",
			"formatted": "My office => Building: -, Floor:, Unit: , Road: - Capital - 000",
			"unit": "-",
			"floor": "-",
			"building": "-",
			"road": "-",
			"address_line_1": "-",
			"address_line_2": "-",
			"country": {
				"uuid": "8c6115bd-0276-4bf4-aed3-221bd0ca68a7",
				"title": "Bahrain"
			},
			"region": {
				"uuid": "e360167d-8446-4e53-91f0-99ef27c4c8bc",
				"title": "Bahrain"
			},
			"city": {
				"uuid": "7121f480-d89b-4508-baa4-53fccecc50b4",
				"title": "Bahrain"
			},
			"area": {
				"uuid": "d83f53ea-3451-4a25-8d05-d93a0ca36591",
				"title": "Capital - 000"
			},
			"extra_dir": null,
			"is_default": true,
			"is_verified": true,
			"location": ""
		}],
		"photo": null,
		"social": {
			"website": null,
			"instagram": null,
			"twitter": null,
			"facebook": null
		},
		"last_login": "2021-02-03 23:59:59"
	},
	"status": 200,
	"msg": "OK"
}

This is a standard, successful JSON response. And while some response fields were omitted for brevity, you get the idea.

If you get GuzzleHttp\Exception\ClientException or with a message starting with Cannot Authenticate: or a status code 401, then you need to double check your API Token

To inspect the response and get the results in PHP object (or array) format, use the following snippet

$body = (string)$response->getBody();
$json_body = json_decode($body);
print_r($json_body);

It is important though to check for errors before proceeding with parsing the response body:

if ($response->getStatusCode() === 200) {

} else {

}

The 1st shipment

Okay, so far we have the client ready and the first request successful, let's dive into creating an actual shipment, well, maybe a test one first.

Full example code

Follow the comments for a quick explanation, this example will ultimately create an actual shipment if you remove the test field from the request.

my_first_shipment.php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$api_base = 'https://ubex-clients.apis.delivery/api/v2';
$api_token = getenv('API_TOKEN');

$client = new Client([
    'base_uri' => $api_base,
    'headers' => [
        'Authorization' => sprintf('Bearer %s', $api_token),
        'Content-Type' => 'application/json'
    ],
]);

$shipment_data = [
    # Whether this is a test or an actual shipment, possible values are '0' or '1'
    'test' => 1,

    # Shipper Info

    // This is important, get this value from the API center after creating your source address
    'address_from' => '2a9d9481-8b74-4a28-b03d-135effcd6401',

    # Receiver Info

    // Keep an eye on the format=> 'CountrycodeNumber' with no spaces or special characters
    'mobile' => '97339003900',
    'first_name' => 'First Name',
    'last_name' => 'Last Name',
    'email' => 'firstname@example.com',

    // This is important, remember to retrieve the UUID of the destination area
    // using `meta/areas` endpoint
    'area' => '6b59fddf-6666-4d8b-979a-8fa5bf70f22f',
    'building' => '1200',
    'road' => '2400',
    'country' => 'BH',

    # Service (Products) Info

    // This is important, the base product is the main service you wish to get,
    // For example=> Domestic Parcel (DOP), remember to retrieve the UUID from
    // 'Service Variables' section
    // Only one base product can be specified
    'base_product' => 'd282d62f-69e0-42e3-abfd-64dcd29f26ec',

    // Other products are optional, for example Cash on Delivery (COD) or
    // Proof of Delivery (POD) services.
    // These services are charged as well, you can use the Pricing/Rate endpoint
    // to get a breakdown
    // You can specify multiple optional products here
    'other_products' => ['120cb1d5-6722-430e-aa03-40cd2d1fac5e'],

    # Billing and Value Info

    // Who's paying the shipment charges
    'bill_to' => 'receiver',

    // Who's paying the customs, taxes and duty charges
    'bill_duties_to' => 'receiver',

    // This is important, this value will be used for COD service
    'parcel_value' => 25.500,
    'parcel_currency' => 'BHD',

    // In most cases, this is identical to the parcel_value
    'declared_value' => 25.500,
    'declared_currency' => 'BHD',

    // Whether the customer has paid the shipment charges
    'paid' => 0,

    # Shipment Info

    // Use "non-dox" Parcel shipments, and "dox" for Documents
    'type'=> 'non-dox',

    // Optional, your internal reference to associate with this shipment
    // Examples=> Order ID, Customer Ref or any other value
    'shipment_reference' => '314159',

    // Actual contents of the shipment, this will be printed on the Waybill
    'content' => 'Fashion Items',

    // Important, this is a crucial part of the shipment info, make sure you list every piece
    // along with accurate measurements
    // This value accepts multiple sub values
    // Note: in many instances, the shipment contains only one piece
    // Note: the final shipment measurements/weight is the sum of all values listed here
    'pieces' => [
        [
            'weight' => 1,
            'length' => 10,
            'width' => 5,
            'height' => 5,
            'qty' => 1,
            'value' => 25.500,
            'content' => 'Navy Blue Slim-Fit Shirt'
        ]
    ]

];

try {
    $response = $client->post('shipments/create', ['json' => $shipment_data]);

    if ($response->getStatusCode() === 200) {
        $body = (string)$response->getBody();
        $shipment = json_decode($body);

        printf("Shipment Tracking: %s\n", $shipment->data->tracking);
    } else {
        print("Shipment creation failed");
    }

} catch (\GuzzleHttp\Exception\GuzzleException $e) {
    // Handle or report the GuzzleExceptions here
} catch (\Exception $e) {
    // Handle or report the Other Exceptions here
}

Happy shipping!!

Last updated