Introduction

Graphmasters APIs are organized around REST. They aim to have predictable and intuitive URLs, accept JSON-encoded request bodies and responses, and use standard HTTP response codes, authentication, and verbs.

BASE URL

                        https://courier-api.graphmasters.net
                        

                    

Authentication

The Graphmasters APIs use API-Keys to authenticate requests. Your API Key contains specific permissions only you should have. So make sure you never communicate the key via email and you do not lose it. Also do not check in your key into code directly, always use secrets for that.

The authentication is performed using the Authorization header. The value of the header should be prefixed by api-key followed by the key itself, like shown in the example.

If the API KEY is invalid or not present, status code 401 will be returned by every endpoint expecting authentication.

All API calls must be made over HTTPS. Calls made over plain HTTP will fail.

AUTHENTICATED REQUEST
curl --request POST 'https://courier-api.graphmasters.net/api/endpoint' \
     --header 'Authorization: api-key << INSERT SECRET API KEY >>'

Your Api Key
You can obtain your API-Key from your personal support contact.
Should you be unsure whom to contact,
write an email to: support@graphmasters.net

Data Compression

The request payload as well as the response payload can be compressed using the gzip algorithm. To send a gzip compressed request payload, add the header Content-Encoding: gzip.

If you would like to receive compressed responses, add the request header Accept-Encoding: gzip. The response will contain the header Content-Encoding: gzip if the response body is compressed.

EXAMPLE: COMPRESSED REQUEST AND RESPONSE
curl --request POST 'https://courier-api.graphmasters.net/api/endpoint' \
     --header 'Content-Encoding: gzip' \
     --header 'Accept-Encoding: gzip'

Time Formats

All objects that contain times, such as for example the pickupTime of the drivingOrder, will be coded in the RFC3339 standard. This is an example of a RFC3339 time

  • 2020-07-10T14:30:20+02:00 uses the +02:00 time zone
  • 2020-07-10T14:30:20Z uses the UTC time zone
Example object with timestamps
{
  "timestamp": "2020-07-10T14:30:20+02:00",
  "timestampUtc": "2020-07-10T14:30:20Z",
}

Errors

We use conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, the json was malformed, etc.). Codes in the 5xx range indicate an error with our servers (these are rare).

Some errors can be handled automatically by the client, these contain an error code which is documented in the endpoint description.

Generally we believe that in the best case the error message needs to answer three questions: What has gone wrong? Why has it gone wrong? How to prevent this the next time? An error response from our API is shown on the right and contains the following parameters:

  • cause: the error message itself, mostly quite technical.
  • description: a textual description of what went wrong.
  • errorCode: a numerical error code for exactly that error.
  • isRetryable: whether a retry-policy should be executed.
  • resolution: a textual description of how to resolve the error.

The question "what" is answered by the text in the description, the "why" is answered by the cause and the "how" is answered by the resolution field. Note that these properties are optional and not all errors return all of these properties (it is pretty hard to have such detailed error message for all possible errors, so take this with a grain of salt).

Example error response
{
  "description": "failed to import vehicle data",
  "cause": "failed to unmarshal request body: json.SyntaxError: invalid character '(' looking for the beginnning of value: Offset: 38",
  "resolution": "try to build correct jsons, see https://www.json.org/json-en.html for reference.",
  "errorCode": 1505,
  "isRetryable": false,
}

Functional API Design

Most APIs are described as RESTful HTTP, however REST and HTTP are two distinct things. HTTP is just the protocol with which the API is realised, REST is the paradigm of how an API is structured. Most RESTful APIs are realised using HTTP, but that is not necessarily a requirement. Vice versa, it is also possible to design an API using HTTP but not the REST paradigm. This API is such a case, and this chapter shall explain the paradigm that was used and most importantly, why it was used.

REST stands for REpresentational State Transfer and follows these basic principles:

  • Resources can be uniquely identified.
  • Usage of HTTP standard methods.
  • Stateless communication.
  • Possibility of different representations of resources.
  • Hypermedia is used.
In a service that consists of resources which can be manipulated by the client, this works very well and gives the developer an easy way to find himself around the API. But that is not necessarily the case for all services. The one thing which one has to bear in mind when going for a RESTful API is that the client basically has to provide the logic, which decides when and how to change resources. The server acts pretty much like a database with simple CRUD operations.

For many APIs this is a good design and fits very well, however in our case we are hiding the logic on the service, because it is so complex and comes with so many constraints, that burdening the client and thus our customer with it is simply not feasible at all. That is why we decided against a RESTful API and instead provide more of an RPC style API which is realised using HTTP. RPC stands for Remote Procedure Call and basically means that the API works more like a list of functions that are grouped into meaningful namespaces.

Lets give some simple examples. Instead of creating and getting a Vehicle in our API the RESTful way like so:

REST style
HTTP POST /api/v1/vehicles      // to create a new vehicle
HTTP GET  /api/v1/vehicles/327  // to get the vehicle with the ID 327
we would offer calls like this:
RPC style
HTTP POST /api/v1/vehicles.create      // to create a new vehicle
HTTP POST /api/v1/vehicles.get         // to get the vehicle (the ID will be somewhere in the request body)
For the given example of creating and getting a resource such as a Vehicle, surely the RESTful design is just as good, if not even better than the RPC design. However, our API does not only consist of CRUD operations. Take for example the preview of a job prediction. This functionality basically predicts incomplete job data and returns the prediction result as a preview (so no state changes on the server happened). The RPC style call could be the following:
RPC style
HTTP POST /api/v1/jobprediction.preview
But how would a RESTful representation look like? It would have to be a HTTP GET, because according to the REST specification a call that does not change the state has to be a GET, HEAD or OPTIONS. (the latter two do not apply). Some suggestions:
REST style
HTTP GET /api/v1/jobprediction/preview
Does not sound too bad, but there is one problem with it, which is that HTTP GETs do technically allow request bodies, however it is forbidden in REST and also not good practice because some implementation of HTTP clients simply do not allow it. So where do we put a rather large set of data that needs to go along with the call?

This dilemma happened in so many places of the API that we simply decided a RESTful design does not really apply for us. The downside of the RPC design is that it is not very common these days, which make it a bit less expected. However, we are trying our best to design meaningful and predictable namespaces as well as verbs that strongly link to the functionality in the call, so that it should hopefully be easy to find what is needed and to understand what it does.

Lastly, to understand the design a bit better, here are some global decisions that might help you when navigating the API:

  • The HTTP method POST is used for almost all calls, the method DELETE for any call that involves deletion.
  • The functions all end with a verb like .create, .get, .change or other.
  • Calls are grouped into main categories like Jobs, Vehicles but also Timeslot Evaluation.
  • Calls can have sub-namespaces, e.g. optimisation.status.get. These namespaces shall make the function even clearer.
  • HTTP headers are not used except for things like data compression.
  • HTTP query variables like https://example.com/api/resource?variable=123 are not used at all.
  • HTTP path variables like https://example.com/api/resource/variable/function are not used at all.

API Reference ID

In NUNAV Courier data is always grouped into depots, which can either be actual depots of your organisation or it could be just a virtual grouping of data. Either way, with each API call we need to reference the depot in which data should be changed, deleted or retrieved. This can be done in one of two ways: Either you provide the Depot ID, which is the actual unique ID of the depot inside the NUNAV Courier system, or you provide an API Reference ID, which is an ID you manually set on the depot via the NUNAV Courier website. You have to ensure that this ID is unique among the depots yourself.

Shifts

Tours and their corresponding Jobs and Shipments are organised along the timeline in so-called Shifts. Whether your business is operating a shift per day, three shifts per day or rather one shift per week or month, it does not matter. Each depot can have its own Shift Schedule, which describes the shift strategy for that depot.

This forces us to provide the Shift alongside some base entities, so that we can place them correctly in time. The Shift can be identified by its beginning timestamp, e.g. "2022-12-06T00:00:00+01:00".

Common Types

Some types are used in many places in the API. They are described here for convenience.

Duration
Durations are commonly used in many entities, and basically represent a span of time. Some APIs use integers to represent durations in milliseconds. However, we decided that there are two disadvantages to this approach:

  • It is not very clear which unit was used and the unit needs to either be documented or within the property name.
  • For large durations like 10 hours, the numbers get huge and unreadable by a human, making debugging unnecessarily hard.
Therefore, we decided to use a custom type that represents a duration in a human-readable way. The duration is represented as a string in the form "72h3m0.5s". Leading zero units are omitted. As a special case, durations less than one second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure that the leading digit is non-zero. The zero duration formats as 0s. Formats are:
  • h: Hours (e.g. 2h)
  • m: Minutes (e.g. 1m)
  • s: Seconds (e.g. 72s)
  • ms: Milliseconds (e.g. 123ms)
  • µs: Microseconds (e.g. 123456µs)
  • ns: Nanoseconds (e.g. 123456789ns)

Input Validation

For all API calls the first thing that happens before executing the logic behind, is to Validate the correctness of the request. There can be technical validation errors such as a negative number where a positive number is expected, there can also be required properties missing. Furthermore there can be logical errors such as the closing of a time window is before the opening of the time window.

Many more validation errors might occur especially when first implementing the API. In order to make it easy for the developer to find common mistakes, the service returns a ValidationErrorResponse if the validation has failed. This response contains an array of errors that the developer can work off.

We believe it is important to provide three pieces of data for finding the error.

  • The property that contains a validation error
  • A problem description
  • A resolution to the problem

With these three pieces of information it should be possible to understand and fix the problem. If any validation error is still present, the request will not be executed at all.

Example validation error response
{
  "error": "the provided request has been invalid, review the list of problems to fix the request",
  "problems": [
    {
      "property": "jobs[0]/timeConstraints[0]/till",
      "problem": "the closing time is before the opening time",
      "resolution": "set the closing of the time window after the opening of the time window",
    },
    {
      "property": "jobs[4]/jobAction",
      "problem": "unknown job action: bla",
      "resolution": "consult the API reference for a list of valid job actions",
    }
  ]
}

API Category Overview

This chapter contains all available API Endpoints grouped into general categories. In order to make it easy to understand the API, we present it from endpoint to data model. Thus, for each endpoint there is a textual description of the endpoint, followed by the technical definition of the endpoint and each data model used for it. In that way we can present data model alongside the endpoint rather than separated.

The categories always start with some explanation about the category as well as an overview of which endpoints are available within the category. This also includes a quick link to each endpoint. What follows is an alphabetically ordered list of all endpoints available in the API.

clients.createCreates or updates Clients. Any Client that already exists will be overwritten completely, any new Client will be created.
clients.deleteDeletes Clients. The Jobs which still reference a deleted Client will remain and have a temporary copy of the Client.
clients.getGets specific Clients or all Clients of a Depot.
clients.patchPatches selected properties of existing Clients. Optionally creates Clients that do not yet exist.
depots.getThis endpoint allows you to get one or more existing Depots. There is also an option to get all Depots.
drivers.createCreates or updates Drivers. Any Driver that already exists will be overwritten completely, any new Driver will be created.
drivers.deleteDeletes Drivers. The Tours which still reference a deleted Driver will also be deleted.
drivers.getGets specific Drivers or all Drivers of a Depot.
drivers.patchPatches selected properties of existing Drivers. Optionally creates Drivers that do not yet exist.
jobs.createCreates or updates Jobs. Any Job that already exists will be overwritten completely, any new Job will be created.
jobs.deleteDeletes Jobs. The Tours which still reference a deleted Job will be updated and the Job removed from the Tour.
jobs.getGets specific Jobs or all Jobs of a Shift and/or Depot.
jobs.reassignReassigns Jobs from one Tour or the list of unassigned Jobs to a Tour.
jobs.status.changeChanges the status of a Job within a Tour. Most commonly it is used to finish the Job.
jobs.unassignUnassigns Jobs from Tours into the list of unassigned Jobs.
jobtracking.trackGathers detailed information about when a Job will be performed during a Tour. Basically tries to answer the question: 'when will I get my delivery?'.
optimisation.applyApplies the resulting Tours of a specific optimisation.
optimisation.cancelCancels a running optimisation. There will be no valid results that could be applied.
optimisation.depot.startTriggers an optimisation of all Vehicles, Drivers and Jobs for a specific Shift in a Depot. The resulting Tours will overwrite already existing Tours.
optimisation.status.getGets the current status of a specific optimisation.
tours.createShortcut function to import a full Tour. It can make use of an existing Vehicle & Driver or automatically creates a default Vehicle & Driver in the call directly. The Jobs included in the request body will be created and assigned to the Tour.
tours.deleteDeletes Tours. The Jobs which still reference a deleted Tour can either be deleted alongside the Tours or be reassigned to the Depot.
tours.getGets specific Tours or all Tours of a Shift and/or Depot.
vehicles.createCreates or updates Vehicles. Any Vehicle that already exists will be overwritten completely, any new Vehicle will be created.
vehicles.deleteDeletes Vehicles. The Tours which still reference a deleted Vehicle will also be deleted.
vehicles.getGets specific Vehicles or all Vehicles of a Depot.
vehicles.patchPatches selected properties of existing Vehicles. Optionally creates Vehicles that do not yet exist.

Clients

The Clients category allows the user to perform basic CRUD operations on Clients.

A Client represents a place or client to be serviced. It could be that your business works with a fixed set of Clients that each have an ID in your system, there is however also the option to have anonymous Clients that get generated along the data import. Most importantly the Client contains an exact geographic location, maybe availabilities in terms of opening hours and other restrictions towards entities like the Vehicle or Driver.

Endpoints in this category contain the creation, deletion and modification of Clients along with the retrieval of Clients.

clients.create

Creates or updates Clients. Any Client that already exists will be overwritten completely, any new Client will be created.


Request Body

CreateClientsRequest

Request to create or update a set of Clients.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of Clients which should be created or updated.

Client

A Client represents a place or client to be serviced. It could be that your business works with a fixed set of Clients that each have an ID in your system, there is however also the option to have anonymous Clients that get generated along the data import. Most importantly the Client contains an exact geographic location, maybe availabilities in terms of opening hours and other restrictions towards entities like the Vehicle or Driver.


An optional reference to another depot, this should only be used if the Client exists in another depot than the Job. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The unique ID for the Client. By default, a random ID will be generated.


The name of the Client.


The time spent at the Client, includes several different components.

ServiceTime

Describes the time spent at the Client during a Stop. Consists of various different aspects.


The time it takes to park the Vehicle once the navigation has finished. Also includes the time it takes to get back onto the street after the stop.


The time it takes to walk from parking location to delivery location and back once. On the Job we can define the number of walks needed, which will be multiplied to the single walking time.


Extra time that is added to the service time if the Vehicle has a trailer.


Extra time needed to hitch a trailer to a Vehicle. This will be added to the hitching time modelled on the Trailer.


Extra time needed to unhitch a trailer from a Vehicle. This will be added to the unhitching time modelled on the Trailer.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


The geographic location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Vehicle types that are prohibited to service this Client.

VehicleType

Lists all valid vehicle types. This type affects the travel times and distances as well as some road / client restrictions.


The Vehicle is a van < 3.5t.


The Vehicle is a truck < 40t.


The Vehicle is a truck that also has a separate trailer, all in all < 40t.


The Vehicle is a bus < 40t.


The Vehicle is a motorcycle.


The Vehicle is a bike.


The Vehicle is a cargo bike, which is slightly wider than a normal bike.


The Vehicle is a pedestrian - which is a bit odd but easier in terms of modelling.


Time windows in which the Client cannot be served. This property has priority over time constraints and is regarded as a hard constraint. Furthermore, it will enforce the departure at the client before the prohibited delivery time starts.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Time constraints on the Client, which are only applied to Jobs under a certain condition.

ConditionalTimeConstraints

Represents a time constraint that is applied to a Job only under a certain condition.


The time windows itself are generated from this TimeSchedule.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Exceptions, at which it is not valid.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


If set, only for provided assortments the time constraint is valid.


If set, only for provided job actions the time constraint is valid.


If true, time constraints resulting from this are hard.


If applyHardTimeConstraint is true, this is the duration of the hard time constraint, measured from the beginning of the time constraint.


Enforces the Tour to be planned such that the stop is finished before the 'hard till' time constraint. By default, the arrival time is what counts, but this will set the departure time against the time constraints. Default value: 'false'.


Additional, non planning-relevant, information about the Client.

ClientInformation

Information about a Client, which is not planning-relevant but may be useful for driver and dispatcher.


Free-text information for the driver, when navigating to the Client. This info-text is shown in the navigation application.


A telephone number that helps both driver and dispatcher to contact someone at the Client.


Data is a general data map with string key-values in which unstructured data can be placed.


If set to true, the Clients will only be created, but existing Clients will not be updated.

POST /api/v1/clients.create
curl --request POST 'https://courier-api.graphmasters.net/api/v1/clients.create' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "clients": [
        {
          "depotReference": {
            "referenceId": "depot-berlin-1",
            "referenceType": "depot-id"
          },
          "id": "37e2595e",
          "name": "Jane Doe",
          "serviceTime": {
            "parkingTime": "3m",
            "walkingTime": "25s",
            "additionalTrailerTime": 10m,
            "additionalTrailerHitchingTime": 5m,
            "additionalTrailerUnhitchingTime": 5m
          },
          "address": {
            "street": "Hollerithallee",
            "houseNumber": "17",
            "postcode": "30419",
            "city": "Hannover",
            "country": "Germany"
          },
          "location": {
            "navigationLocation": {
              "latitude": 52.412861820839325,
              "longitude": 9.632570668893964,
              "heading": 180.0
            },
            "serviceLocation": {
              "latitude": 52.412861820839325,
              "longitude": 9.632570668893964,
              "heading": 180.0
            }
          },
          "logicConstraints": {
            "driverConstraints": "drivers-license A && speaks english || speaks german",
            "clientConstraints": "wheelchair accessible",
            "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
            "jobConstraints": "!heavy",
            "carrierConstraints": "long-range tours && postcode == 12345",
            "providedValues": "drivers-license B && speaks german"
          },
          "prohibitedVehicleTypes": ["truck_and_trailer"],
          "prohibitedDeliveryTimes": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
            }      
          ],
          "conditionalTimeConstraints": [
            {
              "timeSchedule": [
                {
                  "name": "worktime",
                  "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                  "duration": "8h30m"
                }          
              ],
              "exceptions": [
                {
                  "name": "planned absence",
                  "timeSpan": {
                    "from": "2022-12-06T14:00:00+01:00",
                    "till": "2022-12-06T16:00:00+01:00"
                  }
                }          
              ],
              "assortmentConditions": ["regular-assortment", "secondary-assortment"],
              "jobActionConditions": ["pickup", "delivery"],
              "applyHardTimeConstraint": false,
              "hardTimeConstraintDuration": "1h25m"
            }      
          ],
          "enforceDepartureWithinTimeConstraints": true,
          "clientInformation": {
            "driverInfo": "beware of the dog",
            "phoneNumber": "+491234567890"
          },
          "data": {"key": "value"}
        }  
      ],
      "suppressUpdate": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "clients": [
    {
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
},
      "id": "37e2595e",
      "name": "Jane Doe",
      "serviceTime": {
        "parkingTime": "3m",
        "walkingTime": "25s",
        "additionalTrailerTime": 10m,
        "additionalTrailerHitchingTime": 5m,
        "additionalTrailerUnhitchingTime": 5m
},
      "address": {
        "street": "Hollerithallee",
        "houseNumber": "17",
        "postcode": "30419",
        "city": "Hannover",
        "country": "Germany"
},
      "location": {
        "navigationLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
},
        "serviceLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
}
},
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "prohibitedVehicleTypes": ["truck_and_trailer"],
      "prohibitedDeliveryTimes": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "conditionalTimeConstraints": [
        {
          "timeSchedule": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
}
          
          ],
          "exceptions": [
            {
              "name": "planned absence",
              "timeSpan": {
                "from": "2022-12-06T14:00:00+01:00",
                "till": "2022-12-06T16:00:00+01:00"
}
}
          
          ],
          "assortmentConditions": ["regular-assortment", "secondary-assortment"],
          "jobActionConditions": ["pickup", "delivery"],
          "applyHardTimeConstraint": false,
          "hardTimeConstraintDuration": "1h25m"
}
      
      ],
      "enforceDepartureWithinTimeConstraints": true,
      "clientInformation": {
        "driverInfo": "beware of the dog",
        "phoneNumber": "+491234567890"
},
      "data": {"key": "value"}
}
  
  ],
  "suppressUpdate": true
}

clients.delete

Deletes Clients. The Jobs which still reference a deleted Client will remain and have a temporary copy of the Client.


Request Body

DeleteClientsRequest

Request to delete a set of Clients.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of client IDs identifying the Clients that shall be deleted.


If true, all Clients in the Depot will be deleted and the clientIds property will be ignored.

DELETE /api/v1/clients.delete
curl --request DELETE 'https://courier-api.graphmasters.net/api/v1/clients.delete' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "clientIds": ["example-1", "example-2"],
      "deleteAll": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "clientIds": ["example-1", "example-2"],
  "deleteAll": true
}

clients.get

Gets specific Clients or all Clients of a Depot.


Request Body

GetClientsRequest

Request to get one or more Clients. If getAll is true, the ids field is not necessary and will be ignored. If a specific ID is requested, but does not exist, then the response will simply not contain a corresponding entity.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of client IDs identifying the Clients that shall be retrieved.


If set to true, all Clients of the Depot will be retrieved.


Response Body

GetClientsResponse

Response containing the Clients that were retrieved.


A list of Clients that were retrieved during a GetClientsRequest.

Client

A Client represents a place or client to be serviced. It could be that your business works with a fixed set of Clients that each have an ID in your system, there is however also the option to have anonymous Clients that get generated along the data import. Most importantly the Client contains an exact geographic location, maybe availabilities in terms of opening hours and other restrictions towards entities like the Vehicle or Driver.


An optional reference to another depot, this should only be used if the Client exists in another depot than the Job. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The unique ID for the Client. By default, a random ID will be generated.


The name of the Client.


The time spent at the Client, includes several different components.

ServiceTime

Describes the time spent at the Client during a Stop. Consists of various different aspects.


The time it takes to park the Vehicle once the navigation has finished. Also includes the time it takes to get back onto the street after the stop.


The time it takes to walk from parking location to delivery location and back once. On the Job we can define the number of walks needed, which will be multiplied to the single walking time.


Extra time that is added to the service time if the Vehicle has a trailer.


Extra time needed to hitch a trailer to a Vehicle. This will be added to the hitching time modelled on the Trailer.


Extra time needed to unhitch a trailer from a Vehicle. This will be added to the unhitching time modelled on the Trailer.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


The geographic location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Vehicle types that are prohibited to service this Client.

VehicleType

Lists all valid vehicle types. This type affects the travel times and distances as well as some road / client restrictions.


The Vehicle is a van < 3.5t.


The Vehicle is a truck < 40t.


The Vehicle is a truck that also has a separate trailer, all in all < 40t.


The Vehicle is a bus < 40t.


The Vehicle is a motorcycle.


The Vehicle is a bike.


The Vehicle is a cargo bike, which is slightly wider than a normal bike.


The Vehicle is a pedestrian - which is a bit odd but easier in terms of modelling.


Time windows in which the Client cannot be served. This property has priority over time constraints and is regarded as a hard constraint. Furthermore, it will enforce the departure at the client before the prohibited delivery time starts.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Time constraints on the Client, which are only applied to Jobs under a certain condition.

ConditionalTimeConstraints

Represents a time constraint that is applied to a Job only under a certain condition.


The time windows itself are generated from this TimeSchedule.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Exceptions, at which it is not valid.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


If set, only for provided assortments the time constraint is valid.


If set, only for provided job actions the time constraint is valid.


If true, time constraints resulting from this are hard.


If applyHardTimeConstraint is true, this is the duration of the hard time constraint, measured from the beginning of the time constraint.


Enforces the Tour to be planned such that the stop is finished before the 'hard till' time constraint. By default, the arrival time is what counts, but this will set the departure time against the time constraints. Default value: 'false'.


Additional, non planning-relevant, information about the Client.

ClientInformation

Information about a Client, which is not planning-relevant but may be useful for driver and dispatcher.


Free-text information for the driver, when navigating to the Client. This info-text is shown in the navigation application.


A telephone number that helps both driver and dispatcher to contact someone at the Client.


Data is a general data map with string key-values in which unstructured data can be placed.

POST /api/v1/clients.get
curl --request POST 'https://courier-api.graphmasters.net/api/v1/clients.get' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "clientIds": ["example-1", "example-2"],
      "getAll": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "clientIds": ["example-1", "example-2"],
  "getAll": true
}

RESPONSE
{
  "clients": [
    {
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
},
      "id": "37e2595e",
      "name": "Jane Doe",
      "serviceTime": {
        "parkingTime": "3m",
        "walkingTime": "25s",
        "additionalTrailerTime": 10m,
        "additionalTrailerHitchingTime": 5m,
        "additionalTrailerUnhitchingTime": 5m
},
      "address": {
        "street": "Hollerithallee",
        "houseNumber": "17",
        "postcode": "30419",
        "city": "Hannover",
        "country": "Germany"
},
      "location": {
        "navigationLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
},
        "serviceLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
}
},
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "prohibitedVehicleTypes": ["truck_and_trailer"],
      "prohibitedDeliveryTimes": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "conditionalTimeConstraints": [
        {
          "timeSchedule": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
}
          
          ],
          "exceptions": [
            {
              "name": "planned absence",
              "timeSpan": {
                "from": "2022-12-06T14:00:00+01:00",
                "till": "2022-12-06T16:00:00+01:00"
}
}
          
          ],
          "assortmentConditions": ["regular-assortment", "secondary-assortment"],
          "jobActionConditions": ["pickup", "delivery"],
          "applyHardTimeConstraint": false,
          "hardTimeConstraintDuration": "1h25m"
}
      
      ],
      "enforceDepartureWithinTimeConstraints": true,
      "clientInformation": {
        "driverInfo": "beware of the dog",
        "phoneNumber": "+491234567890"
},
      "data": {"key": "value"}
}
  
  ]
}

clients.patch

Patches selected properties of existing Clients. Optionally creates Clients that do not yet exist.


Request Body

PatchClientsRequest

Request to patch or create a set of Clients.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of patches, which will be applied to Clients.

ClientPatch

A patch for a single Client. Note that for each property that can be patched, there is a boolean indicating whether or not the property should be patched or ignored in this request.


The unique ID of the Client.


Set to true if the property name should be patched.


The name of the Client.


Set to true if the property serviceTime should be patched.


The time spent at the Client, includes several different components.

ServiceTimePatch

A patch for the ServiceTime of a Client. Note that for each property that can be patched, there is a boolean indicating whether or not the property should be patched or ignored in this request.


Set to true if the property parkingTime should be patched.


The time it takes to park the Vehicle once the navigation has finished. Also includes the time it takes to get back onto the street after the stop.


Set to true if the property walkingTime should be patched.


The time it takes to walk from parking location to delivery location and back once. On the Job we can define the number of walks needed, which will be multiplied to the single walking time.


Set to true if the property additionalTrailerTime should be patched.


Extra time that is added to the service time if the Vehicle has a trailer.


Set to true if the property additionalTrailerHitchingTime should be patched.


Extra time needed to hitch a trailer to a Vehicle. This will be added to the hitching time modelled on the Trailer.


Set to true if the property additionalTrailerUnhitchingTime should be patched.


Extra time needed to unhitch a trailer from a Vehicle. This will be added to the unhitching time modelled on the Trailer.


Set to true if the property address should be patched.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


Set to true if the property location should be patched.


The location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


Set to true if the property logicConstraints should be patched.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Set to true if the property prohibitedVehicleTypes should be patched.


Vehicles types that are prohibited to service this Client.

VehicleType

Lists all valid vehicle types. This type affects the travel times and distances as well as some road / client restrictions.


The Vehicle is a van < 3.5t.


The Vehicle is a truck < 40t.


The Vehicle is a truck that also has a separate trailer, all in all < 40t.


The Vehicle is a bus < 40t.


The Vehicle is a motorcycle.


The Vehicle is a bike.


The Vehicle is a cargo bike, which is slightly wider than a normal bike.


The Vehicle is a pedestrian - which is a bit odd but easier in terms of modelling.


Set to true if the property prohibitedDeliveryTimes should be patched.


Time windows in which the Client cannot be served. This property has priority over time constraints and is regarded as a hard constraint. Furthermore, it will enforce the departure at the client before the prohibited delivery time starts.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Set to true if the property conditionalTimeConstraints should be patched.


Time constraints on the Client, that are only applied to Jobs under a certain condition.

ConditionalTimeConstraints

Represents a time constraint that is applied to a Job only under a certain condition.


The time windows itself are generated from this TimeSchedule.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Exceptions, at which it is not valid.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


If set, only for provided assortments the time constraint is valid.


If set, only for provided job actions the time constraint is valid.


If true, time constraints resulting from this are hard.


If applyHardTimeConstraint is true, this is the duration of the hard time constraint, measured from the beginning of the time constraint.


Set to true if the property enforceDepartureWithinTimeConstraints should be patched.


Enforces the Tour to be planned such that the stop is finished before the 'hard till' time constraint. By default, the arrival time is what counts, but this will set the departure time against the time constraints. Default value: 'false'.


Set to true if the property clientInformation should be patched.


Additional, non planning-relevant, information about the Client.

ClientInformationPatch

A patch for Information about a Client, which is not planning-relevant but may be useful for driver and dispatcher, there is a boolean indicating whether or not the property should be patched or ignored in this request.


Set to true if the property driverInfo should be patched.


Free-text information for the driver, when navigating to the Client. This info-text is shown in the navigation application.


Set to true if the property phoneNumber should be patched.


A telephone number that helps both driver and dispatcher to contact someone at the Client.


Set to true if the property data should be patched.


Data is a general data map with string key-values in which unstructured data can be placed.


If true, a new Client will be created if possible. This is only the case if all required properties of the Client are there.

PATCH /api/v1/clients.patch
curl --request PATCH 'https://courier-api.graphmasters.net/api/v1/clients.patch' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "clientPatches": [
        {
          "id": "37e2595e",
          "patchName": true,
          "name": "Jane Doe",
          "patchServiceTime": true,
          "serviceTime": {
            "patchParkingTime": true,
            "parkingTime": "3m",
            "patchWalkingTime": true,
            "walkingTime": "25s",
            "patchAdditionalTrailerTime": true,
            "additionalTrailerTime": 10m,
            "patchAdditionalTrailerHitchingTime": true,
            "additionalTrailerHitchingTime": 5m,
            "patchAdditionalTrailerUnhitchingTime": true,
            "additionalTrailerUnhitchingTime": 5m
          },
          "patchAddress": true,
          "address": {
            "street": "Hollerithallee",
            "houseNumber": "17",
            "postcode": "30419",
            "city": "Hannover",
            "country": "Germany"
          },
          "patchLocation": true,
          "location": {
            "navigationLocation": {
              "latitude": 52.412861820839325,
              "longitude": 9.632570668893964,
              "heading": 180.0
            },
            "serviceLocation": {
              "latitude": 52.412861820839325,
              "longitude": 9.632570668893964,
              "heading": 180.0
            }
          },
          "patchLogicConstraints": true,
          "logicConstraints": {
            "driverConstraints": "drivers-license A && speaks english || speaks german",
            "clientConstraints": "wheelchair accessible",
            "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
            "jobConstraints": "!heavy",
            "carrierConstraints": "long-range tours && postcode == 12345",
            "providedValues": "drivers-license B && speaks german"
          },
          "patchProhibitedVehicleTypes": true,
          "prohibitedVehicleTypes": ["truck_and_trailer"],
          "patchProhibitedDeliveryTimes": true,
          "prohibitedDeliveryTimes": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
            }      
          ],
          "patchConditionalTimeConstraints": true,
          "conditionalTimeConstraints": [
            {
              "timeSchedule": [
                {
                  "name": "worktime",
                  "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                  "duration": "8h30m"
                }          
              ],
              "exceptions": [
                {
                  "name": "planned absence",
                  "timeSpan": {
                    "from": "2022-12-06T14:00:00+01:00",
                    "till": "2022-12-06T16:00:00+01:00"
                  }
                }          
              ],
              "assortmentConditions": ["regular-assortment", "secondary-assortment"],
              "jobActionConditions": ["pickup", "delivery"],
              "applyHardTimeConstraint": false,
              "hardTimeConstraintDuration": "1h25m"
            }      
          ],
          "patchEnforceDepartureWithinTimeConstraints": true,
          "enforceDepartureWithinTimeConstraints": true,
          "patchClientInformation": true,
          "clientInformation": {
            "patchDriverInfo": true,
            "driverInfo": "beware of the dog",
            "patchPhoneNumber": true,
            "phoneNumber": "+491234567890"
          },
          "patchData": true,
          "data": {"key": "value"}
        }  
      ],
      "tryCreateClientIfNotExists": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "clientPatches": [
    {
      "id": "37e2595e",
      "patchName": true,
      "name": "Jane Doe",
      "patchServiceTime": true,
      "serviceTime": {
        "patchParkingTime": true,
        "parkingTime": "3m",
        "patchWalkingTime": true,
        "walkingTime": "25s",
        "patchAdditionalTrailerTime": true,
        "additionalTrailerTime": 10m,
        "patchAdditionalTrailerHitchingTime": true,
        "additionalTrailerHitchingTime": 5m,
        "patchAdditionalTrailerUnhitchingTime": true,
        "additionalTrailerUnhitchingTime": 5m
},
      "patchAddress": true,
      "address": {
        "street": "Hollerithallee",
        "houseNumber": "17",
        "postcode": "30419",
        "city": "Hannover",
        "country": "Germany"
},
      "patchLocation": true,
      "location": {
        "navigationLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
},
        "serviceLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
}
},
      "patchLogicConstraints": true,
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "patchProhibitedVehicleTypes": true,
      "prohibitedVehicleTypes": ["truck_and_trailer"],
      "patchProhibitedDeliveryTimes": true,
      "prohibitedDeliveryTimes": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "patchConditionalTimeConstraints": true,
      "conditionalTimeConstraints": [
        {
          "timeSchedule": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
}
          
          ],
          "exceptions": [
            {
              "name": "planned absence",
              "timeSpan": {
                "from": "2022-12-06T14:00:00+01:00",
                "till": "2022-12-06T16:00:00+01:00"
}
}
          
          ],
          "assortmentConditions": ["regular-assortment", "secondary-assortment"],
          "jobActionConditions": ["pickup", "delivery"],
          "applyHardTimeConstraint": false,
          "hardTimeConstraintDuration": "1h25m"
}
      
      ],
      "patchEnforceDepartureWithinTimeConstraints": true,
      "enforceDepartureWithinTimeConstraints": true,
      "patchClientInformation": true,
      "clientInformation": {
        "patchDriverInfo": true,
        "driverInfo": "beware of the dog",
        "patchPhoneNumber": true,
        "phoneNumber": "+491234567890"
},
      "patchData": true,
      "data": {"key": "value"}
}
  
  ],
  "tryCreateClientIfNotExists": true
}

Depots

The Depots category allows the user to perform basic CRUD operations on Depots.

A Depot is a logical grouping of all other basic entities. Only the deletion of a Depot cannot be done from the API, because it is considered a too invasive call.

depots.get

This endpoint allows you to get one or more existing Depots. There is also an option to get all Depots.


Request Body

GetDepotsRequest

Request to get one or more Depots.


The references to the depots, which are set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


If set to true, all Depots will be retrieved.


Response Body

GetDepotsResponse

Response containing an array of Depots that were retrieved.


An array of Depots that were retrieved during a GetDepotsRequest.

Depot

Represents a Depot.


A unique ID for the Depot. By default, a random ID will be generated.


The reference ID for the Depot. Must be unique among all the Depots of the customer.


The name of the Depot.


The timezone of the Depot.


The description of Shift start points. Each recurrence in the given time schedule marks the start of a new Shift. By default, a daily recurrence with the start at midnight will be used.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Data is a general data map with string key-values in which unstructured data can be placed.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


The geographic location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.

POST /api/v1/depots.get
curl --request POST 'https://courier-api.graphmasters.net/api/v1/depots.get' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReferences": [
        {
          "referenceId": "depot-berlin-1",
          "referenceType": "depot-id"
        }  
      ],
      "getAll": true
}'

REQUEST
{
  "depotReferences": [
    {
      "referenceId": "depot-berlin-1",
      "referenceType": "depot-id"
}
  
  ],
  "getAll": true
}

RESPONSE
{
  "depots": [
    {
      "id": "37e2595e",
      "apiReferenceId": "depot-berlin-1",
      "name": "Depot Berlin",
      "timezone": "Europe/Berlin",
      "shiftSchedule": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "data": {"key": "value"},
      "address": {
        "street": "Hollerithallee",
        "houseNumber": "17",
        "postcode": "30419",
        "city": "Hannover",
        "country": "Germany"
},
      "location": {
        "navigationLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
},
        "serviceLocation": {
          "latitude": 52.412861820839325,
          "longitude": 9.632570668893964,
          "heading": 180.0
}
}
}
  
  ]
}

Drivers

The Drivers category allows the user to perform basic CRUD operations on Drivers.



A Driver represents a person actually driving a Vehicle on a Tour. The main properties of a Driver are around the topic of availability and working times, as well as breaks and periods of unavailability. There are also logic constraints towards other entities, such as Vehicles.

Endpoints in this category contain the creation, deletion and retrieval of Drivers.

drivers.create

Creates or updates Drivers. Any Driver that already exists will be overwritten completely, any new Driver will be created.


Request Body

CreateDriversRequest

Request to create or update a set of Drivers.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of Drivers which should be created or updated.

Driver

A Driver represents a person actually driving a Vehicle on a Tour. The main properties of a Driver are around the topic of availability and working times, as well as breaks and periods of unavailability. There are also logic constraints towards other entities, such as Vehicles.


A unique ID for the Driver. By default, a random ID will be generated.


Optional Carrier ID. By default, the Driver does not belong to any Carrier.


The name of the Driver. This value does not need to be unique. The name is helpful to identify the Driver and can be used to obtain a Tour via the NUNAV Courier app.


The availability of the Driver, which can be used to model times at which the Driver is available for Tours.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


The times of unavailability of the Driver, e.g. the Driver is having a vacation.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


The latest time at which a tour must start. Needs to be aligned with the availability of the Driver.


Basic configuration for the work time of the Driver. If the advanced worktime configuration is set, this property will be ignored.

BasicWorktimeConfiguration

Basic configuration for the work time of a Driver.


The maximum work time for a single Shift.


The maximum overtime on top of the maximum work time.


Advanced configuration for the work time of the Driver. If the basic worktime configuration is set, it will be ignored and this property takes priority.

AdvancedWorktimeConfiguration

Advanced configuration for the work time of a Driver.


Describes a period of work time over which certain rules apply, e.g. the work start funnel. The default will be a week starting on Monday (midnight) and ending on Monday (midnight) again.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


The maximum work time (including overtime) for an entire work period.


The target work time for an entire work period.


The maximum work time (including overtime) for a single Shift.


The target work time for a single Shift.


The minimum break a Driver has to take between two work shifts.


A time funnel around the start time, which ensures that the Driver only has starting times within +- this funnel for a work period.


The drivers desire for or against overtime.

OvertimeDesire

Lists different desires for Driver overtime.


The Driver desires to work less than the target work time.


The Driver desires to accumulate overtime.


The Driver desires to be even with overtime.


The breaks that the Driver is obliged to take during a Tour, by default there are no breaks. Breaks are taken in the order they are present in this array.

WorkBreak

Represents a rule for a work break during a Tour.


Optional ID of the break. By default, a random ID will be generated.


The Duration of the break, when it is taken.


If the Tour reaches this driving time, then the break has to be taken at the latest. It can be taken earlier though. A Tour just can't have any driving period longer than this.


If the Tour reaches this working time, then the break has to be taken at the latest. It can be taken earlier though. A Tour just can't have any working period longer than this. Working time is driving time plus service time.


This is the minimum time into the Tour at which a break shall be taken. It has to be in line with the other parameters and not contradicting them.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Whether the Driver can preload the next Tour driven on the same Vehicle. Setting this to true only makes sense if the Vehicles can be preloaded and have a multi driver config.


Whitelist or blacklist, restricting which Vehicles are allowed to be combined with the Driver.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


Data is a general data map with string key-values in which unstructured data can be placed.


If set to true, the Drivers will only be created, but existing Drivers will not be updated.

POST /api/v1/drivers.create
curl --request POST 'https://courier-api.graphmasters.net/api/v1/drivers.create' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "drivers": [
        {
          "id": "56f04550",
          "carrierId": "33fcefcd",
          "name": "Sebastian Vettel",
          "availability": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
            }      
          ],
          "unavailabilities": [
            {
              "name": "planned absence",
              "timeSpan": {
                "from": "2022-12-06T14:00:00+01:00",
                "till": "2022-12-06T16:00:00+01:00"
              }
            }      
          ],
          "latestTourStart": ["DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0"],
          "basicWorktimeConfiguration": {
            "maxWorktimePerShift": "8h45m",
            "maxOvertimePerShift": "1h15m"
          },
          "advancedWorktimeConfiguration": {
            "workPeriod": [
              {
                "name": "worktime",
                "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                "duration": "8h30m"
              }        
            ],
            "maxWorktimeForWorkPeriod": "45h",
            "targetWorktimeForWorkPeriod": "40h",
            "maxWorktimeForShift": "9h45m",
            "targetWorktimeForShift": "8h",
            "minShiftBreak": "11h",
            "workStartFunnelSize": "3h",
            "overtimeDesire": "negative_overtime"
          },
          "breaks": [
            {
              "id": "35a89133",
              "duration": "45m",
              "drivingTimeLimit": "4h30m",
              "totalTimeLimit": "6h",
              "minimumTotalTime": "1h30m"
            }      
          ],
          "logicConstraints": {
            "driverConstraints": "drivers-license A && speaks english || speaks german",
            "clientConstraints": "wheelchair accessible",
            "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
            "jobConstraints": "!heavy",
            "carrierConstraints": "long-range tours && postcode == 12345",
            "providedValues": "drivers-license B && speaks german"
          },
          "canPreloadNextTour": true,
          "restrictedVehicles": {
            "allowed": true,
            "ids": ["33fcefcd", "198aa52d"]
          },
          "data": {"key": "value"}
        }  
      ],
      "suppressUpdate": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "drivers": [
    {
      "id": "56f04550",
      "carrierId": "33fcefcd",
      "name": "Sebastian Vettel",
      "availability": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "unavailabilities": [
        {
          "name": "planned absence",
          "timeSpan": {
            "from": "2022-12-06T14:00:00+01:00",
            "till": "2022-12-06T16:00:00+01:00"
}
}
      
      ],
      "latestTourStart": ["DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0"],
      "basicWorktimeConfiguration": {
        "maxWorktimePerShift": "8h45m",
        "maxOvertimePerShift": "1h15m"
},
      "advancedWorktimeConfiguration": {
        "workPeriod": [
          {
            "name": "worktime",
            "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
            "duration": "8h30m"
}
        
        ],
        "maxWorktimeForWorkPeriod": "45h",
        "targetWorktimeForWorkPeriod": "40h",
        "maxWorktimeForShift": "9h45m",
        "targetWorktimeForShift": "8h",
        "minShiftBreak": "11h",
        "workStartFunnelSize": "3h",
        "overtimeDesire": "negative_overtime"
},
      "breaks": [
        {
          "id": "35a89133",
          "duration": "45m",
          "drivingTimeLimit": "4h30m",
          "totalTimeLimit": "6h",
          "minimumTotalTime": "1h30m"
}
      
      ],
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "canPreloadNextTour": true,
      "restrictedVehicles": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "data": {"key": "value"}
}
  
  ],
  "suppressUpdate": true
}

drivers.delete

Deletes Drivers. The Tours which still reference a deleted Driver will also be deleted.


Request Body

DeleteDriversRequest

Request to delete a set of Drivers.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of driver IDs identifying the Drivers that shall be deleted.


If true, all Drivers in the Depot will be deleted and the driverIds property will be ignored.


If true, also deletes the Jobs which are on Tours that get deleted along the deletion of the Drivers. If false, those Jobs will get unassigned. Default: false.

DELETE /api/v1/drivers.delete
curl --request DELETE 'https://courier-api.graphmasters.net/api/v1/drivers.delete' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "driverIds": ["example-1", "example-2"],
      "deleteAll": true,
      "deleteJobsOnTours": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "driverIds": ["example-1", "example-2"],
  "deleteAll": true,
  "deleteJobsOnTours": true
}

drivers.get

Gets specific Drivers or all Drivers of a Depot.


Request Body

GetDriversRequest

Request to get one or more Drivers. If getAll is true,
the driverIds field is not necessary and will be ignored. If a specific ID is requested, but does
not exist, then the response will simply not contain a corresponding entity.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of driver IDs identifying the Drivers that shall be retrieved.


If set to true, all Drivers of the Depot will be retrieved.


Response Body

GetDriversResponse

Response containing Drivers that were retrieved.


A list of Drivers that were retrieved during a GetDriversRequest.

Driver

A Driver represents a person actually driving a Vehicle on a Tour. The main properties of a Driver are around the topic of availability and working times, as well as breaks and periods of unavailability. There are also logic constraints towards other entities, such as Vehicles.


A unique ID for the Driver. By default, a random ID will be generated.


Optional Carrier ID. By default, the Driver does not belong to any Carrier.


The name of the Driver. This value does not need to be unique. The name is helpful to identify the Driver and can be used to obtain a Tour via the NUNAV Courier app.


The availability of the Driver, which can be used to model times at which the Driver is available for Tours.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


The times of unavailability of the Driver, e.g. the Driver is having a vacation.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


The latest time at which a tour must start. Needs to be aligned with the availability of the Driver.


Basic configuration for the work time of the Driver. If the advanced worktime configuration is set, this property will be ignored.

BasicWorktimeConfiguration

Basic configuration for the work time of a Driver.


The maximum work time for a single Shift.


The maximum overtime on top of the maximum work time.


Advanced configuration for the work time of the Driver. If the basic worktime configuration is set, it will be ignored and this property takes priority.

AdvancedWorktimeConfiguration

Advanced configuration for the work time of a Driver.


Describes a period of work time over which certain rules apply, e.g. the work start funnel. The default will be a week starting on Monday (midnight) and ending on Monday (midnight) again.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


The maximum work time (including overtime) for an entire work period.


The target work time for an entire work period.


The maximum work time (including overtime) for a single Shift.


The target work time for a single Shift.


The minimum break a Driver has to take between two work shifts.


A time funnel around the start time, which ensures that the Driver only has starting times within +- this funnel for a work period.


The drivers desire for or against overtime.

OvertimeDesire

Lists different desires for Driver overtime.


The Driver desires to work less than the target work time.


The Driver desires to accumulate overtime.


The Driver desires to be even with overtime.


The breaks that the Driver is obliged to take during a Tour, by default there are no breaks. Breaks are taken in the order they are present in this array.

WorkBreak

Represents a rule for a work break during a Tour.


Optional ID of the break. By default, a random ID will be generated.


The Duration of the break, when it is taken.


If the Tour reaches this driving time, then the break has to be taken at the latest. It can be taken earlier though. A Tour just can't have any driving period longer than this.


If the Tour reaches this working time, then the break has to be taken at the latest. It can be taken earlier though. A Tour just can't have any working period longer than this. Working time is driving time plus service time.


This is the minimum time into the Tour at which a break shall be taken. It has to be in line with the other parameters and not contradicting them.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Whether the Driver can preload the next Tour driven on the same Vehicle. Setting this to true only makes sense if the Vehicles can be preloaded and have a multi driver config.


Whitelist or blacklist, restricting which Vehicles are allowed to be combined with the Driver.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


Data is a general data map with string key-values in which unstructured data can be placed.

POST /api/v1/drivers.get
curl --request POST 'https://courier-api.graphmasters.net/api/v1/drivers.get' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "driverIds": ["example-1", "example-2"],
      "getAll": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "driverIds": ["example-1", "example-2"],
  "getAll": true
}

RESPONSE
{
  "drivers": [
    {
      "id": "56f04550",
      "carrierId": "33fcefcd",
      "name": "Sebastian Vettel",
      "availability": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "unavailabilities": [
        {
          "name": "planned absence",
          "timeSpan": {
            "from": "2022-12-06T14:00:00+01:00",
            "till": "2022-12-06T16:00:00+01:00"
}
}
      
      ],
      "latestTourStart": ["DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0"],
      "basicWorktimeConfiguration": {
        "maxWorktimePerShift": "8h45m",
        "maxOvertimePerShift": "1h15m"
},
      "advancedWorktimeConfiguration": {
        "workPeriod": [
          {
            "name": "worktime",
            "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
            "duration": "8h30m"
}
        
        ],
        "maxWorktimeForWorkPeriod": "45h",
        "targetWorktimeForWorkPeriod": "40h",
        "maxWorktimeForShift": "9h45m",
        "targetWorktimeForShift": "8h",
        "minShiftBreak": "11h",
        "workStartFunnelSize": "3h",
        "overtimeDesire": "negative_overtime"
},
      "breaks": [
        {
          "id": "35a89133",
          "duration": "45m",
          "drivingTimeLimit": "4h30m",
          "totalTimeLimit": "6h",
          "minimumTotalTime": "1h30m"
}
      
      ],
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "canPreloadNextTour": true,
      "restrictedVehicles": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "data": {"key": "value"}
}
  
  ]
}

drivers.patch

Patches selected properties of existing Drivers. Optionally creates Drivers that do not yet exist.


Request Body

PatchDriversRequest

Request to patch or create a set of Drivers.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of patches, which will be applied to Drivers.

DriverPatch

A patch for a single Driver. Note that for each property that can be patched, there is a boolean indicating whether or not the property should be patched or ignored in this request.


The unique ID of the Client.


Set to true if the property carrierId should be patched.


Carrier ID. By default, the Driver does not belong to any Carrier.


Set to true if the property name should be patched.


The name of the Driver. This value does not need to be unique. The name is helpful to identify the Driver and can be used to obtain a Tour via the NUNAV Courier app.


Set to true if the property availability should be patched.


The availability of the Driver, which can be used to model times at which the Driver is available for Tours.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Set to true if the property unavailabilities should be patched.


The times of unavailability of the Driver, e.g. the Driver is having a vacation.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


Set to true if the property latestTourStart should be patched.


The latest time at which a tour must start. Needs to be aligned with the availability of the Driver.


Set to true if the property basicWorktimeConfiguration should be patched.


Basic configuration for the work time of the Driver. If the advanced worktime configuration is set, this property will be ignored.

BasicWorktimeConfiguration

Basic configuration for the work time of a Driver.


The maximum work time for a single Shift.


The maximum overtime on top of the maximum work time.


Set to true if the property advancedWorktimeConfiguration should be patched.


Advanced configuration for the work time of the Driver. If the basic worktime configuration is set, it will be ignored and this property takes priority.

AdvancedWorktimeConfiguration

Advanced configuration for the work time of a Driver.


Describes a period of work time over which certain rules apply, e.g. the work start funnel. The default will be a week starting on Monday (midnight) and ending on Monday (midnight) again.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


The maximum work time (including overtime) for an entire work period.


The target work time for an entire work period.


The maximum work time (including overtime) for a single Shift.


The target work time for a single Shift.


The minimum break a Driver has to take between two work shifts.


A time funnel around the start time, which ensures that the Driver only has starting times within +- this funnel for a work period.


The drivers desire for or against overtime.

OvertimeDesire

Lists different desires for Driver overtime.


The Driver desires to work less than the target work time.


The Driver desires to accumulate overtime.


The Driver desires to be even with overtime.


Set to true if the property breaks should be patched.


The breaks that the Driver is obliged to take during a Tour, by default there are no breaks. Breaks are taken in the order they are present in this array.

WorkBreak

Represents a rule for a work break during a Tour.


Optional ID of the break. By default, a random ID will be generated.


The Duration of the break, when it is taken.


If the Tour reaches this driving time, then the break has to be taken at the latest. It can be taken earlier though. A Tour just can't have any driving period longer than this.


If the Tour reaches this working time, then the break has to be taken at the latest. It can be taken earlier though. A Tour just can't have any working period longer than this. Working time is driving time plus service time.


This is the minimum time into the Tour at which a break shall be taken. It has to be in line with the other parameters and not contradicting them.


Set to true if the property logicConstraints should be patched.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Set to true if the property canPreloadNextTour should be patched.


Whether the Driver can preload the next Tour driven on the same Vehicle. Setting this to true only makes sense if the Vehicles can be preloaded and have a multi driver config.


Set to true if the property restrictedVehicles should be patched.


Whitelist or blacklist, restricting which Vehicles are allowed to be combined with the Driver.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


Set to true if the property data should be patched.


Data is a general data map with string key-values in which unstructured data can be placed.


If true, a new Driver will be created if possible. This is only the case if all required properties of the Driver are there.

PATCH /api/v1/drivers.patch
curl --request PATCH 'https://courier-api.graphmasters.net/api/v1/drivers.patch' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "driverPatches": [
        {
          "id": "56f04550",
          "patchCarrierId": true,
          "carrierId": "33fcefcd",
          "patchName": true,
          "name": "Sebastian Vettel",
          "patchAvailability": true,
          "availability": [
            {
              "name": "worktime",
              "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
              "duration": "8h30m"
            }      
          ],
          "patchUnavailabilities": true,
          "unavailabilities": [
            {
              "name": "planned absence",
              "timeSpan": {
                "from": "2022-12-06T14:00:00+01:00",
                "till": "2022-12-06T16:00:00+01:00"
              }
            }      
          ],
          "patchLatestTourStart": true,
          "latestTourStart": ["DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0"],
          "patchBasicWorktimeConfiguration": true,
          "basicWorktimeConfiguration": {
            "maxWorktimePerShift": "8h45m",
            "maxOvertimePerShift": "1h15m"
          },
          "patchAdvancedWorktimeConfiguration": true,
          "advancedWorktimeConfiguration": {
            "workPeriod": [
              {
                "name": "worktime",
                "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                "duration": "8h30m"
              }        
            ],
            "maxWorktimeForWorkPeriod": "45h",
            "targetWorktimeForWorkPeriod": "40h",
            "maxWorktimeForShift": "9h45m",
            "targetWorktimeForShift": "8h",
            "minShiftBreak": "11h",
            "workStartFunnelSize": "3h",
            "overtimeDesire": "negative_overtime"
          },
          "patchBreaks": true,
          "breaks": [
            {
              "id": "35a89133",
              "duration": "45m",
              "drivingTimeLimit": "4h30m",
              "totalTimeLimit": "6h",
              "minimumTotalTime": "1h30m"
            }      
          ],
          "patchLogicConstraints": true,
          "logicConstraints": {
            "driverConstraints": "drivers-license A && speaks english || speaks german",
            "clientConstraints": "wheelchair accessible",
            "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
            "jobConstraints": "!heavy",
            "carrierConstraints": "long-range tours && postcode == 12345",
            "providedValues": "drivers-license B && speaks german"
          },
          "patchCanPreloadNextTour": true,
          "canPreloadNextTour": true,
          "patchRestrictedVehicles": true,
          "restrictedVehicles": {
            "allowed": true,
            "ids": ["33fcefcd", "198aa52d"]
          },
          "patchData": true,
          "data": {"key": "value"}
        }  
      ],
      "tryCreateDriverIfNotExists": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "driverPatches": [
    {
      "id": "56f04550",
      "patchCarrierId": true,
      "carrierId": "33fcefcd",
      "patchName": true,
      "name": "Sebastian Vettel",
      "patchAvailability": true,
      "availability": [
        {
          "name": "worktime",
          "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
          "duration": "8h30m"
}
      
      ],
      "patchUnavailabilities": true,
      "unavailabilities": [
        {
          "name": "planned absence",
          "timeSpan": {
            "from": "2022-12-06T14:00:00+01:00",
            "till": "2022-12-06T16:00:00+01:00"
}
}
      
      ],
      "patchLatestTourStart": true,
      "latestTourStart": ["DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0"],
      "patchBasicWorktimeConfiguration": true,
      "basicWorktimeConfiguration": {
        "maxWorktimePerShift": "8h45m",
        "maxOvertimePerShift": "1h15m"
},
      "patchAdvancedWorktimeConfiguration": true,
      "advancedWorktimeConfiguration": {
        "workPeriod": [
          {
            "name": "worktime",
            "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
            "duration": "8h30m"
}
        
        ],
        "maxWorktimeForWorkPeriod": "45h",
        "targetWorktimeForWorkPeriod": "40h",
        "maxWorktimeForShift": "9h45m",
        "targetWorktimeForShift": "8h",
        "minShiftBreak": "11h",
        "workStartFunnelSize": "3h",
        "overtimeDesire": "negative_overtime"
},
      "patchBreaks": true,
      "breaks": [
        {
          "id": "35a89133",
          "duration": "45m",
          "drivingTimeLimit": "4h30m",
          "totalTimeLimit": "6h",
          "minimumTotalTime": "1h30m"
}
      
      ],
      "patchLogicConstraints": true,
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "patchCanPreloadNextTour": true,
      "canPreloadNextTour": true,
      "patchRestrictedVehicles": true,
      "restrictedVehicles": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "patchData": true,
      "data": {"key": "value"}
}
  
  ],
  "tryCreateDriverIfNotExists": true
}

Job Tracking

Job Tracking allows users to get detailed information about when a Job will be performed during a Tour. Basically it tries to answer the question: 'when will I get my delivery?'.

jobtracking.track

Gathers detailed information about when a Job will be performed during a Tour. Basically tries to answer the question: 'when will I get my delivery?'.


Request Body

JobTrackingRequest

Request for tracking one or more Jobs through their trackingId.


The trackingIds for which to get tracking information.


Response Body

JobTrackingResponse

Response for a JobTrackingRequest. Contains information about the Jobs, which have been specified by their trackingId in the request.


A list of tracking information, which contain the results.

TrackingInformation

Information regarding the tracking of a single Job.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The Tracking ID of the Job.


The ID of the Job.


The current status of the job, only if the Job is assigned to a Tour.

JobStatus

Lists different states of the Job on a Tour.


The job has yet to be done, it will be planned into the Tour.


The job is suspended and will not be planned into the tour order.


The job has been finished.


Whether the Job is assigned to a Tour.


If assigned to a tour, the ID of the Tour.


If open and assigned to a tour, the ETA of the Job.


If done and assigned to a tour, the ATA of the Job.


If open and assigned to a tour, the number of stops before the arrival at the Job.


If open and assigned to a tour, the number of Jobs before the arrival at the Job.

POST /api/v1/jobtracking.track
curl --request POST 'https://courier-api.graphmasters.net/api/v1/jobtracking.track' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "trackingIds": ["3a05c4deab57", "612bced0a20e"]
}'

REQUEST
{
  "trackingIds": ["3a05c4deab57", "612bced0a20e"]
}

RESPONSE
{
  "trackingInformation": [
    {
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
},
      "trackingId": "160034738372627959",
      "jobId": "294da491",
      "jobStatus": "open",
      "assignedToTour": true,
      "tourId": "400a38ca",
      "estimatedArrivalTime": "2022-12-06T13:20:00+01:00",
      "actualArrivalTime": "2022-12-06T13:21:12+01:00",
      "stopsBeforeArrival": 5,
      "jobsBeforeArrival": 10
}
  
  ]
}

Jobs

The Jobs category allows the user to perform basic CRUD operations on Jobs as well as functions about the Job status and assignment.



A Job represents the order to deliver or pickup a Shipment at a Client. Jobs exist in a specific Shift and contain information such as the number of items to be delivered, their weight or time constraints.

Endpoints in this category are used to create, update, delete and get Jobs. There are also endpoints to change the Job status and to assign Jobs to Tours manually.

jobs.create

Creates or updates Jobs. Any Job that already exists will be overwritten completely, any new Job will be created.


Request Body

CreateJobsRequest

Request to create or update a set of Jobs.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of Jobs which should be created or updated.

Job

A Job represents the order to deliver or pickup a Shipment at a Client. Jobs exist in a specific Shift and contain information such as the number of items to be delivered, their weight or time constraints.


A unique ID for the Job. By default, a random ID will be generated.


The shift in which to import the Job. See Shifts


The type of job, by default "delivery".

JobAction

Lists types of actions that can be fulfilled with a specific Job.


The Shipment is picked up at the beginning and delivered at the Client.


The Shipment will be picked up at the Client and delivered at the end.


Physical properties of the Shipment which is being moved for this Job.

Shipment

A Shipment contains physical properties of the transported item.


A unique ID for the Shipment. By default, a random ID will be generated.


The barcode of the Shipment. By default, there is no barcode and the Shipment cannot be scanned.


The physical dimensions of the Shipment. Also contains information about the stackability of the Shipment.

CapacityDimensions

Represents the physical dimensions of a Shipment. There are three default dimensions (weight, volume and count),
but it is also possible to add an arbitrary number of custom dimensions.


The weight of the Shipment (in kg).


The volume of the Shipment (in m³).


the number of items the Shipment consists of.


arbitrary additional dimensions that can be defined. The key is the name of the dimension, the value is the value for this dimension.


Whether this Shipment can carry other Shipments above it. This is only needed when using the feature Shipment Stackability. See capacities on the Vehicle.


Whether this Shipment can go on top of other Shipments. This is only needed when using the feature Shipment Stackability. See capacities on the Vehicle.


The Recipient of the shipment.


The Sender of the shipment.


The label of the address (free text).


A freetext field to denote the assortment of the Shipment.


Fine-granular durations for handling the Shipment in various cases.

HandlingDurations

Fine-granular durations for handling the Shipment in various cases.


The duration of loading the Shipment onto the Vehicle at the beginning of the Tour.


The duration of unloading the Shipment from the Vehicle at the end of the Tour.


The duration of loading the Shipment onto the Vehicle when performing a reloading stop on the Tour.


The duration of transferring the Shipment from trailer to front machine when performing a shipment transfer on the Tour.


Data is a general data map with string key-values in which unstructured data can be placed.


The pieces of the Shipment. One Shipment can optionally consist of many single transported items.

ShipmentPiece

A ShipmentPiece contains physical properties of a single transported item of the Shipment.


The ID of the piece.


The barcode identifying the piece.


Data is a general data map with string key-values in which unstructured data can be placed.


The Client to whom the Job is addressed to.

Client

A Client represents a place or client to be serviced. It could be that your business works with a fixed set of Clients that each have an ID in your system, there is however also the option to have anonymous Clients that get generated along the data import. Most importantly the Client contains an exact geographic location, maybe availabilities in terms of opening hours and other restrictions towards entities like the Vehicle or Driver.


An optional reference to another depot, this should only be used if the Client exists in another depot than the Job. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The unique ID for the Client. By default, a random ID will be generated.


The name of the Client.


The time spent at the Client, includes several different components.

ServiceTime

Describes the time spent at the Client during a Stop. Consists of various different aspects.


The time it takes to park the Vehicle once the navigation has finished. Also includes the time it takes to get back onto the street after the stop.


The time it takes to walk from parking location to delivery location and back once. On the Job we can define the number of walks needed, which will be multiplied to the single walking time.


Extra time that is added to the service time if the Vehicle has a trailer.


Extra time needed to hitch a trailer to a Vehicle. This will be added to the hitching time modelled on the Trailer.


Extra time needed to unhitch a trailer from a Vehicle. This will be added to the unhitching time modelled on the Trailer.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


The geographic location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Vehicle types that are prohibited to service this Client.

VehicleType

Lists all valid vehicle types. This type affects the travel times and distances as well as some road / client restrictions.


The Vehicle is a van < 3.5t.


The Vehicle is a truck < 40t.


The Vehicle is a truck that also has a separate trailer, all in all < 40t.


The Vehicle is a bus < 40t.


The Vehicle is a motorcycle.


The Vehicle is a bike.


The Vehicle is a cargo bike, which is slightly wider than a normal bike.


The Vehicle is a pedestrian - which is a bit odd but easier in terms of modelling.


Time windows in which the Client cannot be served. This property has priority over time constraints and is regarded as a hard constraint. Furthermore, it will enforce the departure at the client before the prohibited delivery time starts.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Time constraints on the Client, which are only applied to Jobs under a certain condition.

ConditionalTimeConstraints

Represents a time constraint that is applied to a Job only under a certain condition.


The time windows itself are generated from this TimeSchedule.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Exceptions, at which it is not valid.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


If set, only for provided assortments the time constraint is valid.


If set, only for provided job actions the time constraint is valid.


If true, time constraints resulting from this are hard.


If applyHardTimeConstraint is true, this is the duration of the hard time constraint, measured from the beginning of the time constraint.


Enforces the Tour to be planned such that the stop is finished before the 'hard till' time constraint. By default, the arrival time is what counts, but this will set the departure time against the time constraints. Default value: 'false'.


Additional, non planning-relevant, information about the Client.

ClientInformation

Information about a Client, which is not planning-relevant but may be useful for driver and dispatcher.


Free-text information for the driver, when navigating to the Client. This info-text is shown in the navigation application.


A telephone number that helps both driver and dispatcher to contact someone at the Client.


Data is a general data map with string key-values in which unstructured data can be placed.


The tracking ID of the Job. Should (but does not have to) be unique. E.g. two corresponding jobs (pickup-delivery) could have the same tracking id. By default, tracking for this Job is deactivated.


The expected time it takes to fulfill the Job. This does not include maneuver time for the vehicle to park or find a parking location, it also does not include walking time to and from the vehicle. That would be modelled on the client. By default, this is 0.


It is possible to add multiple time constraints for the fulfillment of this Job. These time constraints can be configured independently, the optimisation chooses the one making most sense. By default, the Job has no time constraints and can be fulfilled anytime, unless restricted by the Driver, Vehicle or Client.

TimeConstraint

A constraint for an Optimisation, which describes that a Job has to be started between the values of
'from' and 'till'. If 'hardFrom' and 'hardTill' are not set, performing the Job outside the time window is possible whilst incurring a penalty.


Soft opening of the window: this is the time at which the fulfillment of the Job ideally starts.


Soft closing of the window: this is the time at which the fulfillment of the Job ideally ends.


Hard opening of the window: this is the absolute minimum time at which the fulfillment of the Job starts.


Hard closing of the window: this is the absolute maximum time at which the fulfillment of the Job ends.


Priority of the time window. By default, the priority is 1.0. It can overwrite the penalty for not making the time window. It must be greater than 0.0.


Detailed reason for the constraint, e.g. "express delivery". This property is optional and only for showing the context of the time constraint to the user.


Pressure function applied to penalties. An advanced feature for pressuring the fulfillment towards a direction within the time window.

AppointmentPressure

Enumerates different pressure functions for time constraints.
A pressure function encourages the optimisation algorithm to prefer a
certain direction for the fulfillment of a Job.
For example towards the beginning of the time constraint.


Gaussian distribution curve that minimises the penalty at the center of the time constraint. See graph plot.
xy0.511.52-0.5-1-1.5-20.511.52-0.5-1-1.5-2


Sigmoid function that minimises the penalty at the beginning of the time constraint. See graph plot.
xy0.511.52-0.5-1-1.5-20.511.52-0.5-1-1.5-2


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


A blacklist or whitelist of specific Drivers that are allowed to perform the Job. By default, any driver can perform any Job.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


A blacklist or whitelist of specific Drivers that are allowed to perform the Job. By default, any vehicle can perform any Job.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


An array of job-ids that must be done before this Job. Warning: Greatly increases complexity for optimisations. The Jobs need to be on the same Tour. By default, the order is free.


An array of job-ids that must be done after this Job. Warning: Greatly increases complexity for optimisations. The Jobs need to be on the same Tour. By default, the order is free.


A very advanced feature to describe which Jobs must or must not be grouped together on a Tour. An example would be the delivery of food and poison, which cannot be done on the same Tour. Warning: Greatly increases complexity for optimisations.

JobGroup

Identifies a group of Jobs which can get rules applied
via a GroupRule. Optionally the group can have time ranges in which it forms.


Unique ID of the group you have to provide.


Optional TimeSpans in which the group applies.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


A very advanced feature to describe which Jobs must or must not be grouped together on a Tour. An example would be the delivery of food and poison, which cannot be done on the same Tour. Warning: Greatly increases complexity for optimisations.

GroupRule

A rule that applies to one or more groups of Jobs.


The ids of the groups to which this rule applies.


Represents the condition that all groups subject to this rule must fulfill.

GroupCondition

Lists all valid conditions for group rules.
Warning: the group rule logic is unfortunately quite complex to understand and makes the computational complexity for the optimisation rather high.


The condition that all jobs belonging to one of the listed groups should all be done one after each other or all be unassigned.

Example:
Consider two groups, food and drinks. All jobs in both groups should arrive at the same time in the same shop. Using this strong condition, both the jobs inside the groups will be done after each other and not split but also the groups itself so that everything arrives together.


The condition that jobs belonging to the same group should all be done one after each other or all be unassigned.

Example:
Consider two groups, food and drinks. Food should arrive at the same time at one shop and the drinks alike for the same shop but food and drinks don't have to arrive together. Using this weak condition, the food and drinks itself will not be split, however all of the foods and all of the drinks can be on different vehicles.


The condition that all jobs belonging to one of the listed groups should be assigned to different vehicles or be unassigned.

Example:
Consider two groups, chemicals and explosives. Chemicals and explosives are not allowed to be on the same vehicle and chemicals can't go with other chemicals and explosives not with other explosives. Using this strong condition, no chemicals and explosives in any combination will be on the same vehicle.


The condition that different jobs from groups should be assigned to different vehicles or be unassigned.

Example:
Consider two groups, food and poison. Food is not allowed to be in the same vehicle as the poison but food can be stored with other food and poison with other poison. Using this weak condition, food and poison will be on different vehicles.


The condition that all jobs belonging to one of the listed groups should be assigned to the same vehicle or be unassigned.

Example:
Consider two groups, food and drinks, that have to be delivered to the same shop. Using this strong condition, all foods and drinks will be on the same vehicle. This however does not secure the same arrival time.


The condition that jobs belonging to the same group should be assigned to the same vehicle or be unassigned.

Example:
Consider two groups, food and drinks. Food needs to be delivered to one shop and drinks to another. Food should be grouped together and drinks too but they don't have to be on the same vehicle since they have different destinations. Using this weak condition, all foods will be on the same vehicle and all drinks will be on the same vehicle but food and drinks can be on different vehicles. This however does not secure the same arrival time.


The condition that all jobs belonging to one of the listed groups delivered between a certain time should be assigned to the same vehicle or be unassigned. Due to complexity this condition is only allowed when the rule is hard.

Example:
Consider two groups, A and B, containing jobs that require different keys to access shops after hours but these keys are on the same keychain. Using this strong condition, all jobs in A and B will be on the same vehicle with the keychain and delivered in the same time window e.g. at night.


The condition that jobs belonging to the same group delivered between a certain time should be assigned to the same vehicle or be unassigned. Due to complexity this condition is only allowed when the rule is hard.

Example:
Consider two groups A and B. A contains jobs that require a specific key to access a shop after hours and B contains jobs that require a different key for a different shop and the keys are independent of each other, i.e. not on the same keychain. Using this weak condition, the jobs in A will be on the same vehicle and delivered in the same time window and the jobs in B in the same way. A and B however can be on different vehicles.


Determines if the condition should be satisfied (hard == false) or must be satisfied (hard == true).


The penalty, which is applied if the condition is not met (only necessary if hard == false).


An order of the job within a tour. Within the tour values of following job must be equal or higher (possible: {0,0,1,3,5,6}, not possible: {0,0,3,1}). Setting no value means that the job can go anywhere. Not every job group order value must be set (i.e. {0,1,3}).


If Tours should be planned with both pickups and deliveries of the same shipment, then it is possible to link two Jobs. Warning: Greatly increases complexity for optimisations.


A factor that describes how important it is to plan this job versus others, the higher, the more important. The default is 1.0 and the factor has to be greater than 0.0.


The number of times the driver has to walk from parking to delivery location.


Whether the Job is merely a prediction of an actual Job.


Data is a general data map with string key-values in which unstructured data can be placed.


AppUIData is equal to Data, just in the difference AppUIData is displayed inside the app of NUNAV Courier


Tags are a list of strings that can be used to tag the job. The tags are shown in the UI but have no effect on the optimisation.


If set to true, the Jobs will only be created, but existing Jobs will not be updated.

POST /api/v1/jobs.create
curl --request POST 'https://courier-api.graphmasters.net/api/v1/jobs.create' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "jobs": [
        {
          "id": "33fcefcd",
          "shift": "2022-12-06T00:00:00+01:00",
          "jobAction": "delivery",
          "shipment": {
            "id": "a573be98",
            "barcode": "623416273456437",
            "capacityDimensions": {
              "weight": 3500.0,
              "volume": 2.3,
              "count": 105.0,
              "additionalDimensions": {"pallets": 1.3},
              "allowShipmentsOnTop": true,
              "allowShipmentToBeOnTop": true
            },
            "recipient": "John Doe",
            "sender": "Jane Doe",
            "addressLabel": "Hollerithallee 17 Hannover",
            "assortment": "fresh_food",
            "handlingDurations": {
              "loadingDuration": 40s,
              "unloadingDuration": 10s,
              "reloadingDuration": 40s,
              "transferDuration": 20s
            },
            "data": {"key": "value"},
            "pieces": [
              {
                "id": null,
                "barcode": null,
                "data": null
              }        
            ]
          },
          "client": {
            "depotReference": {
              "referenceId": "depot-berlin-1",
              "referenceType": "depot-id"
            },
            "id": "37e2595e",
            "name": "Jane Doe",
            "serviceTime": {
              "parkingTime": "3m",
              "walkingTime": "25s",
              "additionalTrailerTime": 10m,
              "additionalTrailerHitchingTime": 5m,
              "additionalTrailerUnhitchingTime": 5m
            },
            "address": {
              "street": "Hollerithallee",
              "houseNumber": "17",
              "postcode": "30419",
              "city": "Hannover",
              "country": "Germany"
            },
            "location": {
              "navigationLocation": {
                "latitude": 52.412861820839325,
                "longitude": 9.632570668893964,
                "heading": 180.0
              },
              "serviceLocation": {
                "latitude": 52.412861820839325,
                "longitude": 9.632570668893964,
                "heading": 180.0
              }
            },
            "logicConstraints": {
              "driverConstraints": "drivers-license A && speaks english || speaks german",
              "clientConstraints": "wheelchair accessible",
              "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
              "jobConstraints": "!heavy",
              "carrierConstraints": "long-range tours && postcode == 12345",
              "providedValues": "drivers-license B && speaks german"
            },
            "prohibitedVehicleTypes": ["truck_and_trailer"],
            "prohibitedDeliveryTimes": [
              {
                "name": "worktime",
                "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                "duration": "8h30m"
              }        
            ],
            "conditionalTimeConstraints": [
              {
                "timeSchedule": [
                  {
                    "name": "worktime",
                    "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                    "duration": "8h30m"
                  }            
                ],
                "exceptions": [
                  {
                    "name": "planned absence",
                    "timeSpan": {
                      "from": "2022-12-06T14:00:00+01:00",
                      "till": "2022-12-06T16:00:00+01:00"
                    }
                  }            
                ],
                "assortmentConditions": ["regular-assortment", "secondary-assortment"],
                "jobActionConditions": ["pickup", "delivery"],
                "applyHardTimeConstraint": false,
                "hardTimeConstraintDuration": "1h25m"
              }        
            ],
            "enforceDepartureWithinTimeConstraints": true,
            "clientInformation": {
              "driverInfo": "beware of the dog",
              "phoneNumber": "+491234567890"
            },
            "data": {"key": "value"}
          },
          "trackingId": "b8c7295b578f",
          "duration": "12s",
          "timeConstraints": [
            {
              "from": "2022-12-06T09:00:00+01:00",
              "till": "2022-12-06T09:30:00+01:00",
              "hardFrom": "2022-12-06T08:00:00+01:00",
              "hardTill": "2022-12-06T09:45:00+01:00",
              "priority": 2.0,
              "reason": "express delivery",
              "pressureFunction": "gaussianWindow"
            }      
          ],
          "logicConstraints": {
            "driverConstraints": "drivers-license A && speaks english || speaks german",
            "clientConstraints": "wheelchair accessible",
            "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
            "jobConstraints": "!heavy",
            "carrierConstraints": "long-range tours && postcode == 12345",
            "providedValues": "drivers-license B && speaks german"
          },
          "restrictedDrivers": {
            "allowed": true,
            "ids": ["33fcefcd", "198aa52d"]
          },
          "restrictedVehicles": {
            "allowed": true,
            "ids": ["33fcefcd", "198aa52d"]
          },
          "precedingJobIds": ["example-1", "example-2"],
          "followingJobIds": ["example-1", "example-2"],
          "groups": [
            {
              "id": "7495934fc9d3",
              "timeSpans": [
                {
                  "from": "2022-12-06T14:00:00+01:00",
                  "till": "2022-12-06T16:00:00+01:00"
                }          
              ]
            }      
          ],
          "groupRules": [
            {
              "groupIds": ["7495934fc9d3", "65743fccd3"],
              "condition": "same_vehicle_strong",
              "hard": true,
              "penalty": 2.3
            }      
          ],
          "tourOrder": 3,
          "linkedJobId": "189b1e23",
          "planningImportanceFactor": 2.5,
          "numberOfWalks": 5,
          "isPredicted": false,
          "data": {"key": "value"},
          "appUiData": null,
          "tags": ["prio-job"]
        }  
      ],
      "suppressUpdate": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "jobs": [
    {
      "id": "33fcefcd",
      "shift": "2022-12-06T00:00:00+01:00",
      "jobAction": "delivery",
      "shipment": {
        "id": "a573be98",
        "barcode": "623416273456437",
        "capacityDimensions": {
          "weight": 3500.0,
          "volume": 2.3,
          "count": 105.0,
          "additionalDimensions": {"pallets": 1.3},
          "allowShipmentsOnTop": true,
          "allowShipmentToBeOnTop": true
},
        "recipient": "John Doe",
        "sender": "Jane Doe",
        "addressLabel": "Hollerithallee 17 Hannover",
        "assortment": "fresh_food",
        "handlingDurations": {
          "loadingDuration": 40s,
          "unloadingDuration": 10s,
          "reloadingDuration": 40s,
          "transferDuration": 20s
},
        "data": {"key": "value"},
        "pieces": [
          {
            "id": null,
            "barcode": null,
            "data": null
}
        
        ]
},
      "client": {
        "depotReference": {
          "referenceId": "depot-berlin-1",
          "referenceType": "depot-id"
},
        "id": "37e2595e",
        "name": "Jane Doe",
        "serviceTime": {
          "parkingTime": "3m",
          "walkingTime": "25s",
          "additionalTrailerTime": 10m,
          "additionalTrailerHitchingTime": 5m,
          "additionalTrailerUnhitchingTime": 5m
},
        "address": {
          "street": "Hollerithallee",
          "houseNumber": "17",
          "postcode": "30419",
          "city": "Hannover",
          "country": "Germany"
},
        "location": {
          "navigationLocation": {
            "latitude": 52.412861820839325,
            "longitude": 9.632570668893964,
            "heading": 180.0
},
          "serviceLocation": {
            "latitude": 52.412861820839325,
            "longitude": 9.632570668893964,
            "heading": 180.0
}
},
        "logicConstraints": {
          "driverConstraints": "drivers-license A && speaks english || speaks german",
          "clientConstraints": "wheelchair accessible",
          "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
          "jobConstraints": "!heavy",
          "carrierConstraints": "long-range tours && postcode == 12345",
          "providedValues": "drivers-license B && speaks german"
},
        "prohibitedVehicleTypes": ["truck_and_trailer"],
        "prohibitedDeliveryTimes": [
          {
            "name": "worktime",
            "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
            "duration": "8h30m"
}
        
        ],
        "conditionalTimeConstraints": [
          {
            "timeSchedule": [
              {
                "name": "worktime",
                "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                "duration": "8h30m"
}
            
            ],
            "exceptions": [
              {
                "name": "planned absence",
                "timeSpan": {
                  "from": "2022-12-06T14:00:00+01:00",
                  "till": "2022-12-06T16:00:00+01:00"
}
}
            
            ],
            "assortmentConditions": ["regular-assortment", "secondary-assortment"],
            "jobActionConditions": ["pickup", "delivery"],
            "applyHardTimeConstraint": false,
            "hardTimeConstraintDuration": "1h25m"
}
        
        ],
        "enforceDepartureWithinTimeConstraints": true,
        "clientInformation": {
          "driverInfo": "beware of the dog",
          "phoneNumber": "+491234567890"
},
        "data": {"key": "value"}
},
      "trackingId": "b8c7295b578f",
      "duration": "12s",
      "timeConstraints": [
        {
          "from": "2022-12-06T09:00:00+01:00",
          "till": "2022-12-06T09:30:00+01:00",
          "hardFrom": "2022-12-06T08:00:00+01:00",
          "hardTill": "2022-12-06T09:45:00+01:00",
          "priority": 2.0,
          "reason": "express delivery",
          "pressureFunction": "gaussianWindow"
}
      
      ],
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "restrictedDrivers": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "restrictedVehicles": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "precedingJobIds": ["example-1", "example-2"],
      "followingJobIds": ["example-1", "example-2"],
      "groups": [
        {
          "id": "7495934fc9d3",
          "timeSpans": [
            {
              "from": "2022-12-06T14:00:00+01:00",
              "till": "2022-12-06T16:00:00+01:00"
}
          
          ]
}
      
      ],
      "groupRules": [
        {
          "groupIds": ["7495934fc9d3", "65743fccd3"],
          "condition": "same_vehicle_strong",
          "hard": true,
          "penalty": 2.3
}
      
      ],
      "tourOrder": 3,
      "linkedJobId": "189b1e23",
      "planningImportanceFactor": 2.5,
      "numberOfWalks": 5,
      "isPredicted": false,
      "data": {"key": "value"},
      "appUiData": null,
      "tags": ["prio-job"]
}
  
  ],
  "suppressUpdate": true
}

jobs.delete

Deletes Jobs. The Tours which still reference a deleted Job will be updated and the Job removed from the Tour.


Request Body

DeleteJobsRequest

Request to delete a set of Jobs.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of job IDs identifying the Jobs that shall be deleted.


If true, all Jobs in the Depot will be deleted and the jobIds property will be ignored.

DELETE /api/v1/jobs.delete
curl --request DELETE 'https://courier-api.graphmasters.net/api/v1/jobs.delete' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "jobIds": ["example-1", "example-2"],
      "deleteAll": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "jobIds": ["example-1", "example-2"],
  "deleteAll": true
}

jobs.get

Gets specific Jobs or all Jobs of a Shift and/or Depot.


Request Body

GetJobsRequest

Request to get one or more Jobs. If getAll is true,
the ids field is not necessary and will be ignored. If a specific ID is requested, but does
not exist, then the response will simply not contain a corresponding entity.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of job IDs identifying the Jobs that shall be retrieved.


If set to true, all Jobs of the Depot will be retrieved.


If getAll is used, this option will ensure that only Jobs from the specified Shift are retrieved. See Shifts.


Response Body

GetJobsResponse

Response containing Jobs that were retrieved.


A list of Jobs that were retrieved during a GetJobsRequest.

Job

A Job represents the order to deliver or pickup a Shipment at a Client. Jobs exist in a specific Shift and contain information such as the number of items to be delivered, their weight or time constraints.


A unique ID for the Job. By default, a random ID will be generated.


The shift in which to import the Job. See Shifts


The type of job, by default "delivery".

JobAction

Lists types of actions that can be fulfilled with a specific Job.


The Shipment is picked up at the beginning and delivered at the Client.


The Shipment will be picked up at the Client and delivered at the end.


Physical properties of the Shipment which is being moved for this Job.

Shipment

A Shipment contains physical properties of the transported item.


A unique ID for the Shipment. By default, a random ID will be generated.


The barcode of the Shipment. By default, there is no barcode and the Shipment cannot be scanned.


The physical dimensions of the Shipment. Also contains information about the stackability of the Shipment.

CapacityDimensions

Represents the physical dimensions of a Shipment. There are three default dimensions (weight, volume and count),
but it is also possible to add an arbitrary number of custom dimensions.


The weight of the Shipment (in kg).


The volume of the Shipment (in m³).


the number of items the Shipment consists of.


arbitrary additional dimensions that can be defined. The key is the name of the dimension, the value is the value for this dimension.


Whether this Shipment can carry other Shipments above it. This is only needed when using the feature Shipment Stackability. See capacities on the Vehicle.


Whether this Shipment can go on top of other Shipments. This is only needed when using the feature Shipment Stackability. See capacities on the Vehicle.


The Recipient of the shipment.


The Sender of the shipment.


The label of the address (free text).


A freetext field to denote the assortment of the Shipment.


Fine-granular durations for handling the Shipment in various cases.

HandlingDurations

Fine-granular durations for handling the Shipment in various cases.


The duration of loading the Shipment onto the Vehicle at the beginning of the Tour.


The duration of unloading the Shipment from the Vehicle at the end of the Tour.


The duration of loading the Shipment onto the Vehicle when performing a reloading stop on the Tour.


The duration of transferring the Shipment from trailer to front machine when performing a shipment transfer on the Tour.


Data is a general data map with string key-values in which unstructured data can be placed.


The pieces of the Shipment. One Shipment can optionally consist of many single transported items.

ShipmentPiece

A ShipmentPiece contains physical properties of a single transported item of the Shipment.


The ID of the piece.


The barcode identifying the piece.


Data is a general data map with string key-values in which unstructured data can be placed.


The Client to whom the Job is addressed to.

Client

A Client represents a place or client to be serviced. It could be that your business works with a fixed set of Clients that each have an ID in your system, there is however also the option to have anonymous Clients that get generated along the data import. Most importantly the Client contains an exact geographic location, maybe availabilities in terms of opening hours and other restrictions towards entities like the Vehicle or Driver.


An optional reference to another depot, this should only be used if the Client exists in another depot than the Job. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The unique ID for the Client. By default, a random ID will be generated.


The name of the Client.


The time spent at the Client, includes several different components.

ServiceTime

Describes the time spent at the Client during a Stop. Consists of various different aspects.


The time it takes to park the Vehicle once the navigation has finished. Also includes the time it takes to get back onto the street after the stop.


The time it takes to walk from parking location to delivery location and back once. On the Job we can define the number of walks needed, which will be multiplied to the single walking time.


Extra time that is added to the service time if the Vehicle has a trailer.


Extra time needed to hitch a trailer to a Vehicle. This will be added to the hitching time modelled on the Trailer.


Extra time needed to unhitch a trailer from a Vehicle. This will be added to the unhitching time modelled on the Trailer.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


The geographic location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


Vehicle types that are prohibited to service this Client.

VehicleType

Lists all valid vehicle types. This type affects the travel times and distances as well as some road / client restrictions.


The Vehicle is a van < 3.5t.


The Vehicle is a truck < 40t.


The Vehicle is a truck that also has a separate trailer, all in all < 40t.


The Vehicle is a bus < 40t.


The Vehicle is a motorcycle.


The Vehicle is a bike.


The Vehicle is a cargo bike, which is slightly wider than a normal bike.


The Vehicle is a pedestrian - which is a bit odd but easier in terms of modelling.


Time windows in which the Client cannot be served. This property has priority over time constraints and is regarded as a hard constraint. Furthermore, it will enforce the departure at the client before the prohibited delivery time starts.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Time constraints on the Client, which are only applied to Jobs under a certain condition.

ConditionalTimeConstraints

Represents a time constraint that is applied to a Job only under a certain condition.


The time windows itself are generated from this TimeSchedule.

TimePeriod

A TimePeriod is a recurring or non-recurring period of time that has a rule (in the RFC 5545 iCal Format) as well as a duration.
The duration is the time that the TimePeriod is active. In this way it is possible to model
complex periods of time that are active for a certain duration. The RFC 5545 format is very powerful when it comes
to irregular periods of time, for instance including easter or complex regularities such as 'every 3rd monday of the month'.
As an example, one could model the worktime of a Driver as follows:

Rule: DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYHOUR=9;BYMINUTE=0;BYSECOND=0
Duration: 8h30m

This would mean that the TimePeriod is active every day from 9am to 5:30pm, except on weekends.


An optional display name for the time period.


The RFC 5545 representation of a recurring time.


The duration of the time period.


Exceptions, at which it is not valid.

Unavailability

Specific time periods (without recurrence rules), at which something is unavailable.
For instance a planned absence of a Driver or Vehicle.


A display name of the unavailability.


The time span of the unavailability.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


If set, only for provided assortments the time constraint is valid.


If set, only for provided job actions the time constraint is valid.


If true, time constraints resulting from this are hard.


If applyHardTimeConstraint is true, this is the duration of the hard time constraint, measured from the beginning of the time constraint.


Enforces the Tour to be planned such that the stop is finished before the 'hard till' time constraint. By default, the arrival time is what counts, but this will set the departure time against the time constraints. Default value: 'false'.


Additional, non planning-relevant, information about the Client.

ClientInformation

Information about a Client, which is not planning-relevant but may be useful for driver and dispatcher.


Free-text information for the driver, when navigating to the Client. This info-text is shown in the navigation application.


A telephone number that helps both driver and dispatcher to contact someone at the Client.


Data is a general data map with string key-values in which unstructured data can be placed.


The tracking ID of the Job. Should (but does not have to) be unique. E.g. two corresponding jobs (pickup-delivery) could have the same tracking id. By default, tracking for this Job is deactivated.


The expected time it takes to fulfill the Job. This does not include maneuver time for the vehicle to park or find a parking location, it also does not include walking time to and from the vehicle. That would be modelled on the client. By default, this is 0.


It is possible to add multiple time constraints for the fulfillment of this Job. These time constraints can be configured independently, the optimisation chooses the one making most sense. By default, the Job has no time constraints and can be fulfilled anytime, unless restricted by the Driver, Vehicle or Client.

TimeConstraint

A constraint for an Optimisation, which describes that a Job has to be started between the values of
'from' and 'till'. If 'hardFrom' and 'hardTill' are not set, performing the Job outside the time window is possible whilst incurring a penalty.


Soft opening of the window: this is the time at which the fulfillment of the Job ideally starts.


Soft closing of the window: this is the time at which the fulfillment of the Job ideally ends.


Hard opening of the window: this is the absolute minimum time at which the fulfillment of the Job starts.


Hard closing of the window: this is the absolute maximum time at which the fulfillment of the Job ends.


Priority of the time window. By default, the priority is 1.0. It can overwrite the penalty for not making the time window. It must be greater than 0.0.


Detailed reason for the constraint, e.g. "express delivery". This property is optional and only for showing the context of the time constraint to the user.


Pressure function applied to penalties. An advanced feature for pressuring the fulfillment towards a direction within the time window.

AppointmentPressure

Enumerates different pressure functions for time constraints.
A pressure function encourages the optimisation algorithm to prefer a
certain direction for the fulfillment of a Job.
For example towards the beginning of the time constraint.


Gaussian distribution curve that minimises the penalty at the center of the time constraint. See graph plot.
xy0.511.52-0.5-1-1.5-20.511.52-0.5-1-1.5-2


Sigmoid function that minimises the penalty at the beginning of the time constraint. See graph plot.
xy0.511.52-0.5-1-1.5-20.511.52-0.5-1-1.5-2


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that are grouped in a single Tour with the entity the LogicConstraints are on.

It is possible to apply simple logic with || (OR) and ! (NOT) as well as numerical logic with >, <, >=, <=, == and !=.
Furthermore, it is possible to restrict certain constraints as well as certain values to a time recurrence which is modelled as an RRULE, which should match the beginning of valid Shifts. Thus the constraint only applies in these Shifts as well as values only apply for these Shifts.

Some examples may be useful to understand the power of LogicConstraints:


  • A Job could require of the Vehicle: 'forklift || ramp', because it is too heavy to be carried.

  • A Vehicle could require of the Driver: 'truck drivers license && truck experience && !newbie'.

  • A Client could require of the Vehicle: 'height < 3.5 && width <= 2.2 || !has-trailer && !loud-motor DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYDAY=SU', which means the vehicle has to have height less than 3.5, either width <= 2.2 or not have a trailer and the motor should not be loud, at least on sundays.


One individual element may start with a !, meaning the value must not be provided.
Within an individual element it is possible to have as many ||'s as needed, meaning at least one of the constraint terms need to be satisfied.
It is possible to combine ||'s and !'s.


A list of constraint terms for the Driver, default: no Driver constraints.


A list of constraint terms for the Client, default: no Client constraints.


A list of constraint terms for the Vehicle, default: no Vehicle constraints.


A list of constraint terms for the Job, default: no Job constraints.


A list of constraint terms for the Carrier, default: no Carrier constraints.


A list of constraint values that are offered, default: no constraint values offered.


A blacklist or whitelist of specific Drivers that are allowed to perform the Job. By default, any driver can perform any Job.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


A blacklist or whitelist of specific Drivers that are allowed to perform the Job. By default, any vehicle can perform any Job.

RestrictedSet

A blacklist or a whitelist, depending on the configuration.
It contains of a list of ids, which, based on the value of 'allowed',
will determine whether the base object must 'pair' with one of these or none of them.


If the base object must always (true) or never (false) pair with one of the associated objects.


The ids of the allowed (or disallowed) objects.


An array of job-ids that must be done before this Job. Warning: Greatly increases complexity for optimisations. The Jobs need to be on the same Tour. By default, the order is free.


An array of job-ids that must be done after this Job. Warning: Greatly increases complexity for optimisations. The Jobs need to be on the same Tour. By default, the order is free.


A very advanced feature to describe which Jobs must or must not be grouped together on a Tour. An example would be the delivery of food and poison, which cannot be done on the same Tour. Warning: Greatly increases complexity for optimisations.

JobGroup

Identifies a group of Jobs which can get rules applied
via a GroupRule. Optionally the group can have time ranges in which it forms.


Unique ID of the group you have to provide.


Optional TimeSpans in which the group applies.

TimeSpan

Represents a span of time from a moment in time until another moment in time. It is important that 'till' is always after or equal to 'from', otherwise the TimeSpan would be invalid.


The beginning of the time span.


The end of the time span.


A very advanced feature to describe which Jobs must or must not be grouped together on a Tour. An example would be the delivery of food and poison, which cannot be done on the same Tour. Warning: Greatly increases complexity for optimisations.

GroupRule

A rule that applies to one or more groups of Jobs.


The ids of the groups to which this rule applies.


Represents the condition that all groups subject to this rule must fulfill.

GroupCondition

Lists all valid conditions for group rules.
Warning: the group rule logic is unfortunately quite complex to understand and makes the computational complexity for the optimisation rather high.


The condition that all jobs belonging to one of the listed groups should all be done one after each other or all be unassigned.

Example:
Consider two groups, food and drinks. All jobs in both groups should arrive at the same time in the same shop. Using this strong condition, both the jobs inside the groups will be done after each other and not split but also the groups itself so that everything arrives together.


The condition that jobs belonging to the same group should all be done one after each other or all be unassigned.

Example:
Consider two groups, food and drinks. Food should arrive at the same time at one shop and the drinks alike for the same shop but food and drinks don't have to arrive together. Using this weak condition, the food and drinks itself will not be split, however all of the foods and all of the drinks can be on different vehicles.


The condition that all jobs belonging to one of the listed groups should be assigned to different vehicles or be unassigned.

Example:
Consider two groups, chemicals and explosives. Chemicals and explosives are not allowed to be on the same vehicle and chemicals can't go with other chemicals and explosives not with other explosives. Using this strong condition, no chemicals and explosives in any combination will be on the same vehicle.


The condition that different jobs from groups should be assigned to different vehicles or be unassigned.

Example:
Consider two groups, food and poison. Food is not allowed to be in the same vehicle as the poison but food can be stored with other food and poison with other poison. Using this weak condition, food and poison will be on different vehicles.


The condition that all jobs belonging to one of the listed groups should be assigned to the same vehicle or be unassigned.

Example:
Consider two groups, food and drinks, that have to be delivered to the same shop. Using this strong condition, all foods and drinks will be on the same vehicle. This however does not secure the same arrival time.


The condition that jobs belonging to the same group should be assigned to the same vehicle or be unassigned.

Example:
Consider two groups, food and drinks. Food needs to be delivered to one shop and drinks to another. Food should be grouped together and drinks too but they don't have to be on the same vehicle since they have different destinations. Using this weak condition, all foods will be on the same vehicle and all drinks will be on the same vehicle but food and drinks can be on different vehicles. This however does not secure the same arrival time.


The condition that all jobs belonging to one of the listed groups delivered between a certain time should be assigned to the same vehicle or be unassigned. Due to complexity this condition is only allowed when the rule is hard.

Example:
Consider two groups, A and B, containing jobs that require different keys to access shops after hours but these keys are on the same keychain. Using this strong condition, all jobs in A and B will be on the same vehicle with the keychain and delivered in the same time window e.g. at night.


The condition that jobs belonging to the same group delivered between a certain time should be assigned to the same vehicle or be unassigned. Due to complexity this condition is only allowed when the rule is hard.

Example:
Consider two groups A and B. A contains jobs that require a specific key to access a shop after hours and B contains jobs that require a different key for a different shop and the keys are independent of each other, i.e. not on the same keychain. Using this weak condition, the jobs in A will be on the same vehicle and delivered in the same time window and the jobs in B in the same way. A and B however can be on different vehicles.


Determines if the condition should be satisfied (hard == false) or must be satisfied (hard == true).


The penalty, which is applied if the condition is not met (only necessary if hard == false).


An order of the job within a tour. Within the tour values of following job must be equal or higher (possible: {0,0,1,3,5,6}, not possible: {0,0,3,1}). Setting no value means that the job can go anywhere. Not every job group order value must be set (i.e. {0,1,3}).


If Tours should be planned with both pickups and deliveries of the same shipment, then it is possible to link two Jobs. Warning: Greatly increases complexity for optimisations.


A factor that describes how important it is to plan this job versus others, the higher, the more important. The default is 1.0 and the factor has to be greater than 0.0.


The number of times the driver has to walk from parking to delivery location.


Whether the Job is merely a prediction of an actual Job.


Data is a general data map with string key-values in which unstructured data can be placed.


AppUIData is equal to Data, just in the difference AppUIData is displayed inside the app of NUNAV Courier


Tags are a list of strings that can be used to tag the job. The tags are shown in the UI but have no effect on the optimisation.

POST /api/v1/jobs.get
curl --request POST 'https://courier-api.graphmasters.net/api/v1/jobs.get' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "jobIds": ["example-1", "example-2"],
      "getAll": true,
      "getAllForShift": "2022-12-06T00:00:00+01:00"
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "jobIds": ["example-1", "example-2"],
  "getAll": true,
  "getAllForShift": "2022-12-06T00:00:00+01:00"
}

RESPONSE
{
  "jobs": [
    {
      "id": "33fcefcd",
      "shift": "2022-12-06T00:00:00+01:00",
      "jobAction": "delivery",
      "shipment": {
        "id": "a573be98",
        "barcode": "623416273456437",
        "capacityDimensions": {
          "weight": 3500.0,
          "volume": 2.3,
          "count": 105.0,
          "additionalDimensions": {"pallets": 1.3},
          "allowShipmentsOnTop": true,
          "allowShipmentToBeOnTop": true
},
        "recipient": "John Doe",
        "sender": "Jane Doe",
        "addressLabel": "Hollerithallee 17 Hannover",
        "assortment": "fresh_food",
        "handlingDurations": {
          "loadingDuration": 40s,
          "unloadingDuration": 10s,
          "reloadingDuration": 40s,
          "transferDuration": 20s
},
        "data": {"key": "value"},
        "pieces": [
          {
            "id": null,
            "barcode": null,
            "data": null
}
        
        ]
},
      "client": {
        "depotReference": {
          "referenceId": "depot-berlin-1",
          "referenceType": "depot-id"
},
        "id": "37e2595e",
        "name": "Jane Doe",
        "serviceTime": {
          "parkingTime": "3m",
          "walkingTime": "25s",
          "additionalTrailerTime": 10m,
          "additionalTrailerHitchingTime": 5m,
          "additionalTrailerUnhitchingTime": 5m
},
        "address": {
          "street": "Hollerithallee",
          "houseNumber": "17",
          "postcode": "30419",
          "city": "Hannover",
          "country": "Germany"
},
        "location": {
          "navigationLocation": {
            "latitude": 52.412861820839325,
            "longitude": 9.632570668893964,
            "heading": 180.0
},
          "serviceLocation": {
            "latitude": 52.412861820839325,
            "longitude": 9.632570668893964,
            "heading": 180.0
}
},
        "logicConstraints": {
          "driverConstraints": "drivers-license A && speaks english || speaks german",
          "clientConstraints": "wheelchair accessible",
          "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
          "jobConstraints": "!heavy",
          "carrierConstraints": "long-range tours && postcode == 12345",
          "providedValues": "drivers-license B && speaks german"
},
        "prohibitedVehicleTypes": ["truck_and_trailer"],
        "prohibitedDeliveryTimes": [
          {
            "name": "worktime",
            "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
            "duration": "8h30m"
}
        
        ],
        "conditionalTimeConstraints": [
          {
            "timeSchedule": [
              {
                "name": "worktime",
                "rule": "DTSTART;TZID=Europe/Berlin:19760101T000000\nFREQ=DAILY;INTERVAL=1;BYHOUR=0;BYMINUTE=0;BYSECOND=0",
                "duration": "8h30m"
}
            
            ],
            "exceptions": [
              {
                "name": "planned absence",
                "timeSpan": {
                  "from": "2022-12-06T14:00:00+01:00",
                  "till": "2022-12-06T16:00:00+01:00"
}
}
            
            ],
            "assortmentConditions": ["regular-assortment", "secondary-assortment"],
            "jobActionConditions": ["pickup", "delivery"],
            "applyHardTimeConstraint": false,
            "hardTimeConstraintDuration": "1h25m"
}
        
        ],
        "enforceDepartureWithinTimeConstraints": true,
        "clientInformation": {
          "driverInfo": "beware of the dog",
          "phoneNumber": "+491234567890"
},
        "data": {"key": "value"}
},
      "trackingId": "b8c7295b578f",
      "duration": "12s",
      "timeConstraints": [
        {
          "from": "2022-12-06T09:00:00+01:00",
          "till": "2022-12-06T09:30:00+01:00",
          "hardFrom": "2022-12-06T08:00:00+01:00",
          "hardTill": "2022-12-06T09:45:00+01:00",
          "priority": 2.0,
          "reason": "express delivery",
          "pressureFunction": "gaussianWindow"
}
      
      ],
      "logicConstraints": {
        "driverConstraints": "drivers-license A && speaks english || speaks german",
        "clientConstraints": "wheelchair accessible",
        "vehicleConstraints": "electric vehicle && NOT petrol vehicle && weight <= 20000",
        "jobConstraints": "!heavy",
        "carrierConstraints": "long-range tours && postcode == 12345",
        "providedValues": "drivers-license B && speaks german"
},
      "restrictedDrivers": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "restrictedVehicles": {
        "allowed": true,
        "ids": ["33fcefcd", "198aa52d"]
},
      "precedingJobIds": ["example-1", "example-2"],
      "followingJobIds": ["example-1", "example-2"],
      "groups": [
        {
          "id": "7495934fc9d3",
          "timeSpans": [
            {
              "from": "2022-12-06T14:00:00+01:00",
              "till": "2022-12-06T16:00:00+01:00"
}
          
          ]
}
      
      ],
      "groupRules": [
        {
          "groupIds": ["7495934fc9d3", "65743fccd3"],
          "condition": "same_vehicle_strong",
          "hard": true,
          "penalty": 2.3
}
      
      ],
      "tourOrder": 3,
      "linkedJobId": "189b1e23",
      "planningImportanceFactor": 2.5,
      "numberOfWalks": 5,
      "isPredicted": false,
      "data": {"key": "value"},
      "appUiData": null,
      "tags": ["prio-job"]
}
  
  ]
}

jobs.reassign

Reassigns Jobs from one Tour or the list of unassigned Jobs to a Tour.


Request Body

ReassignJobsRequest

Request to reassign Jobs from one Tour or from the list of unassigned Jobs to a Tour. The request allows for bulk reassignments in order to increase performance.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of JobReassignments, which each contain information about what needs to be reassigned to where.

JobReassignment

Describes the reassignment for a single Job to a Tour.


The reference to the Job which shall be reassigned.

JobReference

Reference object to a Job. There are two ways of finding the Job, either by the ID of the Job, or by the Barcode on the Shipment of the Job.


This is either the Job ID or the Shipment Barcode.


This is the type of reference.

JobReferenceType

Lists the valid types of referencing a Job.


Identifies the Job by ID.


Identifies the Job by the Barcode of its Shipment.


The reference to the Tour to which the Job shall be assigned.

TourReference

Reference object to a Tour. There are three ways of finding the Tour, either by the ID of the Tour, or by the Vehicle ID or Driver ID of the Tour.


This is either the Tour ID, Vehicle ID or Driver ID.


This is the type of reference.

TourReferenceType

Lists the valid types of referencing a Tour.


Identifies the Tour by ID.


Identifies the Tour by the Vehicle ID that is used.


Identifies the Tour by the Driver ID that is used.


If true, Tours that became empty due to this update will be deleted.

POST /api/v1/jobs.reassign
curl --request POST 'https://courier-api.graphmasters.net/api/v1/jobs.reassign' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "reassignments": [
        {
          "jobReference": {
            "referenceId": "03b283n",
            "referenceType": "id"
          },
          "tourReference": {
            "referenceId": "733h13gd",
            "referenceType": "vehicle-id"
          }
        }  
      ],
      "deleteEmptyTours": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "reassignments": [
    {
      "jobReference": {
        "referenceId": "03b283n",
        "referenceType": "id"
},
      "tourReference": {
        "referenceId": "733h13gd",
        "referenceType": "vehicle-id"
}
}
  
  ],
  "deleteEmptyTours": true
}

jobs.status.change

Changes the status of a Job within a Tour. Most commonly it is used to finish the Job.


Request Body

ChangeJobsStatusRequest

Request to change the status of one or more Jobs. The status is the status of the Job on a Tour.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of job ids for which the status will be changed.


An array of barcodes for which the status will be changed.


The new status for the Jobs.

JobStatus

Lists different states of the Job on a Tour.


The job has yet to be done, it will be planned into the Tour.


The job is suspended and will not be planned into the tour order.


The job has been finished.


If true, tour optimisations that might derive from the update will be suppressed.

POST /api/v1/jobs.status.change
curl --request POST 'https://courier-api.graphmasters.net/api/v1/jobs.status.change' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "jobIds": ["33fcefcd", "d437dc13"],
      "barcodes": ["623416273456437"],
      "newJobStatus": "done",
      "suppressTourOptimisation": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "jobIds": ["33fcefcd", "d437dc13"],
  "barcodes": ["623416273456437"],
  "newJobStatus": "done",
  "suppressTourOptimisation": true
}

jobs.unassign

Unassigns Jobs from Tours into the list of unassigned Jobs.


Request Body

UnassignJobsRequest

Request to unassign Jobs from Tours into the list of unassigned Jobs.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


An array of JobReferences, referencing the jobs that should be unassigned.

JobReference

Reference object to a Job. There are two ways of finding the Job, either by the ID of the Job, or by the Barcode on the Shipment of the Job.


This is either the Job ID or the Shipment Barcode.


This is the type of reference.

JobReferenceType

Lists the valid types of referencing a Job.


Identifies the Job by ID.


Identifies the Job by the Barcode of its Shipment.


If true, Tours that became empty due to this update will be deleted.

POST /api/v1/jobs.unassign
curl --request POST 'https://courier-api.graphmasters.net/api/v1/jobs.unassign' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "jobReferences": [
        {
          "referenceId": "03b283n",
          "referenceType": "id"
        }  
      ],
      "deleteEmptyTours": true
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "jobReferences": [
    {
      "referenceId": "03b283n",
      "referenceType": "id"
}
  
  ],
  "deleteEmptyTours": true
}

Optimisation

The Optimisation category contains all functions that are used to calculate Tours. An Optimisation is an asynchronous process of calculating a Tour given a set of configuration values. The API allows users to manage Optimisations, i.e. starting, applying and cancelling them.

optimisation.apply

Applies the resulting Tours of a specific optimisation.


Request Body

ApplyOptimisationRequest

Request to apply an existing Optimisation that has successfully finished.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The ID of the optimisation run that should be applied. This ID is retrieved upon starting an optimisation.

POST /api/v1/optimisation.apply
curl --request POST 'https://courier-api.graphmasters.net/api/v1/optimisation.apply' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "optimisationId": "162f00f5"
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "optimisationId": "162f00f5"
}

optimisation.cancel

Cancels a running optimisation. There will be no valid results that could be applied.


Request Body

CancelOptimisationRequest

Request to cancel a running Optimisation.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The ID of the optimisation run that should be cancelled. This ID is retrieved upon starting an optimisation.

POST /api/v1/optimisation.cancel
curl --request POST 'https://courier-api.graphmasters.net/api/v1/optimisation.cancel' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "optimisationId": "162f00f5"
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "optimisationId": "162f00f5"
}

optimisation.depot.start

Triggers an optimisation of all Vehicles, Drivers and Jobs for a specific Shift in a Depot. The resulting Tours will overwrite already existing Tours.


Request Body

StartDepotOptimisationRequest

Request to start a new depot-wide optimisation. Any Tours within the given Shift will be replaced by the result of the Optimisation.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The shift in which to start the optimisation. See Shifts


The earliest time at which Tours may start. If for instance we want to prevent Tours from starting in the past, we can that the value to the current time. By default, the beginning of the Shift is used.


If true, automatically applies the result of the optimisation after the optimisation run has finished.


The optimisation target is an optional parameter. On the depot, different targets can be defined (and named), and those names can be used here. If the optimisation target is not provided, a default target will be used.


Response Body

StartDepotOptimisationResponse

Response containing the optimisation ID.


The ID of the Optimisation. With this ID the optimisation can be applied, stopped or cancelled.

POST /api/v1/optimisation.depot.start
curl --request POST 'https://courier-api.graphmasters.net/api/v1/optimisation.depot.start' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "shift": "2022-12-06T00:00:00+01:00",
      "earliestTourStartTime": "2022-12-06T04:00:00+01:00",
      "autoApplyResult": true,
      "optimisationTarget": "minimum-distance"
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "shift": "2022-12-06T00:00:00+01:00",
  "earliestTourStartTime": "2022-12-06T04:00:00+01:00",
  "autoApplyResult": true,
  "optimisationTarget": "minimum-distance"
}

RESPONSE
{
  "optimisationId": "162f00f5"
}

optimisation.status.get

Gets the current status of a specific optimisation.


Request Body

GetOptimisationStatusRequest

Request to get the current status of an Optimisation.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The ID of the Optimisation for which the status should be retrieved. This ID is retrieved upon starting an Optimisation.


Response Body

GetOptimisationStatusResponse

Response containing the optimisation status.


The shift in which the optimisation is running. See Shifts


If true, the result of the Optimisation will be automatically applied after the Optimisation has finished.


The current status of the Optimisation.

OptimisationStatus

Lists all valid states of an Optimisation.


The Optimisation has not yet started.


The Optimisation is currently running.


The Optimisation has finished. (Final state).


The Optimisation has been cancelled. (Final state).


The Optimisation has failed. (Final state).

POST /api/v1/optimisation.status.get
curl --request POST 'https://courier-api.graphmasters.net/api/v1/optimisation.status.get' \
  --header 'Authorization: api-key << INSERT API KEY HERE >>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "depotReference": {
        "referenceId": "depot-berlin-1",
        "referenceType": "depot-id"
      },
      "optimisationId": "162f00f5"
}'

REQUEST
{
  "depotReference": {
    "referenceId": "depot-berlin-1",
    "referenceType": "depot-id"
},
  "optimisationId": "162f00f5"
}

RESPONSE
{
  "shift": "2022-12-06T00:00:00+01:00",
  "autoApplyResult": true,
  "status": "running"
}

Tours

The Tours category allows the user to perform basic CRUD operations on Tours.

A Tour is formed by a Vehicle, a Driver and a set of Jobs. It exists within a specific Shift and Depot.

Endpoints in this category contain the creation, deletion and retrieval of Tours. However, the creation of a Tour is merely a shortcut function of creating a Vehicle, Driver and Jobs and then running an Optimisation on them.

tours.create

Shortcut function to import a full Tour. It can make use of an existing Vehicle & Driver or automatically creates a default Vehicle & Driver in the call directly. The Jobs included in the request body will be created and assigned to the Tour.


Request Body

CreateTourRequest

Request to create a new Tour based on the given base entities and options.


The reference to the depot, which is set in the web interface. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The shift in which to import the Tour. See Shifts


A unique ID for the tour to be created. By default, the system will generate a random ID.


A readable name that will be displayed for this tour. By default, the tour won't have a name.


The unique ID of the driver to be used for this tour, in case it already exists. By default, a new default driver will be created.


A readable name of the driver that drives this tour, only needed in case a new driver will be created.


The unique ID of the vehicle to be used for this tour, in case it already exists. By default, a new default vehicle will be created.


A readable name of the vehicle that is used on this tour, only needed in case a new vehicle will be created.


An array of jobs that shall be created for this tour.

Job

A Job represents the order to deliver or pickup a Shipment at a Client. Jobs exist in a specific Shift and contain information such as the number of items to be delivered, their weight or time constraints.


A unique ID for the Job. By default, a random ID will be generated.


The shift in which to import the Job. See Shifts


The type of job, by default "delivery".

JobAction

Lists types of actions that can be fulfilled with a specific Job.


The Shipment is picked up at the beginning and delivered at the Client.


The Shipment will be picked up at the Client and delivered at the end.


Physical properties of the Shipment which is being moved for this Job.

Shipment

A Shipment contains physical properties of the transported item.


A unique ID for the Shipment. By default, a random ID will be generated.


The barcode of the Shipment. By default, there is no barcode and the Shipment cannot be scanned.


The physical dimensions of the Shipment. Also contains information about the stackability of the Shipment.

CapacityDimensions

Represents the physical dimensions of a Shipment. There are three default dimensions (weight, volume and count),
but it is also possible to add an arbitrary number of custom dimensions.


The weight of the Shipment (in kg).


The volume of the Shipment (in m³).


the number of items the Shipment consists of.


arbitrary additional dimensions that can be defined. The key is the name of the dimension, the value is the value for this dimension.


Whether this Shipment can carry other Shipments above it. This is only needed when using the feature Shipment Stackability. See capacities on the Vehicle.


Whether this Shipment can go on top of other Shipments. This is only needed when using the feature Shipment Stackability. See capacities on the Vehicle.


The Recipient of the shipment.


The Sender of the shipment.


The label of the address (free text).


A freetext field to denote the assortment of the Shipment.


Fine-granular durations for handling the Shipment in various cases.

HandlingDurations

Fine-granular durations for handling the Shipment in various cases.


The duration of loading the Shipment onto the Vehicle at the beginning of the Tour.


The duration of unloading the Shipment from the Vehicle at the end of the Tour.


The duration of loading the Shipment onto the Vehicle when performing a reloading stop on the Tour.


The duration of transferring the Shipment from trailer to front machine when performing a shipment transfer on the Tour.


Data is a general data map with string key-values in which unstructured data can be placed.


The pieces of the Shipment. One Shipment can optionally consist of many single transported items.

ShipmentPiece

A ShipmentPiece contains physical properties of a single transported item of the Shipment.


The ID of the piece.


The barcode identifying the piece.


Data is a general data map with string key-values in which unstructured data can be placed.


The Client to whom the Job is addressed to.

Client

A Client represents a place or client to be serviced. It could be that your business works with a fixed set of Clients that each have an ID in your system, there is however also the option to have anonymous Clients that get generated along the data import. Most importantly the Client contains an exact geographic location, maybe availabilities in terms of opening hours and other restrictions towards entities like the Vehicle or Driver.


An optional reference to another depot, this should only be used if the Client exists in another depot than the Job. See API Reference ID.

DepotReference

Reference object to a Depot. There are two ways of finding the Depot, either by the ID of the Depot, or by a ReferenceID set on the NUNAV Courier Website.
See API Reference ID for details.


This is either the Depot ID or an API Reference ID.


This is the type of reference.

DepotReferenceType

Lists the valid types of referencing a Depot.


Identifies the Depot by API Reference ID.


Identifies the Depot by its Depot ID.


The unique ID for the Client. By default, a random ID will be generated.


The name of the Client.


The time spent at the Client, includes several different components.

ServiceTime

Describes the time spent at the Client during a Stop. Consists of various different aspects.


The time it takes to park the Vehicle once the navigation has finished. Also includes the time it takes to get back onto the street after the stop.


The time it takes to walk from parking location to delivery location and back once. On the Job we can define the number of walks needed, which will be multiplied to the single walking time.


Extra time that is added to the service time if the Vehicle has a trailer.


Extra time needed to hitch a trailer to a Vehicle. This will be added to the hitching time modelled on the Trailer.


Extra time needed to unhitch a trailer from a Vehicle. This will be added to the unhitching time modelled on the Trailer.


The formatted address of the Client. Required if no location is provided.

Address

Contains structured text information about an address. Each individual part is optional, but enhances the geocoding quality.


The street of the address.


The house number of the address.


The postcode of the address.


The city of the address.


The country of the address.


The geographic location at which the Client can be found, the system will automatically geocode the address if this is empty and an address is provided.

Location

The location for a certain Address. At least one of 'navigationLocation' and 'serviceLocation' are required for it to be valid.


The location at which to navigate to.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


The location at which to perform the service.

GeoLocation

A geographic location in the WGS84 format.


The latitude (WGS84).


The longitude (WGS84).


The heading h, where h >= 0.0 and h < 360.0. North == 0.0, East == 90.0, South == 180.0 and West == 270.0.


Detailed logical constraints of this entity as well as constraint values that are offered for other entities.

LogicConstraints

LogicConstraints describe arbitrary logical constraints that can be required from entities that a