Skip to main content

Tracking API

Capture GPS telemetry from field devices, see where your workforce is right now, and replay where they have been.


Overview & Solution​

Field teams are the part of the business you can least see. Attendance is self-reported, visits are claimed after the fact, and disputes come down to one person's word.

The Tracking API closes that gap. Devices push location continuously; you read it back as a live position or as a full day's track. Every point carries speed, accuracy, battery and device metadata, so you can tell a real journey from a device left on a desk.

Key Value Propositions​

  • Live and historical in one API - the same telemetry stream answers "where is this person now" and "where did they go last Tuesday".
  • Accepts backdated points - the API takes timestamped points regardless of when they arrive, so an app can buffer locally while offline and push the batch once connectivity returns. Whether a given app actually supports offline collection is a front-end/SDK decision, not something this API does on its own.

Industry Use Cases​

1. Banking, NBFC & Collections​

  • Verified field presence - prove a collections officer reached the customer's premises, with time and coordinates, instead of relying on a call report.
  • Attendance without hardware - replace biometric machines at branches the workforce never visits.

2. Distribution & Field Sales​

  • Beat adherence - compare the route actually travelled against the planned journey and see where the day diverged.
  • Productive hours - separate travel time from time at customer locations.

3. Service & Maintenance Networks​

  • Nearest-technician dispatch - route the next job to whoever is genuinely closest, not whoever answers first.
  • SLA evidence - reconstruct arrival times when a customer disputes a response window.

How it works​

graph LR
A[Device collects GPS] --> B{Network available?}
B -->|Yes| C[Push to backend]
B -->|No| D[Store on device]
D --> C
C --> E[Live position / History]
  1. Collect - the device records position continuously, in foreground and background.
  2. Buffer - without connectivity, points are retained locally rather than dropped.
  3. Push - buffered points are sent as soon as the network returns.
  4. Read - query the latest known position, or a full track over a time range.
Terminated-state collection

Background collection continues after the app is closed on Android. On iOS this is not possible - a platform restriction, not an SDK limitation.


Works well with​

Pair it withTo get
PJP APIPlanned route vs actual route
Events APIDuty status and check-ins alongside the track
Reverse Geocode APIReadable addresses instead of raw coordinates


API reference​

Field Force Mobility Execution APIs · Requires Intelomatic tenant

Endpoints​

MethodPathPurpose
POST/tracking/pushPush GPS points from a device
POST/tracking/liveGet current positions
POST/tracking/historyGet historical track

All requests require a bearer token and the api-key query parameter:

Authorization: Bearer <access_token>
?api-key=<apiKey>

Push GPS points from a device​

POST /tracking/push

Request Parameters

ParameterInTypeRequiredDescriptionExample
[]bodyobjectNoOne GPS point. Send several objects to push a batch.
[].driverbodystringNoUsername of the employee the device belongs to.
[].trackerIdbodystringNoDevice identifier. The live and history calls read the track back by this value.
[].headingbodyintegerNo
[].latbodynumberNoLatitude, decimal degrees.
[].lngbodynumberNoLongitude, decimal degrees.
[].motionActivitybodyintegerNo
[].sessionbodyintegerNo
[].speedbodyintegerNo
[].timestampbodyintegerNoTime of the fix, Unix epoch seconds.
[].jobStatusbodyintegerNo
[].metabodystringNoExtra device metadata as a JSON-encoded string, not an object.

Request body

[
{
"driver": "your_username",
"trackerId": "mydevice@your_username",
"heading": 0,
"lat": 18.4585507,
"lng": 75.4128607,
"motionActivity": 0,
"session": 1790131313,
"speed": 0,
"timestamp": 1790131380,
"jobStatus": 2,
"meta": "{\"sourceType\":\"api\",\"accuracy\":1217.35,\"battery\":\"86%\",\"networkType\":\"Mobile\"}"
}
]

Response Schema

200 OK

{
"status": {
"success": true,
"time": "2026-09-23T02:29:38.888Z"
}
}
FieldTypeDescription
statusobject
status.successbooleantrue when the points were accepted.
status.timestringServer time the batch was accepted, UTC.

The body is a JSON array, one object per GPS point - send a single-element array for one point.

Get current positions​

POST /tracking/live

Request Parameters

ParameterInTypeRequiredDescriptionExample
layerbodystringNoLayer the trackers belong to, EMPLOYEE.
pagebodyintegerNoPage number, starting at 1.
pageSizebodyintegerNoTrackers per page.
searchKeybodystringNoFree-text filter. Empty string returns all.
sortbodyarrayNoFields to sort by.
sort[]bodystringNo

Request body

{
"layer": "EMPLOYEE",
"page": 1,
"pageSize": 20,
"searchKey": "",
"sort": [
"ts"
]
}

Response Schema

200 OK

{
"result": 0,
"status": {
"success": true,
"message": ""
},
"data": {
"trackers": [
{
"driver": "apidemo_newuser_9",
"trackingInfo": [
{
"trackerId": "mydevice@apidemo_newuser_9",
"lat": 18.4585507,
"lng": 75.4128607,
"ts": 1790131380,
"speed": 0,
"heading": 0,
"device_status": 2,
"session": "1790131313",
"employee_username": "apidemo_newuser_9",
"employee_organization_id": 1,
"employee_team_id": 2,
"employee_type_id": 0,
"received": 1790132970,
"employee_full_name": "Demo User 9",
"meta_event": "",
"meta": "{\"sourceType\":\"api\",\"accuracy\":1217.35,\"battery\":\"86%\",\"networkType\":\"Mobile\"}",
"address": "",
"action_code": "off_duty",
"typeCode": "DUTY",
"event_ts": 0,
"motionActivity": 0,
"employee_status": 3,
"employee_meta": "{\"employee_code\": null, \"employee_dob\": \"1995-04-17T00:00:00\", \"employee_email\": \"[email protected]\", \"employee_guid\": \"6ab33224bba47a219f950da5\", \"employee_phone\": \"919800000009\", \"employee_reporting_manager\": \"apidemo_sovereignsolutions\", \"employee_role\": \"Worker\", \"employee_vehicle_id\": null, \"hierarchyPath\": \"/demo/sovereignsolutions\"}",
"meta_tracking": "{\"sourceType\":\"api\",\"accuracy\":1217.35,\"battery\":\"86%\",\"networkType\":\"Mobile\"}",
"employee_image": ""
}
],
"latest_events": {
"DUTY": {
"action_code": "off_duty",
"typeCode": "DUTY",
"event_ts": 0,
"meta_event": "",
"address": ""
}
},
"latest_duty_event": {
"action_code": "off_duty",
"typeCode": "DUTY",
"event_ts": 0,
"meta_event": "",
"address": ""
},
"employee_image": ""
}
],
"total": 1,
"counters": {
"employee_username": {
"apidemo_newuser_9": 1
},
"device_status": {
"2": 1
},
"action_code": {
"off_duty": 1
}
}
}
}
FieldTypeDescription
resultintegerStatus of the call. 0 means it succeeded.
statusobject
status.successbooleantrue when the call succeeded.
status.messagestring
dataobject
data.trackersarrayOne entry per employee with a known position.
data.trackers[]object
data.trackers[].driverstringUsername of the employee.
data.trackers[].trackingInfoarray
data.trackers[].trackingInfo[]object
data.trackers[].trackingInfo[].trackerIdstringDevice the position came from.
data.trackers[].trackingInfo[].latnumberLatitude of the latest fix.
data.trackers[].trackingInfo[].lngnumberLongitude of the latest fix.
data.trackers[].trackingInfo[].tsintegerTime of the latest fix, Unix epoch seconds.
data.trackers[].trackingInfo[].speedinteger
data.trackers[].trackingInfo[].headinginteger
data.trackers[].trackingInfo[].device_statusinteger
data.trackers[].trackingInfo[].sessionstring
data.trackers[].trackingInfo[].employee_usernamestring
data.trackers[].trackingInfo[].employee_organization_idinteger
data.trackers[].trackingInfo[].employee_team_idinteger
data.trackers[].trackingInfo[].employee_type_idinteger
data.trackers[].trackingInfo[].receivedintegerWhen the platform received the fix, Unix epoch seconds.
data.trackers[].trackingInfo[].employee_full_namestring
data.trackers[].trackingInfo[].meta_eventstring
data.trackers[].trackingInfo[].metastringDevice metadata sent with the point, as a JSON-encoded string.
data.trackers[].trackingInfo[].addressstring
data.trackers[].trackingInfo[].action_codestring
data.trackers[].trackingInfo[].typeCodestring
data.trackers[].trackingInfo[].event_tsinteger
data.trackers[].trackingInfo[].motionActivityinteger
data.trackers[].trackingInfo[].employee_statusintegerEmployee lifecycle state as a numeric code: 1 New, 2 Inactive, 3 Active, 4 Disable.
data.trackers[].trackingInfo[].employee_metastringEmployee profile fields as a JSON-encoded string.
data.trackers[].trackingInfo[].meta_trackingstringDevice metadata sent with the point, as a JSON-encoded string.
data.trackers[].trackingInfo[].employee_imagestring
data.trackers[].latest_eventsobjectMost recent event per event type, keyed by type code.
data.trackers[].latest_events.DUTYobject
data.trackers[].latest_events.DUTY.action_codestring
data.trackers[].latest_events.DUTY.typeCodestring
data.trackers[].latest_events.DUTY.event_tsinteger
data.trackers[].latest_events.DUTY.meta_eventstring
data.trackers[].latest_events.DUTY.addressstring
data.trackers[].latest_duty_eventobjectMost recent duty event (on_duty / off_duty).
data.trackers[].latest_duty_event.action_codestring
data.trackers[].latest_duty_event.typeCodestring
data.trackers[].latest_duty_event.event_tsinteger
data.trackers[].latest_duty_event.meta_eventstring
data.trackers[].latest_duty_event.addressstring
data.trackers[].employee_imagestring
data.totalintegerTotal number of trackers matching the request.
data.countersobjectCounts of the returned trackers, grouped by username, device status and duty action.
data.counters.employee_usernameobject
data.counters.employee_username.apidemo_newuser_9integer
data.counters.device_statusobject
data.counters.device_status.2integer
data.counters.action_codeobject
data.counters.action_code.off_dutyinteger

Get historical track​

POST /tracking/history

Request Parameters

ParameterInTypeRequiredDescriptionExample
trackerIdbodystringNoDevice to read the track for.
frombodystringNoStart of the range, Unix epoch seconds, sent as a string.
tobodystringNoEnd of the range, Unix epoch seconds, sent as a string.

Request body

{
"trackerId": "mydevice@your_username",
"from": "1788022800",
"to": "1791651599"
}

Response Schema

200 OK

{
"result": 0,
"status": {
"success": true,
"message": ""
},
"data": [
{
"deviceStatus": {
"value": 1,
"iconColor": "#7CB342",
"session": "1790131313"
},
"data": [
[
75.4128607,
18.4585507
]
],
"times": [
1790131380
],
"metaData": [
{
"speed": 0,
"heading": 0
}
]
}
]
}
FieldTypeDescription
resultintegerStatus of the call. 0 means it succeeded.
statusobject
status.successbooleantrue when the call succeeded.
status.messagestring
dataarrayOne entry per tracking session in the range.
data[]object
data[].deviceStatusobject
data[].deviceStatus.valueinteger
data[].deviceStatus.iconColorstring
data[].deviceStatus.sessionstringSession the points belong to.
data[].dataarrayTrack points as [longitude, latitude] pairs, in time order.
data[].data[]array
data[].data[][]number
data[].timesarrayUnix epoch seconds for each point, same order as data.
data[].times[]integer
data[].metaDataarraySpeed and heading for each point, same order as data.
data[].metaData[]object
data[].metaData[].speedinteger
data[].metaData[].headinginteger

Coordinates in data are GeoJSON order - longitude first.

Example​

curl -X POST '$BASE_URL/tracking/push?api-key=$API_KEY' \
-H 'Authorization: Bearer $TOKEN' \
-H 'Content-Type: application/json' \
-d '[{"driver": "your_username", "trackerId": "mydevice@your_username", "heading": 0, "lat": 18.4585507, "lng": 75.4128607, "motionActivity": 0, "session": 1790131313, "speed": 0, "timestamp": 1790131380, "jobStatus": 2, "meta": "{\"sourceType\":\"api\",\"accuracy\":1217.35,\"battery\":\"86%\",\"networkType\":\"Mobile\"}"}]'