> ## Documentation Index
> Fetch the complete documentation index at: https://docs.telemax.com.au/llms.txt
> Use this file to discover all available pages before exploring further.

# Request & response format

> JSON conventions, query vs body, datetime serialization, and pagination for the V1 External API.

## Content types

| Usage                                                 | Content-Type                                          |
| ----------------------------------------------------- | ----------------------------------------------------- |
| Token endpoints                                       | `application/x-www-form-urlencoded`                   |
| [`POST /api/devices`](/v1/api-reference/post-devices) | `application/json` (body `{ "vehicleIds": [ ... ] }`) |
| Most other `POST /api/*` routes                       | No body; parameters in **query string** or **route**  |
| Successful JSON responses                             | `application/json; charset=utf-8`                     |

Token routes in the API Reference: [Dashboard user token](/v1/api-reference/post-authentication-token-user) · [API key token](/v1/api-reference/post-authentication-token-api-key).

## 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](/v1/errors)).

<Note>
  V1 endpoints are **not rate-limited**. There are no `X-RateLimit-*` response headers on V1 responses. Rate limiting applies only to V2 (`/api/v2/...`) endpoints.
</Note>

***

## Pagination

Only one V1 endpoint is paginated: `POST /api/GetCompanyVehiclesBatteryHealth`. All other V1 endpoints return their full result set.

The paginated response envelope is:

```json theme={null}
{
  "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 | Zero-based index of the last record on this page |

**Pagination parameters:**

| Parameter        | Default | Max   | Description                    |
| ---------------- | ------- | ----- | ------------------------------ |
| `pageNumber`     | `1`     | —     | Page to retrieve (1-based)     |
| `resultsPerPage` | `25`    | `500` | Records per page               |
| `searchString`   | —       | —     | Optional filter (name or IMEI) |

## 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:

* `UserTimeFormated`, `LastMovementTimeUserFormated` (missing "t" in "Formatted")
* `ConnectionStrengh` (missing "g" in "Strength")
* `LastTimeUTC` / `secondsAgo` on last-time-online DTOs

Clients should bind to these exact names.

## 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.
