Shipment API

API change history

REST JSON interface that exposes methods related to:

  • Submitting a shipment to the notime platfom
  • Checking a shipment's status
  • Cancelling a shipment
  • Updating shipment parameters after submission

1. Submit Shipment

Shipments can be submitted to the notime system via our inbuilt REST API. This is done by making a POST request to the URL given below. All the information required in order to get started should be contained in the below. For special requests and other interfaces (Email, FTP, XML) please contact us on info@notime.eu

At present we support 4 different types of shipments - the so called Services Types:

  • Timeslot-based Delivery: The goods are sent from the shipper to an office or residental address at a given timeslot: e.g. 7pm to 9pm in the evening
  • Instant Delivery: The goods are sent to an office or residental address. They are collected and distributed in one go, there is no clustering or re-distribution involved.
  • Pickup Point: Goods are sent to a pickup station . E.g. www.pickuppoint.ch at the train station.
  • Return: Goods are to be returned to the shipper.

In order to tell the notime platform of which service type the shipment is, you pass to the method the so called ServiceGUID. This unique ID contains the information about which of the four services above it is. It also contains information about timeslots for delivery, pickup station location, shipper collection point, collection time, way-splits etc.
As most of the information is encapsulated in the service, the Submit Shipment method has only few compulsory parameters. E.g in the case of a Pickup Point service the only information we need is the name and phone number of the recipient - Other information, like where we pick the parcels from the shipper, where it gets collected by the customer etc is all part of the service configuration which is hardcoded in the notime platform and linked to your account.
The ServiceGUIDs are set up by your account manager. You can either hardcode them into your code (not recommended) or retrieve them everytime using the Get Services method.

Submit Shipment can be called immediately after the online checkout, or alternatively when commissioning (packing) is completed.

Try it

Request URL

Request headers

(optional)
string
Media type of the body sent to the API.
string
Subscription key which provides access to this API. Found in your Profile.

Request body

The root object is Shipment.

:
Name Type Mandatory Default Note
GroupGuid Guid Yes Guid identifying your shipment account. For testing purposes use the ID: 28228CFE-12F2-4BFB-B8BF-B7FF87746E96. Your account manager will provide you with your ID before going into production.
ServiceGuid Guid The identifier of the selected service object. The list of services can be received by calling Get Services method. Depending on the used service type some properties can be omitted and some are ignored totally:
  • In case of Timeslot-based Delivery the properties Pickup, PickupTimeFrom, PickupTimeTo can be ommited. DropoffTimeFrom, DropoffTimeTo, Fee and PaymentType properties are ignored.
  • In case of Pickup Point all pickup and dropoff parameters can be ommited. Dropoff, DropoffTimeFrom, DropoffTimeTo, Fee and PaymentType properties are ignored.
Reference String This is the shipper's own reference to this shipment. This reference can be used for search and customer support.
Pickup POI Yes, if ServiceGuid not specified The pickup location.
Dropoff POI Yes, unless ServiceGuid of type Pickup Point is provided The dropoff location.
PickupDate UTC Date string (YYYY-MM-DD) Yes This is the date when the goods will be handed from the shipper to notime (home-delivery,instant delivery,pickup point) or from the end user to notime (return)
DropoffDate UTC Date string (YYYY-MM-DD) PickupDate This is the date when the goods are to be delivered. It should be provided unless it is the same with PickupDate
PickupTimeFrom UTC time string (HH:MM:SSZ) Current Time and Date (UTC) Start of pickup time window. This field is only used for shipments of service type instant delivery and in cases where ServiceGUID is not specified
PickupTimeTo UTC time string (HH:MM:SSZ) Current Time and Date (UTC) + 60 minutes (could be different value depending on your account settings) End of pickup time window. This field is only used for shipments of service type instant delivery and in cases where ServiceGUID is not specified
DropoffTimeFrom UTC time string (HH:MM:SSZ) Yes, unless ServiceGuid of type Pickup Point, TimeSlot Delivery or Return is provided Start of dropoff time window. This field is only used for shipments of service type instant delivery and in cases where ServiceGUID is not specified
DropoffTimeTo UTC time string (HH:MM:SSZ) Yes, unless ServiceGuid of type Pickup Point, TimeSlot Delivery or Return is provided End of dropoff time window. This field is only used for shipments of service type instant delivery and in cases where ServiceGUID is not specified
EndUser EndUser Yes, if ServiceGuid of type Pickup Point specified Contact information of the person who will pick up the shipment from Pickup Point. This information should be provided only in the case service of the appropriate type is used during submission.
ServiceFeeCategory Guid Guid identifying service fee to which ServiceGuid should match.
Products Array of Product objects The articles that make up this shipment.
Parcels Array of Parcel objects The parcels, barcodes and sizes that make up this shipment. Parcel data can also be submitted at a later stage in the lifecycle of the shipment. For this use the method: Update Shipment .
Note String Freetext info about the shipment. This information will be displayed to the courier at the relevant stops
PaymentType Int One of the PaymentType values
Fee Double Total fee of the shipment. This is used according to the payment type: Either the amount to be collected at the door (Cash on Delivery), the amount to be paid in the store (To be paid in Store)
ShipmentType Int The shipment type defines what kind of product and transport is required. In most cases the shipment type is hardcoded against your account and doesn't need to be set here.
Labels Array of String Labels are used to describe the requirements that go with a certain shipment and the feature a deliverer offers. A typical requirement label could mean: "Must be transported under 10C". "Must be transported flat". Labels are identified by their name. If this is provided we try to find it in the database otherwise it logs an error and the shipment is rejected.
Some of the preconfigured labels are listed here
WebhookUrl String URL which will be used for automatic sending of POST requests with events that happen in the lifetime of the shipment. An example of the request body is given below:
{
  "Event": "Shipment status changed",
  "Status":"Allocated",
  "ShipmentGuid":"8e970e45-6958-4ca0-86bc-d17b65ce1e1f",
  "Signature": null,
  "Picture": null,
  "DriverComment": null,
  "ProblemCode": null,
  "Latitude": null,
  "Longitude": null,
  "DriverName": "Peter Driver",
  "DriverPicture": null,
  "DeliveryDate": "2016-07-15",
  "DeliveryTimeFrom": "18:20:00Z",
  "DeliveryTimeTo": "18:30:00Z",
  "ExternalReference": "BBF0429D92544CFCABD4"
}
IsUnapproved Boolean False Indicates whether the shipment needs to be approved to be processed. For most use cases this parameter is not to be used.
Language Int Language specified in shipper account Desired language of communication (FollowMe, FollowMe SMS and emails) with recipient.


Name Type Mandatory Default Note
Reference String If this is provided we try to find the corresponding item in the database.
If found the rest of the POI object can be empty (so use only reference to specify POI object). If, together with a valid reference, the fields Name, ContactName, Note, Phone are provided, they will be replaced in the corresponding database entry.
If a new reference is entered, a new POI is created in the database. The reference has to be unique within a GroupGuid.
Name String StreetAddress Set this to either the name of the organisation "IBM Germany" that is located at this POI, or the name of the person (resident) that is located at this POI. E.g. if the parcel recipient is a residential address then set this to the name of the recipient ("Peter Smith")
ContactName String In the case where the Name refers to an organisation ("IBM Germany") specifiy the name of the contact person here. This field refers to the "c/o".
StreetAddress String Yes, if no valid Reference
PostCode String Yes, if no valid Reference
City String Yes, if no valid Reference
CountryCode String Yes, if no valid Reference Country code e.g. "CH", "DE", "FR", "AT"
Phone String Main phone number. In the case of a dropoff POI, this should be a mobile phone number, as we use this one to send out the FolloMe SMS
Phone2 String Additional phone number. This number will be given to the courier and operation manager in case the POI's contact is not reachable otherwise
Phone3 String Additional phone number. This number will be given to the courier and operation manager in case the POI's contact is not reachable otherwise
ContactEmailAddress String Email address under which the recipient can be contacted. In the case of a dropoff POI we use this email for our FollowMe emails.
Note String Freetext message that assist the courier in finding the location. E.g. "Entrance is at the back"
Labels Array of String Labels are used to describe the requirements that go with a certain shipment and the feature a deliverer offers. A typical requirement lable could mean: "Must be transported under 10C". "Must be transported flat". Labels are identified by their name. If this is provided we try to find it in the database otherwise it logs an error and the shipment is rejected.


Name Type Mandatory Default Note
Reference String If this is provided we try to find it in the database. If found the rest of the Product object can be empty (so use only reference to specify Product object).
Name String Yes, if no valid Reference
UnitType Int 1 One of UnitType values
Quantity Double 1.0 kg, units, litres, meters (depending on UnitType)
Note String Freetext info for product
Fee Double Price of the product
ImageUrl String Product's image url. This picture will be passed on to the courier and is visible to the operation manager.
Type Int Please contact your account manager for the relevant product types.
Labels Array of String Labels are used to describe the requirements that go with a certain shipment and the feature a deliverer offers. A typical requirement lable could mean: "Must be transported under 10C". "Must be transported flat". Labels are identified by their name. If this is provided we try to find it in the database otherwise it logs and error.


Name Type Mandatory Default Note
ParcelNumber String Custom identifier of a parcel
Barcode String We support all commonly used barcode types. If no barcode is provided we will generate a unique QR code for this parcel. Barcodes and labels can be downloaded manually from the notime service management website or via the API method Get Labels
Size String Optional information about the size of the parcel. E.g. "XS", "S" etc. For more information please contact support.
Weight Double Optional information about the weight of the parcel in kg.


Name Type Note
Event String At the moment only one event is supported ("Shipment status changed")
Status String Name of the status which was assigned to the shipment
StatusCode Int One of the shipment status which was assigned to the shipment
ShipmentGuid Guid Guid identifying a shipment. The shipment GUID received when initially submitting the shipment
Signature String The URL of signature in case we have one
Picture String The URL of picture from the last problem report
DriverComment String Text of driver comment from the last problem report
ProblemCode Int Problem code from the last problem report
Latitude Double Latitude of driver. It's returned if driver is on route (StatusCode equals to either 70 or 90)
Longitude Double Longitude of driver. It's returned if driver is on route (StatusCode equals to either 70 or 90)
DriverName String Name of driver, in case the shipment is already allocated
DriverPicture String The URL of the driver picture
DeliveryDate UTC Date String (YYYY-MM-DD) Shipment delivery date
DeliveryTimeFrom UTC time string (HH:MM:SSZ) Shipment delivery time from
DeliveryTimeTo UTC time string (HH:MM:SSZ) Shipment delivery time to
ExternalReference String The value of Reference provided in the shipment object


Name Type Mandatory Default Note
FullName String Yes Full name of the recipient.
Phone String Yes Main phone number which is used to send out the FolloMe SMS.
Phone2 String Additional phone number. This number will be given to the operation manager in case the recipient is not reachable.
Phone3 String Additional phone number. This number will be given to the operation manager in case the recipient is not reachable.
Email String Yes Email address under which the recipient can be contacted. This email is used for our FollowMe emails.

Code Description
1 Piece
2 Kilo
3 Liter
4 Ton
5 Pallet
6 Euro-Pallet
7 Half-pallet
8 Box
9 Cubic meter
99 Other

Name Description
RequiresSignature Signature is compulsory for this shipment.
IdentityControl Identity Check is required for this shipment.
Fragile This shipment contains fragile goods.
AskForRating Ask the recipient to provide a service rating.
AgeControl1 Check that the recipient is 16 years or older.
AgeControl2 Check that the recipient is 18 years or older.
TakeReturns Prompts the courier to ask for returns after delivery of the goods.
TakeContainersBoxes Prompts the courier to ask for empty boxes/containers to take back.
DepositInMailboxAllowed Courier can leave parcel in mailbox in case the recipient is not home.
ButlerService Prompts the courier to help to bring parcels into the appartment house or basement.
Gift Means that the delivery is a gift. Prompts the courier to treat it differently.

Code Description
1 Cash
2 Credit card
3 Invoice
11 Paid in Store
12 To be paid in Store

Code Name Description
8 New shipment with invalid address When the shipment with not exact address appeared.
10 New shipment When the shipment with correct address appeared.
12 Handover not possible This status occurs when the goods can't be accepted at handover because they don't meet the contractually agreed terms. Typically this means that the parcel is too large.
13 On Hub When the shuttle picked up the shipment from a storehouse.
16 Not Received The shipper didn't handover the goods/parcels (missing).
20 Allocated When the shipment is assigned to a driver. This event could be fired multiple times, as we real-time optimize driver’s routes.
33 Cancelled by Customer When the shipment has been cancelled by customer.
35 Cancelled by Dispatcher When the shipment has been cancelled by dispatcher.
50 Close To Pickup When the shipment is close to pickup point.
60 At Pickup When the shipment is at to pickup point.
70 On Route When the shipment is on a route to dropoff point.
90 Close to Dropoff When the shipment is close to dropoff point.
100 At Dropoff When the shipment is at to dropoff point.
101 Dropoff Failed The goods could not be delivered to the recipient. E.g. Not at home, goods refused.
103 Second Delivery The shipment is marked for a second delivery, typically on the next day.
104 Return Goods will be returned to the shipper as they could not be delivered.
105 Return Complete Goods have been returned to the shipper.
110 Dropoff Completed When the shipment is completed.

Code Name
1 German
2 English
3 French

{
"GroupGuid": "28228CFE-12F2-4BFB-B8BF-B7FF87746E96",
"PickupDate":"2015-05-31",
"PickupTimeFrom":"13:43:10Z",
"PickupTimeTo":"13:44:10Z",
"DropoffTimeFrom":"13:45:10Z",
"DropoffTimeTo":"13:46:10Z",
"PaymentType":1,
"Fee":7.00,
"Note":"Test Note",
"ShipmentType": 100,
"Labels": ["Test", "Test2"],
"Pickup":
{
"Name":"Bar",
"Phone":"+41987654321",
"City":"Z\u00fcrich",
"CountryCode":"CH",
"Postcode":"8004",
"Streetaddress":"Badenerstrasse 97",
"Labels": ["Test", "Test2"]
},
"Dropoff":
{"Name":"notime AG",
"Phone":"+41 44 508 48 48",
"City":"Z\u00fcrich",
"CountryCode":"CH",
"Postcode":"8003",
"Streetaddress":"Birmensdorferstrasse 94"
},
"Products":
[{
"Reference":"prodref01",
"Name":"Test Product",
"Fee":14.00,
"Quantity":1,
"ImageUrl": "http://test.com/image.png",
"Type": 100,
"Labels": ["Test"]
}],
"Parcels":
[{
"ParcelNumber":"01",
"Size":"S",
"Weight": 0.5
}]
}

Response 200

With all result codes the following object is sent back:

Name Type Description
ResultCode Int 0: success
ResultText String Result description
ShipmentGuid String The reference of the shipment
PickupReference String The reference of the pickup
DropoffReference String The reference of the dropoff
ErrorString String Error description


The ResultCode is always set to "0" for Response 200. The field ResultText might contain additional information about the shipment which ideally should be logged by the caller.
Typical ResultText entries are:

  • Pickup address is not rooftop level accuate.
  • Dropoff address is not rooftop level accuate.
  • Products with the same reference but different property values are passed.
  • No default time windows are configured, please specify yours.
  • More than one time window is available in settings.

{
  "ResultCode": 0,
  "ResultText":"Success",
  "ShipmentGuid":"Shipment-ref-1",
  "PickupReference":"Pickup-ref-1",
  "DropoffReference":"Dropoff-ref-1",
  "ErrorString":null
}

Response 400

Returned in case where the submitted data doesn't fit the validation or business rules. If a validation rule is broken, a json-formatted message is returned in ErrorString property together with ResultCode=99 (Other).

Code Description
1 Pickup address not recognized
2 Dropoff address not recognized
3 Invalid date
4 PickupTimeFrom is invalid
5 DropoffTimeFrom is invalid
6 PickupTimeTo is invalid
7 DropoffTimeTo is invalid
8 GroupGuid is invalid
9 Invalid shipment token
10 PickupTimeWindowGuid is invalid
11 DropoffTimeWindowGuid is invalid
18 Time window given is currently not available.
19 ServiceGuid is invalid
99 General Error - validation rule broken. Check the field ErrorString for more information. I.e. which field is wrong.

Validation rule broken:
{
   "ResultCode":99,
   "ResultText":"Other",
   "ShipmentGuid":null,
   "PickupReference":null,
   "DropoffReference":null,
   "ErrorString":"{\"shipment.PickupDate\":[\"\\\"PickupDate\\\" must be a date/time string in format \\\"dd.MM.yyyy\\\"\"]}"
}

Business rule broken:
{
   "ResultCode":1,
   "ResultText":"Pickup address not recognized",
   "ShipmentReference":null,
   "PickupReference":null,
   "DropoffReference":null,
   "ErrorString":null
}

Response 415

Currently API supports only application/json content type. Most probably you forgot to add 'Content-Type': 'application/json' header.

Response 500

Returned in case of internal server error. Specific error might be specified in status string. General status string is Internal Server Error

Code samples

@ECHO OFF

curl -v -X POST "https://v1.notimeapi.com/api/shipment"
-H "Content-Type: application/json"
-H "Ocp-Apim-Subscription-Key: {subscription key}"

--data-ascii "{body}" 
using System;
using System.Net.Http.Headers;
using System.Text;
using System.Net.Http;
using System.Web;

namespace CSHttpClientSample
{
    static class Program
    {
        static void Main()
        {
            MakeRequest();
            Console.WriteLine("Hit ENTER to exit...");
            Console.ReadLine();
        }
        
        static async void MakeRequest()
        {
            var client = new HttpClient();
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            // Request headers
            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

            var uri = "https://v1.notimeapi.com/api/shipment?" + queryString;

            HttpResponseMessage response;

            // Request body
            byte[] byteData = Encoding.UTF8.GetBytes("{body}");

            using (var content = new ByteArrayContent(byteData))
            {
               content.Headers.ContentType = new MediaTypeHeaderValue("< your content type, i.e. application/json >");
               response = await client.PostAsync(uri, content);
            }

        }
    }
}	
// // This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents-client-ga/)
import java.net.URI;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class JavaSample 
{
    public static void main(String[] args) 
    {
        HttpClient httpclient = HttpClients.createDefault();

        try
        {
            URIBuilder builder = new URIBuilder("https://v1.notimeapi.com/api/shipment");


            URI uri = builder.build();
            HttpPost request = new HttpPost(uri);
            request.setHeader("Content-Type", "application/json");
            request.setHeader("Ocp-Apim-Subscription-Key", "{subscription key}");


            // Request body
            StringEntity reqEntity = new StringEntity("{body}");
            request.setEntity(reqEntity);

            HttpResponse response = httpclient.execute(request);
            HttpEntity entity = response.getEntity();

            if (entity != null) 
            {
                System.out.println(EntityUtils.toString(entity));
            }
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

<!DOCTYPE html>
<html>
<head>
    <title>JSSample</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>

<script type="text/javascript">
    $(function() {
        var params = {
            // Request parameters
        };
      
        $.ajax({
            url: "https://v1.notimeapi.com/api/shipment?" + $.param(params),
            beforeSend: function(xhrObj){
                // Request headers
                xhrObj.setRequestHeader("Content-Type","application/json");
                xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","{subscription key}");
            },
            type: "POST",
            // Request body
            data: "{body}",
        })
        .done(function(data) {
            alert("success");
        })
        .fail(function() {
            alert("error");
        });
    });
</script>
</body>
</html>
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    NSString* path = @"https://v1.notimeapi.com/api/shipment";
    NSArray* array = @[
                         // Request parameters
                         @"entities=true",
                      ];
    
    NSString* string = [array componentsJoinedByString:@"&"];
    path = [path stringByAppendingFormat:@"?%@", string];

    NSLog(@"%@", path);

    NSMutableURLRequest* _request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]];
    [_request setHTTPMethod:@"POST"];
    // Request headers
    [_request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [_request setValue:@"{subscription key}" forHTTPHeaderField:@"Ocp-Apim-Subscription-Key"];
    // Request body
    [_request setHTTPBody:[@"{body}" dataUsingEncoding:NSUTF8StringEncoding]];
    
    NSURLResponse *response = nil;
    NSError *error = nil;
    NSData* _connectionData = [NSURLConnection sendSynchronousRequest:_request returningResponse:&response error:&error];

    if (nil != error)
    {
        NSLog(@"Error: %@", error);
    }
    else
    {
        NSError* error = nil;
        NSMutableDictionary* json = nil;
        NSString* dataString = [[NSString alloc] initWithData:_connectionData encoding:NSUTF8StringEncoding];
        NSLog(@"%@", dataString);
        
        if (nil != _connectionData)
        {
            json = [NSJSONSerialization JSONObjectWithData:_connectionData options:NSJSONReadingMutableContainers error:&error];
        }
        
        if (error || !json)
        {
            NSLog(@"Could not parse loaded json with error:%@", error);
        }
        
        NSLog(@"%@", json);
        _connectionData = nil;
    }
    
    [pool drain];

    return 0;
}
<?php
// This sample uses the Apache HTTP client from HTTP Components (http://hc.apache.org/httpcomponents-client-ga/)
require_once 'HTTP/Request2.php';

$request = new Http_Request2('https://v1.notimeapi.com/api/shipment');
$url = $request->getUrl();

$headers = array(
    // Request headers
    'Content-Type' => 'application/json',
    'Ocp-Apim-Subscription-Key' => '{subscription key}',
);

$request->setHeader($headers);

$parameters = array(
    // Request parameters
);

$url->setQueryVariables($parameters);

$request->setMethod(HTTP_Request2::METHOD_POST);

// Request body
$request->setBody("{body}");

try
{
    $response = $request->send();
    echo $response->getBody();
}
catch (HttpException $ex)
{
    echo $ex;
}

?>
########### Python 2.7 #############
import httplib, urllib, base64

headers = {
    # Request headers
    'Content-Type': 'application/json',
    'Ocp-Apim-Subscription-Key': '{subscription key}',
}

params = urllib.urlencode({
})

try:
    conn = httplib.HTTPSConnection('v1.notimeapi.com')
    conn.request("POST", "/api/shipment?%s" % params, "{body}", headers)
    response = conn.getresponse()
    data = response.read()
    print(data)
    conn.close()
except Exception as e:
    print("[Errno {0}] {1}".format(e.errno, e.strerror))

####################################

########### Python 3.2 #############
import http.client, urllib.request, urllib.parse, urllib.error, base64

headers = {
    # Request headers
    'Content-Type': 'application/json',
    'Ocp-Apim-Subscription-Key': '{subscription key}',
}

params = urllib.parse.urlencode({
})

try:
    conn = http.client.HTTPSConnection('v1.notimeapi.com')
    conn.request("POST", "/api/shipment?%s" % params, "{body}", headers)
    response = conn.getresponse()
    data = response.read()
    print(data)
    conn.close()
except Exception as e:
    print("[Errno {0}] {1}".format(e.errno, e.strerror))

####################################
require 'net/http'

uri = URI('https://v1.notimeapi.com/api/shipment')

request = Net::HTTP::Post.new(uri.request_uri)
# Request headers
request['Content-Type'] = 'application/json'
# Request headers
request['Ocp-Apim-Subscription-Key'] = '{subscription key}'
# Request body
request.body = "{body}"

response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
    http.request(request)
end

puts response.body