Content types
| Usage | Content-Type |
|---|
| Token endpoints | application/x-www-form-urlencoded |
POST /api/v2/vehicles/list | application/json (body { "vehicleIds": [ ... ] }) |
GET and PUT routes | No body; parameters in path or query string |
| Successful JSON responses | application/json; charset=utf-8 |
Token routes in the API Reference: Dashboard user token · 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).
All V2 responses include an API version header:
| Header | Type | Description |
|---|
X-API-Version | integer | Always 2 on V2 responses. Absent on V1 responses. |
Rate limiting
Rate limiting is enforced on all V2 endpoints (/api/v2/...). V1 endpoints are not rate-limited.
Every V2 response includes the following headers:
| Header | Type | Description |
|---|
X-RateLimit-Limit | integer | Maximum requests allowed per window for your token |
X-RateLimit-Remaining | integer | Requests remaining in the current window |
X-RateLimit-Reset | integer | Unix timestamp when the current window resets |
X-RateLimit-Policy | string | Which rate limit window you’re currently closest to hitting — one of second, minute, hour, or day |
When a rate limit is exceeded, the server returns 429 Too Many Requests with an additional header:
| Header | Type | Description |
|---|
Retry-After | integer | Seconds to wait before retrying |
Retry strategy: Wait the full Retry-After value before retrying. If you receive consecutive 429s, double the wait interval on each attempt up to a maximum of 60 seconds.
Limits:
| Scope | Limit |
|---|
| Global per token (V2) | 60 requests / 60 seconds (sliding window) |
Most V2 list endpoints accept page (1-based, default 1) and pageSize (default 50) query parameters and return:
{
"items": [...],
"currentPage": 1,
"numberOfPages": 7,
"totalResults": 342,
"lastResultIndex": 24
}
| Field | Type | Description |
|---|
items | array | Records on the current page |
currentPage | integer | Current page number (1-based) |
numberOfPages | integer | Total number of pages |
totalResults | integer | Total records across all pages |
lastResultIndex | integer | Index of the last record on this page |
GET /api/v2/battery-health uses different envelope fields: page, pageSize, and totalCount (instead of currentPage, numberOfPages, totalResults). It also omits lastResultIndex.
V2 pagination parameters:
| Parameter | Default | Max | Description |
|---|
page | 1 | — | Page to retrieve (1-based) |
pageSize | 50 | 500 | Records per page |
Legacy V1 pagination parameters (applies only to POST /api/GetCompanyVehiclesBatteryHealth):
| Parameter | Default | Max | Description |
|---|
pageNumber | 1 | — | Page to retrieve (1-based) |
resultsPerPage | 25 | 500 | Records per page |
searchString | — | — | Optional filter (name or IMEI) |
Endpoints with pagination support:
| Endpoint | Parameters |
|---|
POST /api/GetCompanyVehiclesBatteryHealth (V1 legacy) | pageNumber / resultsPerPage |
GET /api/v2/companies/{id}/vehicles/last-position | page / pageSize |
GET /api/v2/companies/{id}/alert-records | page / pageSize |
GET /api/v2/companies/{id}/alerts | page / pageSize |
POST /api/v2/vehicles/list | page / pageSize |
GET /api/v2/vehicles/{id}/positions | page / pageSize |
GET /api/v2/battery-health | page / pageSize — returns totalCount instead of totalResults |
| All other V2 list endpoints | page / pageSize |
Date and time
- JSON serialization for
DateTime uses custom converters (SimplifiedDateTimeConverter) that write without fractional seconds, e.g. 2026-04-07T14:32:00.
- Request parameters: pass ISO-like strings that
DateTime.Parse accepts (e.g. 2026-04-07T14:32:00 or 2026-04-07T14:32:00Z depending on client). Many actions call DateTime.SpecifyKind(..., Utc) in code—treat replay and position ranges as UTC unless the controller comment says otherwise.
TimeSpan in JSON (e.g. trip Duration) uses standard .NET format.
Legacy JSON field names
Several DTOs use legacy spellings for backward compatibility. These apply to V2 endpoints that share the same PositionDto shape as V1:
UserTimeFormated, LastMovementTimeUserFormated (missing “t” in “Formatted”)
ConnectionStrengh (missing “g” in “Strength”)
Clients should bind to these exact names.
The last-time-online DTOs (LastTimeOnlineDto, DeviceLastTimeOnlineDto) use lastTimeOnlineUtc and secondsAgo — both in standard camelCase. There is no PascalCase legacy variant.
Null vs omitted
- Nullable reference fields may be omitted or null depending on serializer defaults; treat absent optional fields as null.
- For
PositionDto, isOnline is only set in snapshot-based paths; record-based paths may omit or default it.