# Measurement Data

> Stations using MQTT? See [MQTT Integration](https://www.testlabiq.com/en/help/mqtt-integration) — same
> payload format, same API key, just a different transport.

## What is it?

The "Measurement data" section on a test case's detail page shows **all**
measurements for that test case in a single view — as tiles (last value per
channel, min/max) or as a chart with limit comparison. That holds regardless
of how the values arrived: automatically via REST/MQTT while the test ran, as
a CSV upload during execution, or uploaded afterward as a CSV once the test
case is already completed. There is only this one source — no separate "live"
area and no separate "attachment with chart preview" anymore.

While the test case is running, the view updates continuously (green "Live"
dot). After completion (Passed, Failed, Skipped, Cancelled), the same section
shows the full, read-only history — including any values uploaded afterward.

The "Chart" button lets you adjust the display (chart type, trendline,
legend, axes …). With only one measurement channel the legend is hidden by
default, since it wouldn't distinguish anything — it can be switched on
anytime via the same button.

## How measurements get in

1. **REST API:** `POST /api/v1/measurements` with the station's API key in the
   `x-api-key` header (alternatively `Authorization: Bearer <key>`):

   ```json
   {
     "sequenceItemId": "<uuid>",
     "measurements": [
       { "timestamp": "2026-06-30T08:00:00Z", "channelName": "U_in",
         "value": 12.1, "unit": "V", "quality": 100, "metadata": {} }
     ]
   }
   ```

   `sequenceItemId` is shown on the test case's detail page in the
   "Measurement data" section (copy button next to the ID). `quality` (0–100)
   and `metadata` are optional. Without `sequenceItemId`, values are
   attributed to the station only (e.g. warming up/calibrating before a test
   case is running) and appear only on that station's page.
2. **MQTT** — see [MQTT Integration](https://www.testlabiq.com/en/help/mqtt-integration).
3. **CSV upload during execution:** in the "Test case executed" dialog or
   directly in the measurement data section via "Upload" — flows into the
   live view immediately, same as REST/MQTT, and feeds the automatic limit
   evaluation. Required columns: `timestamp, channelName, value, unit`
   (optional `quality`), at most 10,000 rows per file.
4. **CSV upload after completion:** the same "Upload" button in the
   measurement data section, now against an already-completed test case — the
   values are added directly to that test case's permanent record (see below)
   and appear in the chart immediately. No row limit like the running-test
   path, only the general 50 MB file size limit.
5. **Status starts automatically:** A still-pending test case switches to "In
   progress" automatically when the first measurements arrive.

## How long is measurement data kept?

Recent values live in the fast live database, but only for a rolling window
of roughly 24 hours. Older values are automatically moved (hourly, in the
background) into a permanent CSV record per test case — nothing is lost, and
this is invisible in the view: the measurement data section always shows the
complete, correct history, whether a value just arrived live or was archived
weeks ago. This also holds for test cases that run longer than the rolling
window (e.g. multi-day climate tests) — the export keeps running independent
of the test case's status, not only once it completes.

When a test case completes, any remaining values are archived immediately;
from then on there is exactly one permanent measurement-data record for that
test case, kept for traceability (ISO 17025) as well.

## Setting station status via API

In addition to measurements, a station can also set its own status via the
same API key:

`PATCH /api/v1/stations/me/status` with the same header and body
`{ "status": "IN_USE" }`. Valid values: `AVAILABLE`, `IN_USE`, `MAINTENANCE`,
`OUT_OF_SERVICE`. There is deliberately no `id` in the body — the API key
determines the station, so it can only change itself.

The test case status itself does **not** need to be set separately: it
automatically switches to "In progress" when the first measurements arrive.
The actual verdict (Passed/Failed) remains a deliberate manual step in the UI
("test case was performed").

## Common issues

- **Error response format.** `{ "error": { "code": "...", "message": "..." }
  }` — the `code` (`PERMISSION_DENIED`, `VALIDATION`, `NOT_FOUND`,
  `LIMIT_EXCEEDED`) is stable and can be evaluated programmatically.
- **`401 — API key missing / invalid.`** Get the current key from the station
  page.
- **`404 — Sequence item not found.`** The `sequenceItemId` doesn't belong to
  this station's organization.
- **`413 — Payload too large.`** A request may be at most 5 MB; split large
  volumes across multiple requests.
- **Duplicate values are skipped** — not an error, protects against duplicate
  sends (the response lists them under `duplicates`).
- **"This path is only for completed test cases."** The upload button in the
  measurement data section decides automatically: if the test case is still
  running, use the live upload instead (no station assigned yet? assign one
  to the test case first).
- **CSV row errors.** The message names the row and reason (unreadable date,
  non-numeric value, missing required column). Semicolon/decimal comma is
  detected automatically.
- **Checking afterwards what arrived:** Every delivery (REST, MQTT, or CSV
  upload during execution) is in the delivery log — retrievable via
  `GET /api/v1/ingestion/deliveries` (see [REST API](https://www.testlabiq.com/en/help/rest-api)) or by
  asking the support assistant. An upload after completion doesn't go through
  this log (it never writes to the live table) — it's traceable through the
  normal audit log instead.

---

Source: https://www.testlabiq.com/en/help/measurement-data
