Skip to main content

Kilometers Report

Distance traveled, fuel consumption, and cost metrics for your fleet over a given period.

GET/apidev/v1/reports/avl/kilometers
PermissionAPICLI_RPTAVL_KILOMETROS
Rate Limit10 req/min (sliding window)
Cache300s (5 min)
Max Range31 days

Overview​

Provides distance and consumption data for every vehicle in your fleet. Use it to audit mileage, estimate fuel costs, and track CO₂ emissions.

  • Daily breakdown — perday=true returns one row per vehicle per day
  • Driver grouping — perperson=true segments results by the assigned driver
  • Geographic subdivision — groupbygeo splits totals by state, city, or neighbourhood
  • Subtotals — subtotals=true includes summary rows

Request​

Request Headers​

Every request to a protected endpoint requires these headers:

HeaderRequiredDescription
AuthorizationYesBearer token obtained from the Login endpoint. Format: Bearer <token>
X-API-KeyYesCompany integration key provided during onboarding. Format: gtk_xxx...
tenantYesYour assigned tenant domain (default: geotareas.com) — always send your assigned tenant
Content-TypeConditionalapplication/json — required for POST and PUT requests

Query Parameters​

ParameterTypeRequiredDefaultDescription
startdatestringYes—ISO 8601 start date-time (e.g. 2026-03-01T00:00:00)
enddatestringYes—ISO 8601 end date-time. Max range 31 days from startdate
devicesstringNoAll visibleComma-separated device IDs. Max 500
limitintegerNo25Records per page (1–100)
offsetintegerNo0Records to skip
perdaybooleanNofalseGroup results by day
perpersonbooleanNofalseGroup results by assigned driver
subtotalsbooleanNofalseInclude subtotal rows
groupbygeoenumNo—Subdivide by area: state, city, or neighbourhood
subtotals=true changes how limit behaves

The subtotal and grand-total rows are appended after the page has been cut, and the result is then trimmed back to limit. So with subtotals=true the response still returns at most limit rows, but some of that budget is spent on summary rows — you get fewer detail rows than a plain page of the same size.

Summary rows are not flagged in the payload. You can only recognise them by device_name: a per-device subtotal reads "<device name> (subtotal)" and the grand total reads "Total general". If you are aggregating the data yourself, filter those rows out or you will double-count.

meta.total always counts detail rows only. For a clean paginated read, leave subtotals off and compute your own totals.

Device visibility

When devices is omitted, the report includes all devices visible to the authenticated user based on their permission scope.


Code Examples​

curl -s "https://$TENANT/apidev/v1/reports/avl/kilometers?startdate=2026-03-01T00:00:00&enddate=2026-03-15T23:59:59&limit=50&perday=true" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"

Response Fields​

FieldTypeDescription
device_namestringDisplay name of the vehicle/device
person_namestringAssigned driver name. Only populated when perperson=true
statestringState name. Only present when groupbygeo is state, city or neighbourhood
citystringCity name. Only present when groupbygeo is city or neighbourhood
neighbourhoodstringNeighbourhood name. Only present when groupbygeo=neighbourhood
datetimestring | nullDate of the record (YYYY-MM-DD). Only populated when perday=true
kmsnumberTotal kilometers traveled
temperaturenumberAverage temperature sensor 1 reading (°C). 0 if the vehicle has no sensor
fuelnumberEstimated fuel consumed (liters)
costnumberEstimated fuel cost (currency per vehicle config)
co2numberEstimated CO₂ emissions (kg)
The geo fields are omitted, not blank

state, city and neighbourhood are added to each row only when you ask for geographic grouping, and they stack up as you go deeper:

groupbygeoFields added to every row
(omitted)none
statestate
citystate, city
neighbourhoodstate, city, neighbourhood

When a field is not added, the key is absent from the object — "city" in row is false. It does not arrive as an empty string, so do not read it without checking first.

device_name, person_name and datetime behave the other way round: the key is always there, and it is perperson / perday that decide whether it carries a value.

Fuel and cost values

fuel, cost, and co2 are calculated using the fuel consumption rate and fuel price configured in each vehicle's settings. If not configured, these fields return 0.

Example Response​

{
"success": true,
"data": [
{
"device_name": "Truck A-101",
"person_name": "",
"datetime": "2026-03-01",
"kms": 267.7,
"temperature": 22.3,
"fuel": 32.12,
"cost": 48.18,
"co2": 83.54
},
{
"device_name": "Van B-205",
"person_name": "",
"datetime": "2026-03-01",
"kms": 142.3,
"temperature": 4.1,
"fuel": 11.38,
"cost": 17.07,
"co2": 29.57
}
],
"meta": {
"total": 84,
"limit": 50,
"offset": 0
}
}

With perperson=true​

When driver grouping is enabled, person_name is populated and multiple rows may appear for the same device if drivers changed during the period:

{
"device_name": "Truck A-101",
"person_name": "Carlos Martinez",
"datetime": "2026-03-01",
"kms": 180.5,
"temperature": 22.3,
"fuel": 21.66,
"cost": 32.49,
"co2": 56.32
}

With groupbygeo=state​

Geographic grouping adds the levels up to the one you asked for. With state, the row gains state — and no city or neighbourhood keys at all:

{
"device_name": "Truck A-101",
"person_name": "",
"state": "Montevideo",
"datetime": null,
"kms": 180.5,
"temperature": 0,
"fuel": 21.66,
"cost": 32.49,
"co2": 56.32
}

With groupbygeo=neighbourhood​

The deepest level brings the three keys together, one row per neighbourhood visited:

{
"device_name": "Truck A-101",
"person_name": "",
"state": "Montevideo",
"city": "Montevideo",
"neighbourhood": "Pocitos",
"datetime": null,
"kms": 42.8,
"temperature": 0,
"fuel": 5.14,
"cost": 7.71,
"co2": 13.36
}

Errors​

CodeHTTPDescription
INVALID_DATE_RANGE400Date range exceeds the 31-day maximum, end before start, or non-ISO dates
VALIDATION_ERROR400Invalid params: missing dates, limit > 100, > 500 devices
UNAUTHORIZED401Missing, invalid, or expired tenant / Authorization / X-API-Key
FORBIDDEN403User lacks APICLI_RPTAVL_KILOMETROS permission
RATE_LIMITED429Exceeded 10 req/min
INTERNAL_ERROR500Unexpected server error