fulfillmenttools can connect to various carriers allowing you to create shipments and corresponding parcels. Please clarify beforehand which carriers should be made available to your instance.
However, the usage of existing & ready to use carriers is similar and can be used no matter how many carriers you operate.
Carrier
Courier, Express and Parcel Services (or in Short: CEP) refer to entities, that are in general configured in fulfillmenttools. It depends on your setup which CEP Providers are available & ready to use. The API description including some documentation about the used attributes can be found in our API reference
Good to know
By default, a freshly created tenant system does not show the available carriers within the backoffice since most of the carriers are country-specific. Activating a carrier has to be done via API. After that, it can be configured within the backoffice.
To get a list of available carriers you can issue the following call:
The response gives you a list of configured carriers, along with some general information and their key, which describes which kind of implementation is chosen by fulfillmenttools whenever this carrier is used to, for example, issue a label request or setup track and trace connection for a parcel. You can get a more detailed look at a configured carrier by requesting one identified carrier instance, for example:
A Carrier instance is a singleton in any given fulfillmenttools platform. That means in general it can exist exactly once per tenant.
As you can see in the above response there are some configurations made to this exact carrier (DHL in this case). These configurations can be done on every carrier instance (check Add Carrier for details or continue reading.
Creation of a carrier
A carrier can be created by issuing the following call:
As you can see there are already some configurations to this carrier provided upon creation. Some of the interesting data is
Attribute
Description
defaultParcelWeightInGram
parcelLabelClassifications
This array of values describes which parcel dimensions should be selectable by a client when issuing a parcel. Please see, that these values are dependent on the carrier and your contract with it. It also maybe not be a mandatory value and could possibly be omitted.
credentials
The credentials that are used to connect to the carriers' API. Which kind of credentials is needed depends on the carrier (selected by the attribute key. In this case the DHL API in Version 2 is selected. Thus we need to provide an API Key. Also there is (especially for DHL) the possibility to provide Fallback Credentials using the legacy DHL API ("DHL Geschäftskunden API" in this case.)
logoUrl
This optional attribute can be used to set a specific logo to a custom carrier or to overwrite the fallback logos for standard carriers provided by fulfillmenttools if needed.
Carrier specific configuration
Depending on the used Carrier implementation (depicted by the tag key) some additional configuration can be used to successfully operate a carrier:
One of the most important configurations is the attribute returnLabel in a given configuration. It tells fulfillmenttools whether a return label should be created with every label requested from the given carrier.
This resource describes the stores, warehouses, popup stores, locations, etc. of the fulfillment network. In general, a facility is a place where fulfillment processes take place or should be considered. Details see use case Add and Manage Facilities
In this carrier services related use case a facility is a place where CEP services pick up parcels or inter facility transfers are started / finished.
Connection between a Facility and a Carrier
Users can assign different carriers to one facility. With this information a fencing can be implemented where orders which need to be shipped by a chosen carrier are routed to a facility where this carrier is active. Carrier that are enabled on tenant level must also be enabled for the facilities in which this carrier is available.
The Facility-To-Carrier-Connection is (some people already understood) the connection between a facility and a carrier. Many configurations that allow for frictionless carrier services have to be configured here. Please refer to FacilityCarrierConnection for detailed information on every attribute. Here are some of the attributes worth mentioning:
Attribute
Description
cutoffTime
Value (hour and minute) describe the time when the carrier (usually) shows up to take parcels with him. This information is especially useful when configuring SAMEDAY deliveries as it is crucial to have finished any fulfillment process until the arrival of the carrier.
deliveryAreas
This optional value might be of special interest to Custom Carriers and specific SAMEDAY carriers. It shows which target addresses (identified by an array of ISO 3166-1 alpha-2 conform country codes and their respective postalcodes) can be a valid target to a parcel sent via this carrier from the facility.
Connect an existing carrier to a facility
Let's assume that we have a facility (see Add and Manage Facilities) and a carrier (see Creation of a carrier) already created. Lets receive the correspondent entities first (omitting some of the attributes):
curl-sSL'https://your.api.fulfillmenttools.com/api/facilities/a81a1c85-cfe5-49d3-81d3-675154ef323e' \--header'Authorization: Bearer <TOKEN>'200OK{"id":"a81a1c85-cfe5-49d3-81d3-675154ef323e","name":"Darkstore Cologne","address":{"street":"Schanzenstr.","houseNumber":"8-20","postalCode":"51063","city":"Cologne","country":"DE","companyName":"fulfillmenttools","resolvedCoordinates":{"lon":7.013988,"lat":50.964969 },"resolvedTimeZone":{"offsetInSeconds":3600,"timeZoneId":"Europe/Berlin","timeZoneName":"W. Europe Standard Time" },... },"locationType":"WAREHOUSE","services": [ {"type":"PICKUP" }, {"type":"SHIP_FROM_STORE" } ],"status":"ONLINE","created":"2022-12-20T10:00:48.419Z","lastModified":"2023-03-27T14:13:51.213Z","version":6,...}
Please take note of two important parameters we are going to use in the following: The id of the facility (a81a1c85-cfe5-49d3-81d3-675154ef323e in this case) and the id of the carrier (488bd1a6-6c76-4407-8dab-ece716dac14d). We need both values in order to create a connection between those two entities.
The Connection
By using both values in our target URL the following call we configure the carrier to said facility:
The empty array of the attribute deliveryAreas indicates, that there are no restrictions regarding delivery targets.
We also conveniently set the cutoff time to 16:30, because in our fictive case this is the time when the DHL driver typically arrives at the Darkstore to pick up the parcels.
That's it: As long as the Carrier and the FacilityCarrierConnection stays in status "ACTIVE", it should be possible to create shipments and in the end also parcels using DHL as a CEP (see Create a shipment with parcels to track) originating from this facility.
Create a shipment with parcels to track
Before we dive into the process of sending a parcel we need to clarify two more entities: Shipment and Parcel.
Entity
Description
Parcel
A parcel is the digital representation of one physical parcel that is avised / on its way to the consumer.
Shipment
A shipment is the bracket around all parcels sent within a process using the same carrier. Please note: Certain data could vary from parcel to parcel: dimensions or targetAddress of the shipment can be overwritten in a parcel instance.
Let's assume we already connected a Facility with a Carrier using a FacilityCarrierConnection (see Connect an existing carrier to a facility). In this use case we are going to create a standalone shipment and two parcels - without having a Pickjob or any other leading entity. This is a perfect example on how flexible fulfillmenttools is: There might be standard processes, but you are also able to use parts of the system to suit your operational needs - like for example the need of dynamically create a Shipment Label for further use in other systems.
Create Shipment for pickup in a facility and by a carrier
With the following call we create a shipment to be picked up in facility with ID 4fd70a59-9efe-40fd-808b-08ae86ca558f using the DHL Carrier with ID 488bd1a6-6c76-4407-8dab-ece716dac14d:
As you can see: The shipment has knowledge about the facility, the CEP and the address where to deliver.
As mentioned above: This shipment is not connected to any existing process! If you want to create a shipment to a specific process you need to provide the attribute processId within the request. Also shipments can be created during preceding processes. In that case data like the target address is provided via the order or the pickjob to the shipment which is created by fulfillmenttools.
Having the Shipment in place we are now ready to create a parcel via this shipment by issuing the following request:
curl-sSL-XPOST'https://your.api.fulfillmenttools.com/api/shipments/3e62db41-af9e-4ce1-8c44-1ef340457057/parcels' \--header'Authorization: Bearer <TOKEN>'201Created{"loadUnitRefs": [],"version":1,"id":"713b9cd8-6d47-45ff-a12a-ef3acb270180","status":"OPEN","shipmentRef":"3e62db41-af9e-4ce1-8c44-1ef340457057","processRef":"3af2e1a7-d104-4ef9-a43b-13890ae318cf","carrierRef":"488bd1a6-6c76-4407-8dab-ece716dac14d","recipient":{"firstName":"Luke","lastName":"Skywalker","street":"Planetenstraße","houseNumber":"13","postalCode":"40223","city":"Düsseldorf","country":"DE" },"sender":{"street":"Carlsplatz","houseNumber":"3","postalCode":"40213","city":"Düsseldorf","country":"DE","companyName":"ptdus","resolvedCoordinates":{"lon":6.77285093516085,"lat":51.2263665950437 },"emailAddresses":null,"additionalAddressInfo":null,"phoneNumbers":null,"resolvedTimeZone":{"offsetInSeconds":3600,"timeZoneId":"Europe/Berlin","timeZoneName":"W. Europe Standard Time" } },"dimensions":{"weight":2000 },"created":"2023-04-14T15:03:07.982Z","lastModified":"2023-04-14T15:03:07.982Z"}
Please take note that we are issuing a parcel the most simple way in which fulfillmenttools will use all necessary information from the corresponding shipment. However, you are also able to overwrite certain data from the shipment for each created parcel, such as the dimensions, the recipient, the sender or return address.
We just created the entity that represents the parcel in status OPEN. Now, in an async matter, fulfillmenttools is automatically taking care of the actual advising of the parcel label. During the time it takes fulfillmenttools and the CEPs API to negotiate and create a parcel, the status of the parcel changes from OPEN via PROCESSING to finally DONE. The shipment also transparently changes its status to CONFIRMED as soon as all created parcels of the shipment reached the status DONE.
Interpreting the result of a parcel request
Once the parcel reached one of the status DONE (happy case) or FAILED it is time to take a look at the result attribute of the parcel:
The result in general shows details about the outcome of the request:
In case of a successful termination of the request towards this specific CEP API (see above) we can find the trackingNumber, a tracking URL, a label to download the sendLabel and also with the attribute labelUrl a document that consists of all the documents that are of importance to this parcel (such as for example deliveryNotes, return labels, etc.).
In case of a unsuccessful termination of the request the summary attribute carries information about the root cause of the failure. The contents of this error message usually originates from the carrier - fulfillmenttools has limited control about the data.
In this case we are ready to download the avised label using the following call:
It is also possible to pass the information directly when creating an order. In the order the services can be directly listed for each preferredCarrierWithProducts:
curl --location --globoff '{{host}}/api/orders' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{authToken}}' \
--data-raw '{
"orderDate": "2023-03-11T08:16:07.000Z",
"deliveryPreferences": {
"shipping": {
"preferredCarriersWithProduct": [
{
"carrierKey": "BPOST",
"carrierServices": [
"SIGNATURE"
]
}
]
}
},
"consumer": {
"email": "ulf.steinke@ocff.de",
"addresses": [
{
"salutation": "Dhr.",
"firstName": "Jean",
"lastName": "Peeters",
"street": "Breidelstraat",
"houseNumber": "2",
"postalCode": "8000",
"city": "Brugge",
"country": "BE",
"emailAddress": "Jean.Peeters@yahoo.com",
"additionalAddressInfo": "637148",
"phoneNumber": "526-640-7512",
"addressType": "POSTAL_ADDRESS"
}
]
},
"tenantOrderId": "FC-4711-2361",
"status": "OPEN",
"orderLineItems": [
{
"article": {
"tenantArticleId": "2020249",
"title": "T-Shirt \"Am Sonnenhut\"",
"imageUrl": "https://d358g9injarr4u.cloudfront.net/res/product_1000/240eadd8-8f50-479d-b0d8-74412bd4a9f9.jpg",
"attributes": [
{
"category": "miscellaneous",
"key": "BRAND",
"value": "Adidas"
},
{
"category": "descriptive",
"priority": 100,
"key": "%%subtitle%%",
"value": "Neu!"
},
{
"category": "descriptive",
"priority": 200,
"key": "Mitgliederpreis",
"value": "17,96 EUR"
},
{
"category": "descriptive",
"priority": 300,
"key": "Schnitt",
"value": "Frauen"
},
{
"category": "descriptive",
"priority": 400,
"key": "Material",
"value": "100% Baumwolle"
},
{
"category": "descriptive",
"priority": 500,
"key": "Artikelnummer",
"value": "2020249"
},
{
"category": "descriptive",
"priority": 600,
"key": "Größe",
"value": "S"
},
{
"category": "descriptive",
"priority": 700,
"key": "Beschreibung",
"value": "Rotes T-Shirt mit weißen Streifen an den Ärmeln, Blockdruck mit Schriftzug auf der Brust"
}
]
},
"quantity": 1,
"scannableCodes": [
"2020249"
]
},
{
"article": {
"tenantArticleId": "2010681",
"title": "Steppjacke \"Mühlenbach\"",
"imageUrl": "https://d358g9injarr4u.cloudfront.net/res/product_1000/9fcb7e42-7c84-4ab0-999a-869efe077e0a.jpg",
"attributes": [
{
"category": "descriptive",
"priority": 100,
"key": "%%subtitle%%",
"value": "Neu!"
},
{
"category": "descriptive",
"priority": 200,
"key": "Größe",
"value": "L"
},
{
"category": "descriptive",
"priority": 300,
"key": "Oberstoff",
"value": "100% Polyester"
},
{
"category": "descriptive",
"priority": 400,
"key": "Futter",
"value": "100% Polyester"
},
{
"category": "descriptive",
"priority": 500,
"key": "Füllung",
"value": "100% Polyester"
},
{
"category": "descriptive",
"priority": 600,
"key": "Beschreibung",
"value": "Dreifarbige Steppjacke mit verstaubarer Kapuze, Zwei Eingriffstaschen, Gesticktes Logo auf der Brust"
},
{
"category": "descriptive",
"priority": 700,
"key": "Artikelnummer",
"value": "2010681"
}
]
},
"quantity": 1,
"scannableCodes": [
"2010681"
]
},
{
"article": {
"tenantArticleId": "5020064",
"title": "Wandtattoo Stadion",
"imageUrl": "https://d358g9injarr4u.cloudfront.net/res/product_1000/343f4569-66bb-4b0c-aa2b-20011a51b620.jpg",
"attributes": [
{
"category": "descriptive",
"priority": 100,
"key": "Maße",
"value": "70 x 50 cm"
},
{
"category": "descriptive",
"priority": 200,
"key": "Beschreibung",
"value": "Wandtattoo in Ziegelwand-Optik, Mit tollem Blick aufs Stadion"
},
{
"category": "descriptive",
"priority": 300,
"key": "Anwendung",
"value": "Für die Beklebung sollte die Fläche staub- und fetfrei sein. Bringen Sie den Aufkleber in Position und reiben Sie diese gleichmäßig mit der flachen Hand an den Untergrund, um sie zu fixieren. Jede Stelle nochmals gest andrücken. Fertig! Für auftretende Schäden nach der Verklebung auf dem Untergrund etc. ist eine Haftung ausgeschlossen."
},
{
"category": "descriptive",
"priority": 400,
"key": "Artikelnummer",
"value": "5020064"
}
]
},
"quantity": 2,
"scannableCodes": [
"5020064"
]
}
],
"paymentInfo": {
"currency": "EUR"
}
}'
Only services offered by the chosen carrier will be taken when creating a parcel. Providing a service for a carrier which does not offer that service will be ignored.
Setting Carrier URLs
Whether you want to operate against sandbox URLs or against real URLs provided by CEPs can be configured on different levels.
You can set carrier specific URLs tenant-wide, so they are being used in every facility or you can decide to set URLs for specific facilities separately. In order to achieve this, set the URLs as shown in the following by setting the carrier configuration and/or the facility carrier configuration.
Carrier Level URLs
Setting the carrier URLs on carrier level will result in these URLs being used whenever this carrier is used in a facility. Use the following endpoint to set the URL.
The following example demonstrates how to set the service url and track and trace url for a DHL carrier.
Setting the carrier URLs on facility level will overwrite any URL that has been set on carrier level for the respective carrier.
The URLs on facility carrier level can be set by updating the configuration in the facility carrier connection. The following endpoint can be used for this purpose.
This example shows how to set the urls for a GLS carrier.
This value depicts, no surprise here, the default value (1000 gram) to a parcel advised using this carrier. However, the actual weight might be overwritten by the actual call for the creation of a parcel (see in our API Specification).