Once a trip is in progress, we process the GPS updates as realisation points. The most recent information from your “tracking device”, should be delivered to our platform often for more accurate trip monitoring. Simacan provides an API for sending these realisation points using the OTM5 format.
The full endpoint reference is available as the OTM5 Realisation API in the API Marketplace.
OTM5 realisation data comes in three shapes:
- By sending the coordinates along with the trip ID the update belongs to.
- By sending the coordinates along with the license plate of the vehicle the update belongs to. If the vehicle is not yet known it will be created on demand.
- By sending the coordinates along with the device ID of the vehicle the update belongs to. If the vehicle is not yet known it will be created on demand.
An example of the first looks like this:
{
"eventType": "locationUpdateEvent",
"creationDate": "2021-10-27T09:00:31Z",
"externalAttributes": {
"tripId": "my-trip-id",
},
"lifecycle": "actual",
"actors": [{
"entity": { "name": "some-shipper" },
"roles": ["shipper"],
"associationType": "inline"
},
{
"entity": { "name": "some-carrier" },
"roles": ["carrier"],
"associationType": "inline"
}
],
"geoReference": {
"lat": 52,
"lon": 7,
"type": "latLonPointGeoReference"
}
}An example of the second looks like this:
{
"eventType": "locationUpdateEvent",
"creationDate": "2021-10-27T09:00:31Z",
"lifecycle": "actual",
"actors": [{
"entity": { "name": "some-shipper" },
"roles": ["shipper"],
"associationType": "inline"
},
{
"entity": { "name": "some-carrier" },
"roles": ["carrier"],
"associationType": "inline"
}
],
"vehicle": {
"entity": {
"vehicleType": "Truck",
"licensePlate": "AA-BB-CC"
},
"associationType": "inline"
},
"geoReference": {
"lat": 52,
"lon": 7,
"speed": {
"value": 0,
"unit": "km/h"
},
"heading": {
"value": 0,
"unit": "degrees"
},
"type": "latLonPointGeoReference"
}
}An example of the third looks like this:
{
"eventType": "locationUpdateEvent",
"creationDate": "2021-10-27T09:00:31Z",
"lifecycle": "actual",
"vehicle": {
"entity": {
"externalAttributes": {
"vehicleId": "some-device-id"
}
},
"associationType": "inline"
},
"actors": [{
"entity": { "name": "some-shipper"},
"roles": ["shipper"],
"associationType": "inline"
},
{
"entity": { "name": "some-carrier"},
"roles": ["carrier"],
"associationType": "inline"
}
],
"geoReference": {
"lat": 52,
"lon": 7,
"speed": {
"value": 0,
"unit": "km/h"
},
"heading": {
"value": 0,
"unit": "degrees"
}
}
}As can be seen from both versions there are a few mandatory parts:
- Each message needs to be of the type
locationUpdateEvent. Any other OTM5 event types will be rejected with a validation error. - Each message needs to have actors, we require both the carrier and shipper information.
- Each message needs a couple id. As mentioned above, this can either be the trip ID in the external attributes or the vehicle. If both are provided the trip ID will be used and the vehicle will be ignored.
- Each message with only license plate or vehicle ID, requires a call to the couple API to assign the vehicle to a trip.
- Each message needs coordinates. The speed and heading can be optionally provided in both cases.
- Each message expects the lifecycle actual and the creation date of the update.
This example only works, if you obtained a bearer token from our Auth API. Include this in the header. Here we post to the production URL
curl -X PUT \
https://otm5-realisation-receiver.services.simacan.com/api/v5/events \
-H "Authorization: Bearer eyXXX" \
-H "Content-Type: application/json" \
-d '{
"eventType": "locationUpdateEvent",
"creationDate": "2021-10-27T09:00:31Z",
"externalAttributes": {
"tripId": "my-trip-id"
},
"lifecycle": "actual",
"actors": [{
"entity": { "name": "some-shipper" },
"roles": ["shipper"],
"associationType": "inline"
},
{
"entity": { "name": "some-carrier" },
"roles": ["carrier"],
"associationType": "inline"
}
],
"geoReference": {
"lat": 52,
"lon": 7,
"type": "latLonPointGeoReference"
}
}'If you receive an HTTP status code 200 OK, you have confirmed you are sending data correctly. You can start sending all your updates to our platform.
Great! You are totally set to send tracking data updates for specified tracking devices
Besides location updates, the same endpoint accepts goods realisation messages. Where a locationUpdateEvent reports where a vehicle is, a goods realisation reports what happened to the goods at a stop: which items were delivered or picked up, which were refused or damaged, and in what quantity. This allows the platform to reflect the outcome of a load or unload down to the level of the individual goods.
A goods realisation is sent as an updateEvent on the load or unload action that was realized. The result is expressed using the OTM5 result model: the action carries an overall result, and that result can contain a results array with a separate result per (group of) goods.
An example of a partially succeeded unload looks like this:
{
"eventType": "updateEvent",
"creationDate": "2026-02-03T19:54:11Z",
"entity": {
"entityType": "unload",
"id": "ccc9b885-0b69-374f-b148-60598d2e3dba",
"lifecycle": "realized",
"result": {
"status": "partiallySucceeded",
"results": [
{
"status": "succeeded",
"references": [
{
"uuid": "f97626b0-b6f8-3447-9e8c-d7d06c7ca50c",
"entityType": "items",
"associationType": "reference"
}
]
},
{
"status": "failed",
"remark": "One helmet had a crack in it and was refused by the customer",
"reason": "incomplete",
"references": [
{
"associationType": "inline",
"entity": {
"type": "items",
"id": "041fd231-d58c-38c4-b9e3-c1e17acabfc5",
"quantity": 4
}
}
]
}
]
},
"timeFormat": "dateTime",
"startTime": "2026-02-03T19:53:37Z",
"endTime": "2026-02-03T19:54:07Z"
},
"actors": [
{
"entity": { "name": "some-shipper" },
"roles": ["shipper"],
"associationType": "inline"
},
{
"entity": { "name": "some-carrier" },
"roles": ["carrier"],
"associationType": "inline"
}
]
}As with location updates, a few parts are mandatory:
- Each message needs to be of the type
updateEvent. - Each message needs
actors; we require both the carrier and shipper information. These are used to identify the trip. - The
entitydescribes the action that was realized. It needs anentityTypeofloadorunload, theidof that action, and thelifecyclerealized. - The
entityneeds aresultdescribing the outcome of the action (see below). - The
startTimeandendTimedescribe when the action was actually carried out. UsetimeFormatdateTime.
The result on the action describes the overall outcome, and optionally breaks it down per goods in results.
| Field | Description |
|---|---|
status | The overall outcome of the action: succeeded, partiallySucceeded, failed or cancelled. |
remark | Free text clarifying the result. May be omitted. |
reason | A reason code explaining the (partial) failure, one of damage, receiverAbsent or incomplete. Omit it when the action succeeded. |
results | Optional array of goods-level results. Use this to report the outcome per (group of) goods. |
Each entry in the results array reports the outcome for one or more goods:
| Field | Description |
|---|---|
status | The outcome for the referenced goods: succeeded, partiallySucceeded, failed or cancelled. |
remark | Optional free text, for example why the goods were refused. |
reason | Optional reason code, for example incomplete. |
references | The goods this result applies to. Both items and transportEquipment may be referenced. |
The goods in references can be identified in two ways:
By reference — point to goods that are already known on the trip by their uuid:
{
"uuid": "f97626b0-b6f8-3447-9e8c-d7d06c7ca50c",
"entityType": "items",
"associationType": "reference"
}Inline — describe the goods in the message itself. The quantity here is the realized quantity (how much was actually delivered or picked up):
{
"associationType": "inline",
"entity": {
"type": "items",
"id": "041fd231-d58c-38c4-b9e3-c1e17acabfc5",
"quantity": 4
}
}Just like a location update, this example only works if you obtained a bearer token from our Auth API. Include it in the header and post to the production URL:
curl -X PUT \
https://otm5-realisation-receiver.services.simacan.com/api/v5/events \
-H "Authorization: Bearer eyXXX" \
-H "Content-Type: application/json" \
-d '{
"eventType": "updateEvent",
"creationDate": "2026-02-03T19:54:11Z",
"entity": {
"entityType": "unload",
"id": "ccc9b885-0b69-374f-b148-60598d2e3dba",
"lifecycle": "realized",
"result": {
"status": "partiallySucceeded",
"results": [
{
"status": "succeeded",
"references": [
{
"uuid": "f97626b0-b6f8-3447-9e8c-d7d06c7ca50c",
"entityType": "items",
"associationType": "reference"
}
]
},
{
"status": "failed",
"remark": "One helmet had a crack in it and was refused by the customer",
"reason": "incomplete",
"references": [
{
"associationType": "inline",
"entity": {
"type": "items",
"id": "041fd231-d58c-38c4-b9e3-c1e17acabfc5",
"quantity": 4
}
}
]
}
]
},
"timeFormat": "dateTime",
"startTime": "2026-02-03T19:53:37Z",
"endTime": "2026-02-03T19:54:07Z"
},
"actors": [
{ "entity": { "name": "some-shipper" }, "roles": ["shipper"], "associationType": "inline" },
{ "entity": { "name": "some-carrier" }, "roles": ["carrier"], "associationType": "inline" }
]
}'A 200 OK confirms the goods realisation was accepted and will be processed towards the SCT.