Shipment API
API change historyREST 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
Request URL
Request headers
-
(optional)stringMedia type of the body sent to the API.
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:
|
||
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. | |
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:
|
||
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. | |
ServiceFeeCategory | Guid | Guid identifying service fee charged to the enduser. The available service fees need to be configured manually and stored against your service. This parameter is only used in rare cases where we have different fee structures for the same service. | ||
DisablePhoneNotification | Boolean | False | Indicates whether the shipment FollowMe SMS communication is disabled. |
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 | The name of the organisation "IBM Germany" that is located at this POI. | |
ContactName | String | The name of the person (resident) that is located at this POI, or the name of the contact person in case Name of organisation is specified | ||
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 |
---|---|---|---|---|
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. In case all the dimensions of the parcel are provided the size gets calculated automatically. | ||
Weight | Double | Optional information about the weight of the parcel in kg. | ||
Length | Double | Optional information about the length of the parcel in cm. | ||
Width | Double | Optional information about the width of the parcel in cm. | ||
Height | Double | Optional information about the height of the parcel in cm. | ||
Type | int | Optional ParcelType. | ||
Name | String | Optional name of product inside a parcel. | ||
ImageUrl | String | Optional image url of product. This picture will be passed on to the courier and is visible to the operation manager. | ||
Notes | String | Optional notes. Maximum length is 256 symbols. | ||
ProductBarcodes | Array of String | Optional barcodes of original product. | ||
RequiredBarcodeTypes | Array of Product Barcode Type | Optional list of product barcode types. | ||
StorageReference | String | Optional product storage location. |
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 |
ClusterPoint | String | Cluster point code, in case the shipment is related to one |
TourLetter | String | Tour letter, in case the shipment is allocated to a tour |
StopNumber | Int | Stop number, in case the shipment is allocated to a tour |
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. | ||
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 apartment 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 | Description |
---|---|
1 | Undefined Parcel Type |
2 | Temperature device |
3 | Regular Post Parcel |
4 | Shopping Bag |
5 | Original Product |
6 | Cooked Food |
7 | Open Container (used for shrinking) |
8 | Closed Container (used for shrinking) |
9 | Thermo box |
10 | Thermo bag |
11 | Hotgood ("Valuable, Expensive Product") |
12 | Power Adapter |
Code | Description |
---|---|
1 | Serial Number |
2 | IMEI |
Code | Name |
---|---|
1 | German |
2 | English |
3 | French |
{
"GroupGuid": "28228CFE-12F2-4BFB-B8BF-B7FF87746E96",
"PickupDate": "2015-05-31T00:00:00.0000000+00:00",
"PickupTimeFrom": "2020-01-22T13:43:10.0000000+00:00",
"PickupTimeTo": "2020-01-22T13:44:10.0000000+00:00",
"DropoffTimeFrom": "2020-01-22T13:45:10.0000000+00:00",
"DropoffTimeTo": "2020-01-22T13:46:10.0000000+00:00",
"PaymentType": 1,
"Fee": 7,
"Note": "Test Note",
"ShipmentType": 100,
"Labels": [
"Test",
"Test2"
],
"Pickup": {
"Name": "Bar",
"Phone": 41987654321,
"City": "Zürich",
"CountryCode": "CH",
"Postcode": 8004,
"Streetaddress": "Badenerstrasse 97",
"Labels": [
"Test",
"Test2"
]
},
"Dropoff": {
"Name": "notime AG",
"Phone": "+41 44 508 48 48",
"City": "Zürich",
"CountryCode": "CH",
"Postcode": 8003,
"Streetaddress": "Birmensdorferstrasse 94"
},
"Parcels": [
{
"ParcelNumber": 1,
"Size": "S",
"Weight": 0.5,
"ImageUrl": "http://test.com/image.png",
"Name": "Test Product"
}
]
}
Responses
200 OK
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 |
Typical ResultText entries are:
- Pickup address is not rooftop level accuate.
- Dropoff address is not rooftop level accuate.
- No default time windows are configured, please specify yours.
- More than one time window is available in settings.
Representations
{
"ResultCode": 0,
"ResultText": "Success",
"ShipmentGuid": "Shipment-ref-1",
"PickupReference": "Pickup-ref-1",
"DropoffReference": "Dropoff-ref-1",
"ErrorString": null
}
400 Bad Request
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. |
Representations
415 Unsupported Media Type
Currently API supports only application/json content type. Most probably you forgot to add 'Content-Type': 'application/json' header.
500 Internal Server Error
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