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

# Battery health

> Paginated battery health scores and diagnostics for vehicles in the authenticated company.

### Overview

<Note>Battery health is available for select customers only.</Note>

Returns battery health data for all vehicles in the caller's company. Includes a fleet-level summary and per-vehicle scores, voltage history, diagnostic badges, and component scores. Supports filtering, searching, sorting, and pagination.

<Note>The V1 version of this endpoint is [Battery health](/v1/api-reference/post-get-company-vehicles-battery-health). V2 returns a richer response with scores, bands, 90-day voltage trends, and diagnostic badges instead of ML predictions.</Note>

<Note>**Rate limit:** 4 req/s · 30/min · 600/hr · 14,400/day</Note>

### Endpoint

`GET /v2/api/battery-health`

### Query parameters

<ParamField query="pageNumber" type="integer" default="1">
  Page number (1-based).
</ParamField>

<ParamField query="pageSize" type="integer" default="25">
  Number of results per page.
</ParamField>

<ParamField query="searchText" type="string">
  Optional filter by vehicle name.
</ParamField>

<ParamField query="filter" type="integer" default="0">
  Band filter: `0` = All, `1` = Critical, `2` = Warning, `3` = Healthy.
</ParamField>

<ParamField query="sortBy" type="integer" default="0">
  Sort field (maps to `BatteryHealthSortField` enum values).
</ParamField>

<ParamField query="sortDescending" type="boolean" default="false">
  When `true`, sort results in descending order.
</ParamField>

<ParamField query="badgeFilter" type="integer" default="0">
  Badge filter (maps to `BatteryHealthBadge` enum values; `0` = None / no filter).
</ParamField>

### Response

**200 OK** — `BatteryHealthResponse`

#### Top-level fields

| Field      | Type    | Description                                                              |
| ---------- | ------- | ------------------------------------------------------------------------ |
| summary    | object  | Fleet-level counts and average score — see below                         |
| items      | array   | Paged list of per-vehicle battery health objects — see below             |
| totalCount | integer | Total number of vehicles matching the current filter (before pagination) |
| page       | integer | Current page number (1-based)                                            |
| pageSize   | integer | Number of items per page                                                 |

#### `summary`

| Field         | Type    | Description                                                                 |
| ------------- | ------- | --------------------------------------------------------------------------- |
| healthyCount  | integer | Number of vehicles with a Healthy or Excellent band                         |
| warningCount  | integer | Number of vehicles with a Fair or Poor band                                 |
| criticalCount | integer | Number of vehicles with a Critical band                                     |
| avgScore      | number  | Average health score across all company vehicles for the latest scored date |

#### `items[]`

Each element in `items` represents one vehicle.

| Field             | Type            | Description                                                                                                                         |
| ----------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| vehicleId         | integer         | Vehicle identifier                                                                                                                  |
| vehicleName       | string          | Vehicle display name                                                                                                                |
| imei              | string \| null  | Tracker IMEI when known                                                                                                             |
| currentVoltage    | number \| null  | Latest observed battery voltage (V)                                                                                                 |
| isEngineOn        | boolean \| null | Whether the engine was running at the time of the reading                                                                           |
| band              | string \| null  | Health band classification: `"Critical"`, `"Warning"`, or `"Healthy"`                                                               |
| badges            | string\[]       | Active badge identifiers for this vehicle (e.g. `"DEEP_DISCHARGE"`, `"ALTERNATOR"`, `"PARK_DRAIN"`). Used for display and filtering |
| voltageHistory    | object          | Peak, average, and lowest voltage over rolling windows — see below                                                                  |
| forecast          | object          | Short-term battery forecast — see below                                                                                             |
| statuses          | array           | Active diagnostic statuses — see below                                                                                              |
| healthScore       | object          | Overall health score and component breakdown — see below                                                                            |
| last90DaysVoltage | array           | Daily average voltage readings for the last 90 days — see below                                                                     |
| daysToReplace     | integer \| null | Days until battery replacement is recommended; `null` when not applicable or unavailable                                            |
| scoredOn          | string \| null  | ISO 8601 date the health score was last calculated (e.g. `"2026-06-07"`)                                                            |
| restScore         | integer \| null | Raw resting-voltage component score                                                                                                 |
| crankScore        | integer \| null | Raw cranking-voltage component score                                                                                                |
| trendScore        | integer \| null | Raw voltage-trend component score                                                                                                   |
| decayScore        | integer \| null | Raw parked-decay component score                                                                                                    |
| chargeScore       | integer \| null | Raw charge-acceptance component score                                                                                               |
| latestScore       | integer \| null | Raw latest-reading component score                                                                                                  |

#### `voltageHistory`

Contains four rolling-window objects keyed `7day`, `30day`, `60day`, and `90day`. Each has the same shape:

| Field   | Type           | Description                                |
| ------- | -------------- | ------------------------------------------ |
| peak    | number \| null | Highest voltage observed in the window (V) |
| average | number \| null | Mean voltage in the window (V)             |
| lowest  | number \| null | Lowest voltage observed in the window (V)  |

#### `forecast`

| Field   | Type            | Description                                                   |
| ------- | --------------- | ------------------------------------------------------------- |
| score   | integer \| null | Composite health score (0–100); `null` when not yet available |
| comment | string          | Human-readable forecast summary based on `daysToReplace`      |

#### `statuses[]`

| Field         | Type           | Description                                    |
| ------------- | -------------- | ---------------------------------------------- |
| id            | string \| null | Stable status identifier (e.g. `"PARK_DRAIN"`) |
| label         | string \| null | Short display label (e.g. `"Park Drain"`)      |
| comment       | string \| null | Human-readable description of the condition    |
| signalPattern | string \| null | Signal rule that triggered this status         |

#### `healthScore`

| Field       | Type            | Description                                              |
| ----------- | --------------- | -------------------------------------------------------- |
| score       | integer \| null | Overall health score (0–100); `null` when not computable |
| maxScore    | integer         | Maximum possible score (always `100`)                    |
| comment     | string          | Human-readable summary of the overall score              |
| composition | object          | Per-component ratings — see below                        |

#### `healthScore.composition`

Each field is a string rating derived from the component's raw score relative to its maximum.

| Field            | Type   | Values                                                       |
| ---------------- | ------ | ------------------------------------------------------------ |
| restingVoltage   | string | `"Good"`, `"Fair"`, `"Bad"`, or `"grey"` (insufficient data) |
| crankVoltage     | string | `"Good"`, `"Fair"`, `"Bad"`, or `"grey"`                     |
| trend            | string | `"Good"`, `"Fair"`, `"Bad"`, or `"grey"`                     |
| decay            | string | `"Good"`, `"Fair"`, `"Bad"`, or `"grey"`                     |
| chargeAcceptance | string | `"Good"`, `"Fair"`, `"Bad"`, or `"grey"`                     |
| latestReading    | string | `"Good"`, `"Fair"`, `"Bad"`, or `"grey"`                     |

#### `last90DaysVoltage[]`

Daily voltage readings for trend visualisation. May be an empty array if data is unavailable.

| Field   | Type           | Description                                       |
| ------- | -------------- | ------------------------------------------------- |
| date    | string         | ISO 8601 calendar date (e.g. `"2026-06-07"`)      |
| voltage | number \| null | Average external battery voltage for that day (V) |

### Example response

```json theme={null}
{
  "summary": {
    "healthyCount": 18,
    "warningCount": 4,
    "criticalCount": 1,
    "avgScore": 76
  },
  "items": [
    {
      "vehicleId": 1042,
      "vehicleName": "Fleet Van 03",
      "imei": "357647131029365",
      "currentVoltage": 12.9,
      "isEngineOn": false,
      "band": "Healthy",
      "badges": [],
      "voltageHistory": {
        "7day": { "peak": 14.2, "average": 13.78, "lowest": 12.56 },
        "30day": { "peak": 14.2, "average": 13.78, "lowest": 12.56 },
        "60day": { "peak": 14.2, "average": 13.72, "lowest": 12.41 },
        "90day": { "peak": 14.3, "average": 13.69, "lowest": 12.21 }
      },
      "forecast": {
        "score": 84,
        "comment": "AI analysis predicts optimal performance and voltage retention for the next 90+ days."
      },
      "statuses": [],
      "healthScore": {
        "score": 84,
        "maxScore": 100,
        "comment": "Battery health is good.",
        "composition": {
          "restingVoltage": "Good",
          "crankVoltage": "Good",
          "trend": "Fair",
          "decay": "Good",
          "chargeAcceptance": "Good",
          "latestReading": "Good"
        }
      },
      "last90DaysVoltage": [
        { "date": "2026-06-07", "voltage": 12.9 },
        { "date": "2026-06-06", "voltage": 13.1 }
      ],
      "daysToReplace": 120,
      "scoredOn": "2026-06-07",
      "restScore": 18,
      "crankScore": 15,
      "trendScore": 10,
      "decayScore": 13,
      "chargeScore": 14,
      "latestScore": 14
    }
  ],
  "totalCount": 23,
  "page": 1,
  "pageSize": 25
}
```

### Error responses

| Status | Meaning                                           |
| ------ | ------------------------------------------------- |
| 401    | Missing or invalid token                          |
| 403    | Token does not have access to battery health data |

```bash theme={null}
curl "https://api.telemax.com.au/v2/api/battery-health?pageNumber=1&pageSize=25&filter=0" \
  -H "Authorization: Bearer <token>"
```


## OpenAPI

````yaml openapi.yaml GET /v2/api/battery-health
openapi: 3.1.0
info:
  title: Telemax External API (V2)
  version: '2026-04-14'
  description: >
    Telemax External API — fleet telemetry, vehicle commands, and integrations.


    **Base URL:** `https://api.telemax.com.au`


    **Authentication:** All routes require a `Bearer` JWT unless marked
    `[AllowAnonymous]`.

    Obtain tokens via `POST /v2/api/authentication/token/api-key`.


    **RESTful architecture:** V2 uses standard HTTP methods (GET, POST, PUT,
    DELETE) with

    resource-based routes and consistent pagination via `page` and `pageSize`
    query parameters.


    **API versioning:** All responses will include an `X-API-Version` header
    containing the

    date-based version string (e.g. `2026-04-28`). See the
    [Changelog](/v2/changelog) for

    the deprecation policy and version history.


    For full documentation including error handling, pagination, and known field
    quirks, see [docs.telemax.com.au](https://docs.telemax.com.au).
servers:
  - url: https://api.telemax.com.au
security:
  - BearerAuth: []
paths:
  /v2/api/battery-health:
    get:
      summary: Battery health (V2)
      description: >-
        Paginated battery health scores and diagnostics for vehicles in the
        authenticated company.
      parameters:
        - name: pageNumber
          in: query
          schema:
            type: integer
            default: 1
          description: >-
            Page number to retrieve (1-based). Returned as `page` in the
            response.
        - name: pageSize
          in: query
          schema:
            type: integer
            default: 25
          description: Number of results per page. Returned as `pageSize` in the response.
        - name: searchText
          in: query
          schema:
            type: string
          description: Optional filter by vehicle name.
        - name: filter
          in: query
          schema:
            type: integer
            default: 0
          description: 'Band filter: 0 = All, 1 = Critical, 2 = Warning, 3 = Healthy.'
        - name: sortBy
          in: query
          schema:
            type: integer
            default: 0
          description: Sort field (maps to BatteryHealthSortField enum values).
        - name: sortDescending
          in: query
          schema:
            type: boolean
            default: false
          description: When true, sort results in descending order.
        - name: badgeFilter
          in: query
          schema:
            type: integer
            default: 0
          description: >-
            Badge filter (maps to BatteryHealthBadge enum values; 0 = None / no
            filter).
      responses:
        '200':
          description: >-
            **200 OK** — Returns a fleet-level summary and a paginated list of
            per-vehicle battery health records, including voltage history,
            health scores, badge signals, and replacement forecasts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  summary:
                    type: object
                    description: >-
                      Fleet-level battery health counts and average score across
                      all vehicles.
                    properties:
                      healthyCount:
                        type: integer
                        description: Number of vehicles in the Healthy band.
                      warningCount:
                        type: integer
                        description: Number of vehicles in the Warning or Fair band.
                      criticalCount:
                        type: integer
                        description: Number of vehicles in the Critical band.
                      avgScore:
                        type: number
                        description: >-
                          Average health score (0–100) across all scored
                          vehicles.
                  items:
                    type: array
                    description: Paginated list of per-vehicle battery health records.
                    items:
                      type: object
                      properties:
                        vehicleId:
                          type: integer
                          description: Unique vehicle (device) ID.
                        vehicleName:
                          type: string
                          description: Display name of the vehicle.
                        imei:
                          type: string
                          description: IMEI of the GPS device fitted to the vehicle.
                        currentVoltage:
                          type: number
                          description: Most recent battery voltage reading in volts.
                        isEngineOn:
                          type: boolean
                          description: >-
                            Whether the engine was running at the time of the
                            latest reading.
                        voltageHistory:
                          type: object
                          description: >-
                            Peak, average, and lowest voltage readings over
                            rolling windows.
                          properties:
                            7day:
                              type: object
                              description: Voltage statistics over the last 7 days.
                              properties:
                                peak:
                                  type: number
                                  description: Highest recorded voltage in the window.
                                average:
                                  type: number
                                  description: >-
                                    Mean voltage across all readings in the
                                    window.
                                lowest:
                                  type: number
                                  description: Lowest recorded voltage in the window.
                            30day:
                              type: object
                              description: Voltage statistics over the last 30 days.
                              properties:
                                peak:
                                  type: number
                                average:
                                  type: number
                                lowest:
                                  type: number
                            60day:
                              type: object
                              description: Voltage statistics over the last 60 days.
                              properties:
                                peak:
                                  type: number
                                average:
                                  type: number
                                lowest:
                                  type: number
                            90day:
                              type: object
                              description: Voltage statistics over the last 90 days.
                              properties:
                                peak:
                                  type: number
                                average:
                                  type: number
                                lowest:
                                  type: number
                        forecast:
                          type: object
                          description: >-
                            AI-generated 90-day performance forecast for the
                            battery.
                          properties:
                            score:
                              type: integer
                              description: Forecast confidence score (0–100).
                            comment:
                              type: string
                              description: Human-readable forecast summary.
                        statuses:
                          type: array
                          description: >-
                            Active diagnostic badges detected for this vehicle's
                            battery.
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                                enum:
                                  - HEALTHY
                                  - PARK_DRAIN
                                  - TREND_DOWN
                                description: >-
                                  Badge identifier. `HEALTHY` — all signals
                                  within normal range. `PARK_DRAIN` — battery
                                  losing charge faster than normal while parked.
                                  `TREND_DOWN` — resting voltage has been slowly
                                  declining over the past 30 days.
                              label:
                                type: string
                                description: Display label for the badge.
                              comment:
                                type: string
                                description: >-
                                  Plain-language explanation of the detected
                                  condition.
                              signalPattern:
                                type: string
                                description: >-
                                  Technical signal rule that triggered this
                                  badge.
                        healthScore:
                          type: object
                          description: >-
                            Composite battery health score broken down by signal
                            category.
                          properties:
                            score:
                              type: integer
                              description: >-
                                Overall health score (0–100). Higher is
                                healthier.
                            maxScore:
                              type: integer
                              description: Maximum possible score (always 100).
                            comment:
                              type: string
                              description: Plain-language summary of the health score.
                            composition:
                              type: object
                              description: >-
                                Per-signal rating contributing to the overall
                                score. Values are `Good`, `Fair`, or `Bad`.
                              properties:
                                restingVoltage:
                                  type: string
                                  description: Rating for resting (parked) voltage level.
                                crankVoltage:
                                  type: string
                                  description: >-
                                    Rating for voltage during engine crank
                                    events.
                                trend:
                                  type: string
                                  description: >-
                                    Rating for the 30-day voltage trend
                                    direction.
                                decay:
                                  type: string
                                  description: Rating for voltage decay rate while parked.
                                chargeAcceptance:
                                  type: string
                                  description: >-
                                    Rating for how well the battery accepts
                                    charge.
                                latestReading:
                                  type: string
                                  description: >-
                                    Rating based on the most recent voltage
                                    reading.
                        last90DaysVoltage:
                          type: array
                          description: >-
                            Daily average voltage readings over the last 90
                            days. Dates with no data are omitted.
                          items:
                            type: object
                            properties:
                              date:
                                type: string
                                format: date
                                description: Date of the reading (YYYY-MM-DD).
                              voltage:
                                type: number
                                description: Average voltage for that day in volts.
                        band:
                          type: string
                          enum:
                            - Critical
                            - Warning
                            - Fair
                            - Healthy
                          description: Overall health band derived from the health score.
                        restScore:
                          type: integer
                          description: >-
                            Sub-score for resting voltage (contributes to
                            `healthScore`).
                        crankScore:
                          type: integer
                          description: Sub-score for crank voltage behaviour.
                        trendScore:
                          type: integer
                          description: Sub-score for the 30-day voltage trend.
                        decayScore:
                          type: integer
                          description: Sub-score for voltage decay rate while parked.
                        chargeScore:
                          type: integer
                          description: Sub-score for charge acceptance.
                        latestScore:
                          type: integer
                          description: Sub-score based on the most recent voltage reading.
                        daysToReplace:
                          type: integer
                          description: >-
                            Estimated number of days until the battery should be
                            replaced, based on current trends.
                        scoredOn:
                          type: string
                          format: date
                          description: >-
                            Date the health score was last calculated
                            (YYYY-MM-DD).
                        badges:
                          type: array
                          description: >-
                            List of active badge IDs for quick filtering.
                            Mirrors `statuses[].id`.
                          items:
                            type: string
                            enum:
                              - HEALTHY
                              - PARK_DRAIN
                              - TREND_DOWN
                  totalCount:
                    type: integer
                    description: >-
                      Total number of vehicles with battery health data (across
                      all pages).
                  page:
                    type: integer
                    description: Current page number (1-based).
                  pageSize:
                    type: integer
                    description: Number of results returned per page.
              example:
                summary:
                  healthyCount: 0
                  warningCount: 1
                  criticalCount: 1
                  avgScore: 58.5
                items:
                  - vehicleId: 24381
                    vehicleName: Teltonika Test Device A
                    imei: '865124071644076'
                    currentVoltage: 12.31
                    isEngineOn: false
                    voltageHistory:
                      7day:
                        peak: 12.31
                        average: 12.25
                        lowest: 11.92
                      30day:
                        peak: 12.72
                        average: 11.47
                        lowest: 2.11
                      60day:
                        peak: 12.72
                        average: 11.62
                        lowest: 2.11
                      90day:
                        peak: 12.72
                        average: 11.62
                        lowest: 2.11
                    forecast:
                      score: 41
                      comment: >-
                        AI analysis predicts optimal performance for the next
                        90+ days.
                    statuses:
                      - id: HEALTHY
                        label: Healthy
                        comment: All signals within normal range.
                        signalPattern: No other badges firing
                    healthScore:
                      score: 41
                      maxScore: 100
                      comment: All signals within normal range.
                      composition:
                        restingVoltage: Bad
                        crankVoltage: Bad
                        trend: Fair
                        decay: Fair
                        chargeAcceptance: Fair
                        latestReading: Fair
                    last90DaysVoltage:
                      - date: '2026-03-27'
                        voltage: 12.31
                      - date: '2026-03-28'
                        voltage: 12.31
                    band: Critical
                    restScore: 10
                    crankScore: 8
                    trendScore: 6
                    decayScore: 7
                    chargeScore: 5
                    latestScore: 5
                    daysToReplace: 90
                    scoredOn: '2026-05-27'
                    badges:
                      - HEALTHY
                totalCount: 2
                page: 1
                pageSize: 25
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  responses:
    Unauthorized:
      description: >
        **401 Unauthorized** — JWT is missing, expired, or malformed.

        The JWT bearer middleware rejects the request before it reaches the
        controller.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            type: AUTHENTICATION
            code: INVALID_CREDENTIALS
            description: The provided API key is invalid or does not exist.
            requestId: 0HNLTALNU4DCO:00000004
            docUrl: https://docs.telemax.com.au/errors/invalid-credentials
    Forbidden:
      description: >
        **403 Forbidden** — Token is valid but the caller does not have access
        to the requested company or vehicle.

        Tokens issued for one company cannot access resources scoped to a
        different company in the hierarchy.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            type: AUTHORIZATION
            code: INVALID_SCOPE
            description: >-
              The provided token does not have permission to access this
              resource.
            requestId: 50e5c5f7-ccae-4ab6-b070-56d6645ceb1e
            docUrl: https://docs.telemax.com.au/errors/invalid-scope
    TooManyRequests:
      description: >
        **429 Too Many Requests** — Rate limit exceeded. Check the Retry-After
        header for the number of seconds to wait before retrying.

        Use exponential backoff: wait Retry-After seconds, then double the
        interval on each subsequent 429.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            type: RATE_LIMIT
            code: RATE_LIMIT_EXCEEDED
            description: Too many requests. Please slow down.
            requestId: req_6d2f8b4a
            docUrl: https://docs.telemax.com.au/errors/rate-limit-exceeded
    InternalServerError:
      description: >
        **500 Internal Server Error** — An unexpected error occurred. Include
        the requestId when contacting support.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            type: SERVER_ERROR
            code: INTERNAL_SERVER_ERROR
            description: An unexpected error occurred. Please try again later.
            requestId: req_1e5a3c7d
            docUrl: https://docs.telemax.com.au/errors/internal-server-error
  headers:
    X-RateLimit-Limit:
      description: >-
        Maximum number of requests allowed per minute for this token. **Not yet
        active** — this header will be added once the rate-limit middleware is
        deployed. See the [Changelog](/v2/changelog) for the rollout date.
      schema:
        type: integer
        example: 60
    X-RateLimit-Remaining:
      description: >-
        Number of requests remaining in the current rate limit window. **Not yet
        active** — see `X-RateLimit-Limit`.
      schema:
        type: integer
        example: 47
    X-RateLimit-Reset:
      description: >-
        Unix timestamp (seconds) at which the current rate limit window resets.
        **Not yet active** — see `X-RateLimit-Limit`.
      schema:
        type: integer
        example: 1746000060
    Retry-After:
      description: Number of seconds to wait before retrying after a 429 response.
      schema:
        type: integer
        example: 30
  schemas:
    ApiError:
      type: object
      description: Standard error response returned by all API endpoints.
      properties:
        type:
          type: string
          description: >-
            Error category (e.g. AUTHENTICATION, AUTHORIZATION, RESOURCE,
            VALIDATION_ERROR, RATE_LIMIT, SERVER_ERROR).
          example: AUTHENTICATION
        code:
          type: string
          description: Machine-readable error code within the category.
          example: INVALID_CREDENTIALS
        description:
          type: string
          description: Human-readable explanation of the error and how to resolve it.
          example: The provided API key is invalid or does not exist.
        requestId:
          type: string
          description: Unique request identifier for support correlation.
          example: req_7f3a2b1c
        docUrl:
          type: string
          format: uri
          description: Link to the relevant error documentation page.
          example: https://docs.telemax.com.au/errors/invalid-credentials
      required:
        - type
        - code
        - description
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        JWT Bearer token obtained from `POST
        /v2/api/authentication/token/api-key`.


        **Lifetime:** ~24 hours (86,399 seconds). Cache the token and reuse it.
        Re-authenticate 5 minutes before expiry.


        **Scoping:** API key tokens are scoped to the company the key belongs to
        and may restrict

        access to a vehicle allowlist and/or action set (see token claims).


        **No refresh endpoint** — re-authenticate with your API key when the
        token expires.

````