Conroo Trucking Api documentation

Conroo Trucking Api Version 1.0.0


Introduction



API CHANGELOG:
Trucking api introduction image

Trucking api process graph

This Api description explains how the various endpoints in this api can be used to effectively used to communicate with conroo. Correct authentication is required to interact with this api through an Api Key, conroo must be contacted for access.

Authentication

Since this is a server to server api communication shall be done by an api key which will be distributed by us. It should be sent as a header with name "X-API-KEY" and the value provided. Also the truckingSystemId should be provided in authentication api calls as it is needed to identify if the current api key belongs to the trucking system.

Request example in javascript


                                    
const headers = new Headers({
'X-API-KEY': apiKey,
'Content-Type': 'application/json', 
});

// Make the API call using fetch
fetch(apiEndpoint, {
method: 'GET', // You can use other HTTP methods (e.g., 'POST', 'PUT', 'DELETE')
headers: headers,
})
.then(response => response.json())
.then(data => {
console.log('API Response:', data);
})
.catch(error => {
console.error('API Error:', error);
});                                  
                                    

Working with tours

Tours are the main component of the api and describe a route taken by a trucker.
Tours are a collection of loading units which represent the bookings (whether they may be pickups or deliveries), and they are specified for a specific timeslot (time to be completed) together.

Trucking api tour explanation

Tours entities


Getting the status of loading units

The first step on interacting with tours is getting the necessary information of the loading units. We offer that through the endpoint "get status" in which an array of requets containing loadUnitNumber and referenceNumber are provided along with the type.
The response contains data for the loading units and also a shared timeslot between all these loading units.

Request example in javascript

 

const endpointUrl = '/v1/truckingSystems/{truckingSystemId}/forwarders/{forwarderId}/facilities/{facilityId}/loadingunits';

// Define the request payload (body data)
const requestBody = {
"requests": [
{
"loadUnitNumber": "CERU1234567",
"referenceNumber": "90090061924532",
"type": "delivery"
}
]
};

// Define the path parameters
const truckingSystemId = 123; // Replace with the actual truckingSystemId
const forwarderId = 456;      // Replace with the actual forwarderId
const facilityId = 789;       // Replace with the actual facilityId

// Generate the complete URL by replacing path parameters
const completeUrl = endpointUrl
.replace('{truckingSystemId}', truckingSystemId)
.replace('{forwarderId}', forwarderId)
.replace('{facilityId}', facilityId);

// Define request headers
const headers = new Headers({
'Content-Type': 'application/json',
'X-API-KEY': 'YOUR_API_KEY_HERE', // Replace with your actual API key
// Add any additional headers if required
});

// Create the Fetch API request
const fetchOptions = {
method: 'POST',
headers: headers,
body: JSON.stringify(requestBody),
};

// Make the API call
fetch(completeUrl, fetchOptions)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// Handle the successful response data here
console.log('API Response:', data);
})
.catch(error => {
// Handle errors here
console.error('API Error:', error);
});                            
                        

The json response is shown below (detailed fields explanation are in the swagger specifications):

 
[
  {
    "responses": {
      "loadUnitNumber": "CERU1234567",
      "referenceNumber": "90090061924532",
      "type": "delivery",
      "loadUnit": {
        "loadUnitLength": 40,
        "loadUnitNumber": "CERU1234567",
        "loadUnitType": "string",
        "emptyWeight": 2000,
        "id": 1,
        "listDangerousGoodsData": [
          {
            "clazz": "string",
            "id": 0,
            "lq": true,
            "uNNr": "string"
          }
        ],
        "listSealData": [
          {
            "id": 0,
            "number": "string"
          }
        ],
        "listCustomsData": [
          {
            "documentNumber": "string",
            "documentType": "string",
            "id": 0
          }
        ],
        "listWasteData": [
          {
            "aVVNumber": "string",
            "eAKKeyNumber": "string",
            "id": 0,
            "voucherNumber": "string"
          }
        ],
        "netWeight": 20000,
        "overhang": 0
      },
      "errorCode": "string"
    },
    "timeSlots": [
      {
        "remainingCapacity": 50,
        "expectedCycleTime": 20,
        "id": 0,
        "slotBegin": "2022-08-10T07:34:58.294Z",
        "slotEnd": "2022-08-10T07:35:15.886Z"
      }
    ]
  }
]

                         
                       

Creating a tour

After the prerequisite of getting the loading units we are ready to create a tour. Tours are created in the level of forwarders, and also per trucker with the information of loading units being part of a facility. Here the same information should be still sent of loadUnitNumber, referenceNumber and type and also the timeslotId. Get status is important because it provides the information of the loadiung units along with the timeslots available in which we can use here to create the tour.

Request example in javascript

                            
const endpointUrl = '/v1/truckingSystems/{truckingSystemId}/forwarders/{forwarderId}/truckers/{truckerId}/facilities/{facilityId}/tours';

// Define the request payload (body data)
const requestBody = {
"timeSlotId":346,
"containerBookings": [
{
"loadUnitNumber": "CERU1234567",
"referenceNumber": "90090061924532",
"type": "delivery"
}
]
};

// Define the path parameters
const truckingSystemId = 123; // Replace with the actual truckingSystemId
const forwarderId = 456;      // Replace with the actual forwarderId
const facilityId = 789;       // Replace with the actual facilityId
const truckerId = "419242-10941-01249f";

// Generate the complete URL by replacing path parameters
const completeUrl = endpointUrl
.replace('{truckingSystemId}', truckingSystemId)
.replace('{forwarderId}', forwarderId)
.replace('{facilityId}', facilityId)
.replcae('{truckerId}',truckerId);

// Define request headers
const headers = new Headers({
'Content-Type': 'application/json',
'X-API-KEY': 'YOUR_API_KEY_HERE', // Replace with your actual API key
// Add any additional headers if required
});

// Create the Fetch API request
const fetchOptions = {
method: 'POST',
headers: headers,
body: JSON.stringify(requestBody),
};

// Make the API call
fetch(completeUrl, fetchOptions)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// Handle the successful response data here
console.log('API Response:', data);
})
.catch(error => {
// Handle errors here
console.error('API Error:', error);
}); 
                        

If all goes well a 200 http response should be returned, mirroring back the tour data saved.

Manipulating the tour (planned for phase 2)

After we create the tours, the tours can be manipulated as most basic entities in a rest api:

  • Getting tours (get tour by id), the id is provided by the create tour response
  • Canceling a tour (if the conditions are met)
  • Getting the timeslots of the tour for this given time
  • Updating the timeslot for a tour
  • Adding another loading unit to the tour
  • Removing a loading unit to the tour

All these endpoints are specified in the swagger specification, we will be explaining only the non trivial ones in this documentation.

Updating timeslot of tour

In cases when a tour can not be completed at the agreed time, the time can be changed.
First the available times must be fetched from the endpoint "get timeslots per tour", and then an id must be sent for that timeslot to update the tour in the next endpoint.

Adding a containerbooking to the tour

Adding a container booking mostly follows the same schema, with the only important point that if the loadingunit does not have the shared timeslot with the other existing loading units in the tour this action will not work.

Loading units

Working with loading units

Loading units as specified before on the tours section are objects which represent loading units in facilities(terminals/depots). Fetching loading units was already explained on tours, the only other action is updating the information of an update load unit. This may happen on cases where the facility does not give the correct information or does not even have it. Cases where this may be applicable are a missing loadUnitNumber for deliveries.

Example request in javascript


 const endpointUrl = '/v1/truckingSystems/{truckingSystemId}/forwarders/{forwarderId}/tours/{tourId}/containerBooking/{containerBookingId}/loadUnits';

// Define the request payload (body data)
const requestBody = {
  "loadUnit": {
    "loadUnitLength": 40,
    "loadUnitNumber": "CERU1234567",
    "loadUnitType": "string",
    "emptyWeight": 2000,
    "id": 1,
    "listDangerousGoodsData": [
      {
        "clazz": "string",
        "id": 0,
        "lq": true,
        "uNNr": "string"
      }
    ],
    "listSealData": [
      {
        "id": 0,
        "number": "string"
      }
    ],
    "listCustomsData": [
      {
        "documentNumber": "string",
        "documentType": "string",
        "id": 0
      }
    ],
    "listWasteData": [
      {
        "aVVNumber": "string",
        "eAKKeyNumber": "string",
        "id": 0,
        "voucherNumber": "string"
      }
    ],
    "netWeight": 20000,
    "overhang": 0
  }
};

// Define the path parameters
const truckingSystemId = 123; // Replace with the actual truckingSystemId
const forwarderId = 456;      // Replace with the actual forwarderId
const tourId = 789;       // Replace with the actual  tourId
const containerBookingId = 32;

// Generate the complete URL by replacing path parameters
const completeUrl = endpointUrl
.replace('{truckingSystemId}', truckingSystemId)
.replace('{forwarderId}', forwarderId)
.replace('{tourId}', tourId)
.replcae('{containerBookingId}',containerBookingId);

// Define request headers
const headers = new Headers({
'Content-Type': 'application/json',
'X-API-KEY': 'YOUR_API_KEY_HERE', // Replace with your actual API key
// Add any additional headers if required
});

// Create the Fetch API request
const fetchOptions = {
method: 'POST',
headers: headers,
body: JSON.stringify(requestBody),
};

// Make the API call
fetch(completeUrl, fetchOptions)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
// Handle the successful response data here
console.log('API Response:', data);
})
.catch(error => {
// Handle errors here
console.error('API Error:', error);
}); 
                      

All attributes that belong to this object can be manipulated.
Basic validation is applicable like iso 6346 for loadunitnumber or weight and length validations.

Forwarders

Forwarders are part of the trucker objects and through this object we know which truckers "belong" to which forwarders.

Saving a forwarder

The saving forwarder endpoint saves the forwarder by name and email if not existing, and if it is already in our system, it is returned. In either case an appropriate forwarder instance with an id will be returned.

Getting forwarders

The get forwarders endpoint is quite simplistic in which it returns all forwarders for your truckiong system.

Example response

 
[
  {
    "email": "forwarder@truck.com",
    "id": 3,
    "name": "Example Forwarder"
  }
]
                            

Truckers and Trucks

The truckers endpoints are mostly trivial in use, they are all CRUD endpoints in which we allow the base functonality like:
  • Creating truckers/trucks
  • Fetching the data by id
  • Updating the data of trucks/truckers (all of the object should be sent and not just changed fields)
  • Getting all trucks/truckers for a forwarder.
  • Deleting the trucks/truckers

All information for these endpoints is available in the swagger documentation at the top of the page.

Websocket messages

Event updates on our system currently happen constantly, and as an alternative to implementing server endpoints to do http calls, we have websocket endpoints in which we give updates to all the events we push and the events we expected to be pushed here.

Authorization example in javascript

                            
const WebSocket = require('websocket').client;

const wsClient = new WebSocket();

const serverUrl = 'ws://your-websocket-server-url';
const apiKey = 'your-api-key';

wsClient.on('connectFailed', (error) => {
  console.error('Connection failed:', error);
});

wsClient.on('connect', (connection) => {
  console.log('WebSocket Client Connected');

  connection.on('error', (error) => {
    console.error('Connection Error:', error);
  });

  connection.on('close', () => {
    console.log('Connection Closed');
  });

  connection.on('message', (message) => {
    if (message.type === 'utf8') {
      console.log('Received message:', message.utf8Data);
    }
  });

  // Set the API key in the headers
  connection.setHeader('X-API-KEY', apiKey);

  // Connect to the WebSocket server
  connection.connect(serverUrl);
});
                            
                        

Pushed events

These events are events conroo sends to update the state about truckers and their connected entities like load units, tours and other components.

UpdateContainerBookingData

This event is sent on cases where the facility(terminal/depot) has new information and updates the data of one of the load units that is part of the tour. The load unit must be updated acoordingly after this messsage


{
  "type": "update_booking_loading_unit_data",
  "event": {
    "loadUnit": {
      "loadUnitLength": 0,
      "loadUnitType": "string",
      "loadUnitNumber": "string",
      "emptyWeight": 0,
      "listDangerousGoodsData": [
        {
          "uNNr": "string",
          "lq": true,
          "clazz": "string"
        }
      ],
      "listSealData": [
        {
          "sealNumber": "string"
        }
      ],
      "listCustomsData": [
        {
          "documentNumber": "string",
          "documentType": "string"
        }
      ],
      "listWasteData": [
        {
          "voucherNumber": "string",
          "aVVNumber": "string",
          "eAKKeyNumber": "string"
        }
      ],
      "netWeight": 0,
      "overhang": 0
    },
    "tourId": 0,
    "containerBookingId": 0
  }
}
                        

UpdateTourSlotTimes

On updates of trains or other entities in which loadunits may cause changes in time schedule, the available timeslots change, this messsage calculates the new available timeslots for a tour. In this case a new timeslot should be picked with the endpoint updateTimeslotForTour.


{
  "type": "update_tour_slot_times",
  "event": {
    "tourId": 0,
    "timeSlots": [
      {
        "id": 0,
        "slotBegin": "2019-08-24T14:15:22Z",
        "slotEnd": "2019-08-24T14:15:22Z"
      }
    ]
  }
}
                        

DeleteContainerBooking

On cases where a container is deleted by a facility or other entity, this information is passed on acoordingly.


{
  "type": "delete_booking",
  "event": {
    "tourId": 0,
    "containerBookingId": 0,
    "reason": "string",
    "truckerId": "string",
    "author": "FACILITY"
  }
}
                        

DeleteTourBooking

This message is equivalent to the previous one, with the only key difference being that this deletes the whole tour and not just one specific booking.

                    
{
  "type": "delete_tour",
  "event": {
    "tourId": 0,
    "reason": "string",
    "truckerId": "string",
    "author": "FACILITY"
  }
}
                    
                   

TranshipmentTaskConfirmation

This message informs that the crane task has been complete for the specific loadunit and everything is complete in the side of the facility successfully on the process of picking/delivering.


{
  "type": "transhipment_task_confirmation",
  "event": {
    "tourId": "string",
    "containerBookingId": "string",
    "truckerId": "string"
  }
}
                   

UpdateModule

Modules as part of facilities may be closed and opened due to internal needs of the facility.This message informs about such a change along with all the ids of the loadunits that are affected, this can be useful for informing the truckers whose these containers belong to.


{
  "type": "update_module_state",
  "event": {
    "state": "opened",
    "facilityId": 0,
    "module": "string",
    "containerBookingIds": [
      0
    ]
  }
}