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

# Trip Replay

> Fetch trip waypoints, decode polylines, and render trips on Google Maps or Leaflet using the V2 replay endpoint.

## Overview

V2 consolidates trip replay into a single paginated endpoint. Each `TripDto` covers one continuous movement segment:

| Field                           | Description                                                            |
| ------------------------------- | ---------------------------------------------------------------------- |
| `distance`                      | Trip distance in **km**                                                |
| `duration`                      | Trip duration as `"hh:mm:ss"` (e.g. `"00:28:14"`)                      |
| `startAddress` / `endAddress`   | Reverse-geocoded start and end addresses                               |
| `startTimeUser` / `endTimeUser` | Trip start/end formatted in the user's configured timezone             |
| `encoded`                       | Google Polyline Algorithm–encoded path string                          |
| `url`                           | Ready-to-use Google Static Maps URL for a thumbnail                    |
| `points`                        | Array of waypoints with speed, direction, ignition, fuel, and odometer |

<Note>
  V2 uses a single `GET /v2/api/replay/{id}` endpoint for all replay requests. The V1 distinction between `GetReplayUserTime` and `GetReplay` (UTC vs. user time) no longer applies — V2 always returns both `timeUtc` and `timeUser` on each point.
</Note>

***

## Step 1 — Request a date range

Fetch trips for vehicle `1000` over one week. Pass `from` and `to` as ISO 8601 UTC strings:

<CodeGroup>
  ```bash cURL theme={null}
  curl -s \
    "https://api.telemax.com.au/v2/api/replay/1000?from=2025-05-01T00:00:00Z&to=2025-05-08T00:00:00Z&page=1&pageSize=20" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

  ```python Python theme={null}
  import requests

  r = requests.get(
      "https://api.telemax.com.au/v2/api/replay/1000",
      params={
          "from":     "2025-05-01T00:00:00Z",
          "to":       "2025-05-08T00:00:00Z",
          "page":     1,
          "pageSize": 20,
      },
      headers={"Authorization": "Bearer YOUR_TOKEN"},
  )
  r.raise_for_status()
  data = r.json()
  trips = data["items"]
  print(f"{len(trips)} trip(s) on page {data['currentPage']} of {data['numberOfPages']}")
  ```
</CodeGroup>

***

## Step 2 — Inspect the response

The response is a paginated envelope. Each element in `items` is a `TripDto`:

```json theme={null}
{
  "items": [
    {
      "distance": 14,
      "duration": "00:20:22",
      "startAddress": "31, Diamantina Cir, Karalee, Brisbane, Qld, AUS",
      "endAddress": "5, Gordon St, Ipswich, Brisbane, Qld, AUS",
      "startTimeUser": "05/12/2026 08:09:09",
      "endTimeUser": "05/12/2026 08:29:31",
      "encoded": "zdagDkuzc\\??z@wB~C_DRR...",
      "url": "https://maps.googleapis.com/maps/api/staticmap?...",
      "points": [
        {
          "lat": -27.536263, "lng": 152.840733,
          "timeUtc": "2026-05-12T01:09:09",
          "timeUser": "2026-05-12T08:09:09",
          "speed": 0, "direction": 260,
          "ignition": true, "odo": 47465,
          "fuelLevel": 92, "fuelVolume": null
        }
      ]
    }
  ],
  "currentPage": 1,
  "numberOfPages": 31,
  "totalResults": 31,
  "lastResultIndex": 1
}
```

**Point fields:**

| Field         | Type           | Description                             |
| ------------- | -------------- | --------------------------------------- |
| `lat` / `lng` | number         | GPS coordinates                         |
| `timeUtc`     | string         | Waypoint timestamp (UTC, no `Z` suffix) |
| `timeUser`    | string         | Waypoint timestamp in user's timezone   |
| `speed`       | number         | Speed at this point (km/h)              |
| `direction`   | number         | Heading in degrees (0–359)              |
| `ignition`    | boolean        | Ignition state at this point            |
| `odo`         | number         | Odometer reading (km)                   |
| `fuelLevel`   | integer        | Fuel level (%)                          |
| `fuelVolume`  | number \| null | Fuel volume (litres)                    |

***

## Step 3 — Decode the `encoded` polyline

The `encoded` field uses the **Google Polyline Algorithm** format, supported by all major mapping SDKs.

<CodeGroup>
  ```python Python theme={null}
  # pip install polyline
  import polyline

  def decode_trip(trip):
      coords = polyline.decode(trip["encoded"])  # list of (lat, lng) tuples
      print(f"{trip['startAddress']} → {trip['endAddress']}: {len(coords)} decoded points, "
            f"{trip['distance']} km, {trip['duration']}")
      return coords

  for trip in trips:
      coords = decode_trip(trip)
  ```

  ```javascript JavaScript theme={null}
  // npm install @mapbox/polyline
  import polyline from "@mapbox/polyline";

  for (const trip of trips) {
    const coords = polyline.decode(trip.encoded); // [[lat, lng], ...]
    console.log(
      `${trip.startAddress} → ${trip.endAddress}: ${coords.length} points, ` +
      `${trip.distance} km, ${trip.duration}`
    );
  }
  ```
</CodeGroup>

***

## Step 4 — Render on a map

<CodeGroup>
  ```javascript JavaScript (Leaflet) theme={null}
  // Assumes Leaflet map initialised as `map`
  import polyline from "@mapbox/polyline";

  for (const trip of trips) {
    const coords = polyline.decode(trip.encoded);

    // Draw the route
    L.polyline(coords, { color: "#0075FF", weight: 3 }).addTo(map);

    // Start marker
    L.marker(coords[0])
      .bindPopup(`<b>Start</b><br>${trip.startAddress}<br>${trip.startTimeUser}`)
      .addTo(map);

    // End marker
    L.marker(coords[coords.length - 1])
      .bindPopup(`<b>End</b><br>${trip.endAddress}<br>${trip.endTimeUser}`)
      .addTo(map);
  }

  // Fit map to all trips
  const allCoords = trips.flatMap(t => polyline.decode(t.encoded));
  if (allCoords.length) map.fitBounds(allCoords);
  ```
</CodeGroup>

***

## Fetching all pages

For long date ranges, iterate through all pages:

```python Python theme={null}
def fetch_all_trips(vehicle_id: int, from_dt: str, to_dt: str, token: str) -> list:
    trips = []
    page = 1
    while True:
        r = requests.get(
            f"https://api.telemax.com.au/v2/api/replay/{vehicle_id}",
            params={"from": from_dt, "to": to_dt, "page": page, "pageSize": 20},
            headers={"Authorization": f"Bearer {token}"},
        )
        r.raise_for_status()
        data = r.json()
        trips.extend(data.get("items", []))
        if page >= data.get("numberOfPages", 1):
            break
        page += 1
    return trips
```

***

## Google Static Maps thumbnail

The `url` field is a pre-built Google Static Maps URL. Use it server-side to generate a trip thumbnail without decoding the polyline:

```python Python theme={null}
import requests

for i, trip in enumerate(trips):
    thumb_url = trip["url"] + "&size=400x200&key=YOUR_GMAPS_KEY"
    img_data = requests.get(thumb_url).content
    with open(f"trip_{i}.png", "wb") as f:
        f.write(img_data)
```

***

## Gotchas

* **Distance unit:** `distance` is in **kilometres** in V2 (V1 used metres).
* **Duration format:** `duration` is `"hh:mm:ss"` in V2, not ISO 8601 `PT...` format.
* **Single endpoint:** V2 has one replay endpoint. Both UTC and user-time fields are always returned on each point — no need to choose between `GetReplay` and `GetReplayUserTime`.
* **`encoded` format:** Google Polyline Algorithm. If your decoder produces invalid coordinates, confirm the encoding with your Telemax contact.
