Content types
Token route in the API Reference: API key token.
Response envelope
Successful operations return the payload directly (200 OK with DTO JSON). There is no global wrapper like { "data": ... }.
Service-layer results use ApiResult / ApiResult<T> internally; controllers map them to HTTP status codes and return either the DTO or the error object as the JSON body (see Errors).
Response headers
Rate limiting
Limits apply per API key and per endpoint, in four fixed windows: per second, per minute, per hour and per day. A request must be within all four. A request over any limit is rejected with429, not queued. Every V2 endpoint is rate-limited except the token endpoint, POST /v2/api/authentication/token/api-key. Every response that reaches the endpoint counts against the limit, including 403, 404, 409, 422 and 500; follow-up pages in a pagination session do not.
Responses from a rate-limited endpoint carry these headers once the token has authenticated:
They are absent on a
401 for a missing, invalid or expired bearer token, on a 404 with code: PATH_NOT_FOUND, on a 405, on the token endpoint, and on follow-up pages served free by a pagination session.
When a limit is exceeded, the server returns 429 Too Many Requests with an additional header:
Retry strategy: wait the full
Retry-After value before retrying. That always clears the window that was exhausted; if another window is also used up, the retry gets a new 429 with that window’s Retry-After, so wait again.
Limits:
Four single-vehicle endpoints have a single tight window that is the limit in practice:
GET /v2/api/vehicles/info allows 60 per minute; GET /v2/api/vehicles/{id}/last-online allows 2 per second; GET /v2/api/vehicles/{id}/last-position allows 60 per day; GET /v2/api/vehicles/{id}/positions allows 60 per hour. The count is per API key across all vehicles, not per vehicle.
¹ This endpoint returns the last known position for every vehicle mapped to the company. Recommended usage is approximately one poll cycle every 5 minutes. A cycle costs at least one counted request per company — follow-up pages are free in a pagination session — so spread the requests: if the calls are sent together, the per-second (4) and per-minute (20) limits are the first ones hit. Polling more frequently than this is unlikely to yield new data and burns through the budget quickly.
² Nearest vehicles loads every vehicle mapped to the company on each request; Fleet last positions loads one page at a time. The rate limit applies per request regardless of fleet size.
³ Accepts a maximum of 50 vehicle IDs per request.
Pagination
Paginated V2 endpoints acceptpage (1-based, default 1) and pageSize (default 50) query parameters and return:
GET /v2/api/battery-health pages differently: it takes pageNumber (default 1) and pageSize (default 25), and returns page, pageSize and totalCount instead of currentPage, numberOfPages and totalResults. It has no lastResultIndex.
Legacy V1 pagination parameters (applies only to
POST /api/GetCompanyVehiclesBatteryHealth):
Endpoints with pagination support:
Pagination sessions
Follow-up pages of the V2 endpoints listed above, except battery health, can be fetched without counting against the rate limit:- Request a page with an explicit
pageparameter. This first request counts as usual. A200response carries anX-Session-Tokenheader. - Request further pages of the same endpoint and query (
pageandpageSizemay change) and send the latest token back in anX-Session-Tokenrequest header. Each page you have not fetched yet in this session is free and has noX-RateLimit-*headers.
- Always send the token from the most recent response.
- Fetching a page again counts against the limit and starts a new session.
- A token works only with the API key that created it, and expires after 10 minutes without use.
- Changing any other query parameter starts a new session.
GET /v2/api/battery-healthdoes not take part (it pages withpageNumber).
Date and time
- JSON serialization for
DateTimeuses custom converters (SimplifiedDateTimeConverter) that write without fractional seconds, e.g.2026-04-07T14:32:00. - Request parameters: pass ISO-like strings that
DateTime.Parseaccepts (e.g.2026-04-07T14:32:00or2026-04-07T14:32:00Zdepending on client). Many actions callDateTime.SpecifyKind(..., Utc)in code—treat replay and position ranges as UTC unless the controller comment says otherwise. TimeSpanvalues in JSON (e.g. tripduration) use the .NET format[d.]hh:mm:ss[.fffffff], not ISO 8601.
Null vs omitted
- Fields are always present. A field with no value is written as
null, not omitted. - For
PositionDto,isOnlineis always present. Single-vehicle Last position never sets it, so it is alwaysfalsethere.