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

# The Exporter API

> The Flask API on the track machine: the endpoints the dashboard calls, the DAQ upload endpoint, and how its logs are split.

The exporter API is the track machine's local service layer, and it serves two unrelated jobs from one process. It answers the [dashboard](/software/developer/estate/systems/telemetry/dashboard) by querying InfluxDB and writing STL exports, and it receives DAQ run uploads from the karts and puts them in S3.

It listens on **port 5432**, and the same code is also built as the conversion Lambda that runs in AWS. See [Deployment and the Pipeline](/software/developer/estate/systems/telemetry/deployment#the-images).

## The Two Jobs

| Job | Who calls it | What it touches |
| - | - | - |
| Charging monitoring and export | The dashboard | InfluxDB, the local export folder, S3, Teams |
| DAQ run upload | A DAQ unit on a kart | The local file system, then S3 |

> [!NOTE]
>
> These share nothing but the process. A fault in one does not imply a fault in the other, and the logs are split on that basis.

## Endpoints

### Live Monitoring

| Endpoint | Purpose |
| - | - |
| `GET /karts/connected` | Kart IDs seen in a window, filtered by ID prefix. The dashboard asks for the last 60 seconds |
| `GET /karts/<kart>/stats` | Battery stats for one kart, looking back 15 minutes from the given end time |
| `GET /karts/<kart>/connection-stats` | Connection health over a window, aggregated into buckets, one minute by default |
| `GET /regions` | The machine's own region, and every region it knows about |

The stats endpoint returns more than readings. Alongside `batteryStats` it reports `secondsSinceValid`, a `dataIsShownButOutdated` flag raised when the newest reading is more than **2 minutes** old, and `errorGettingStats` when the query itself failed.

> [!NOTE]
>
> Those three fields are why the dashboard can distinguish stale data from absent data from a broken query, which are three different faults. The 15 minute window and the 2 minute threshold are hard coded rather than configurable.

> [!WARNING]
>
> `/regions` raises rather than defaulting if `HUB_REGIONS` or `HUB_REGION` are not set on the container, so a machine missing either fails the region selector outright. That is deliberate: guessing a region would file exports in the wrong place.

### Charging Export

| Endpoint | Purpose |
| - | - |
| `GET /karts` | Karts that were charging in a window. The end defaults to a day after the start |
| `POST /karts/export/path` | Resolves the destination folder from region, event type and timezone. Event type defaults to `Test` |
| `GET /karts/<kart>/runs` | Charging sessions merged into runs, dropping runs shorter than a threshold, five minutes by default |
| `POST /karts/<kart>/runs` | Exports one run or stint, querying InfluxDB and writing the STL files |
| `POST /sync/s3` | Uploads the local export folder to S3 and posts a Teams notification |

That sequence is the export, and [Charging Export](/software/developer/estate/systems/telemetry/charging-export) covers what each step does to the data.

> [!WARNING]
>
> The export endpoint returns HTTP 500 with an `error` field when a run fails to export, and the failure is logged to the charging log. A part-completed export leaves whatever it already wrote in the local folder, so a retry can find files from the previous attempt already present.

### DAQ Upload

| Endpoint | Purpose |
| - | - |
| `POST /upload` | Receives a completed run from a DAQ unit, zips it with its logging table and metadata, works out the run number, and uploads to S3 |

The kart identifies itself with a `kart-id` request header. See [Upload and Conversion](/software/developer/estate/systems/telemetry/daq-pipeline#uploading-from-the-track) for the zip contents, the metadata fields and the run numbering.

## How The Logs Are Split

Requests are logged on the way in and the way out, into three files under the container's `logs/` folder:

| Log | Contains |
| - | - |
| `exporter_api.log` | Everything, and also written to stdout so it appears in `docker logs` |
| `daq_exporter_api.log` | Only requests carrying a `kart-id` header, prefixed with that kart |
| `charging_exporter_api.log` | Everything else |

> [!WARNING]
>
> The split is decided purely by the presence of the `kart-id` header, not by the path. So anything that reaches the API without that header lands in the charging log regardless of what it was doing. When you cannot find a request, check the combined log rather than assuming it never arrived.

All three sync to S3 with the rest of the track logs every 30 minutes. See [Track Operations](/software/developer/estate/systems/telemetry/track-operations#what-happens-while-it-runs).

## Key Files

All paths are under `telemetry/telemetry-api/` in [can-wifi](https://github.com/Smedley-Group-Advanced-Technology/can-wifi).

| File | Role |
| - | - |
| `src/api.py` | Every endpoint, and the request logging split |
| `src/services/influxdb_service.py` | The InfluxDB queries |
| `src/services/kart_data_manager_service.py` | Which karts were charging or connected |
| `src/services/charging_run_service.py` | Merging sessions into runs, battery and connection stats |
| `src/services/stint_service.py` | Dividing a run into stints |
| `src/services/telemetry_exporter_service.py` | The export itself, and the destination path |
| `src/services/uploading/` | Run numbering, zip assembly, and the fallback dump of a failed upload |
| `src/services/teams_notification_service.py` | The notification posted on a sync |
| `src/lambda_function.py` | The same code's other life, as the conversion Lambda |

## Related Documentation

| Page | Relevance |
| - | - |
| [Telemetry Dashboard](/software/developer/estate/systems/telemetry/dashboard) | The client for most of these endpoints |
| [Charging Export](/software/developer/estate/systems/telemetry/charging-export) | The export sequence in order |
| [Upload and Conversion](/software/developer/estate/systems/telemetry/daq-pipeline) | What happens after `/upload` |
| [Track Operations](/software/developer/estate/systems/telemetry/track-operations) | The container, its logs and its folders |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.