All Lume data is transmitted to the secure Virridy cloud platform and accessible via the web dashboard at thelume.ai/dashboard.
Programmatic Data API (Customer API)
Beyond the dashboard, every Lume deployment can be accessed programmatically through the Virridy Lume Customer API — a small, read-only HTTPS API that returns the same server-computed E. coli probability, estimated CFU concentration, turbidity, and water temperature the dashboard renders, as JSON you can ingest into your own systems (SCADA, data warehouses, public dashboards, alerting).
| Property | Value |
| Base URL | https://lume-inventory-api.evan-thomas-3d8.workers.dev |
| Format | JSON, UTF-8. Times are ISO-8601 UTC. |
| Auth header | Authorization: Bearer lume_sk_<your-token> |
| Scope | Each token authenticates as one organization and returns data only for that organization's deployed sensors. Out-of-scope barcodes return 404. |
Getting a token: Your Virridy contact issues an API token for your account — a 72-character string beginning lume_sk_ — and delivers it through a secure channel. Treat it like a password: anyone holding it can pull your sensor data. If a token is lost or shared by mistake, email info@virridy.com and we'll revoke it within minutes and issue a fresh one.
Endpoint 1 — Latest reading per sensor
GET/api/v1/customer/sensors
Returns the most recent server-computed prediction for every deployed sensor in your account.
curl https://lume-inventory-api.evan-thomas-3d8.workers.dev/api/v1/customer/sensors \
-H "Authorization: Bearer lume_sk_..."
Example response
{
"model_version": "2026-04-27-turbidity-relative",
"customer": "Your Organization",
"generated_at": "2026-06-03T14:00:00.000Z",
"sensors": [
{
"barcode": "50001",
"use_case": "Main St. Bridge",
"last_seen": "2026-06-03T13:45:00.000Z",
"ecoli_prob": 0.21,
"ecoli_cfu": 18.4,
"turbidity_ntu_rel": 6.2,
"temp_c": 19.4,
"tlf_mon2": 1320,
"tlf_stlf20": 8.44,
"voltage_v": 12.6
}
]
}
Endpoint 2 — Historical timeseries for one sensor
GET/api/v1/customer/sensors/<barcode>/timeseries
Returns a time-series of 15-minute-binned predictions for one sensor.
| Param | Default | Range | Meaning |
| hours | 24 | 1–168 | Window length in hours, ending at “now”. |
curl "https://lume-inventory-api.evan-thomas-3d8.workers.dev/api/v1/customer/sensors/50001/timeseries?hours=24" \
-H "Authorization: Bearer lume_sk_..."
Example response
{
"model_version": "2026-04-27-turbidity-relative",
"customer": "Your Organization",
"barcode": "50001",
"hours": 24,
"generated_at": "2026-06-03T14:00:00.000Z",
"readings": [
{
"time": "2026-06-03T13:30:00.000Z",
"ecoli_prob": 0.18,
"ecoli_cfu": 15.1,
"turbidity_ntu_rel": 5.9,
"temp_c": 19.2,
"tlf_mon2": 1280,
"tlf_stlf20": 8.39
}
]
}
Readings are sorted ascending by time. Bins with no valid reading in that interval are absent, not null — the response is sparse. Requesting a barcode that isn't on your account returns 404.
Response fields
| Field | Meaning |
| model_version | The TLF→E. coli prediction model version. Changes when we retrain; changes are announced in advance. |
| customer | Your organization name on record. |
| generated_at | Server time the response was assembled. |
| barcode | Sensor barcode (string). |
| use_case | Free-text label for the deployment site, set by Virridy admins. |
| last_seen | Time of the most recent reading used in the prediction. null if the sensor hasn't reported recently. |
| ecoli_prob | Probability the E. coli concentration exceeds 10 CFU/100 mL, in [0, 1]. |
| ecoli_cfu | Estimated E. coli concentration in CFU/100 mL, floored at 0.1. |
| turbidity_ntu_rel | Sensor-relative turbidity (NTU). Not cross-comparable between sensors — see note below. |
| temp_c | Water temperature in °C. |
| tlf_mon2 | Raw tryptophan-like fluorescence signal (mon2 channel, arbitrary units). Not corrected for temperature. |
| tlf_stlf20 | Temperature-corrected tryptophan-like fluorescence: the S-TLF slope of the full sweep, normalized to 20 °C on the sensor's own quench coefficient and adjusted for logged window cleanings. The TLF value the E. coli model uses. Turbidity enters the model separately (turbidity_ntu_rel). |
| voltage_v | Sensor battery voltage (V), when available. |
Sensors that haven't reported within the last 3 hours show null for prediction fields. We never extrapolate — apply your own staleness rules using last_seen.
Errors
| Status | Body | Meaning |
| 401 | {"error":"Unauthorized"} | Missing or invalid token, or the token was revoked. |
| 404 | {"error":"Barcode not found in your account"} | The barcode in the URL isn't a deployed sensor in your account. |
| 502 | {"error":"Upstream error: ..."} | Transient — the underlying sensor data pipeline returned an error. Retry. |
Model versioning
Every response carries a model_version identifier. When we retrain the regression (new coefficients, new turbidity calibration, etc.), this string changes. Significant model changes are announced in advance — log model_version alongside the readings you persist so future analyses know which model produced them.
About the turbidity field
turbidity_ntu_rel is sensor-relative: the slope of the bench-calibrated NTU regression is applied on top of each sensor's own clean-water baseline (10th-percentile in-water signal). It tracks relative turbidity changes for that specific sensor over time, but values are not directly comparable between sensors. A future model release will move to absolute NTU once enough multi-sensor formazin calibrations are in hand; the field name will not change.
Rate limits & cadence
No hard rate limits today. Reasonable polling cadences:
/api/v1/customer/sensors — once every 15 minutes, matching the sensor reporting cadence. Polling more often returns the same data.
/api/v1/customer/sensors/<barcode>/timeseries — once per hour or less; pull a 24-hour or 7-day window as needed.
Support
Email info@virridy.com with the model_version (or the request time if no response came back), the request URL (minus your token), the full response body, and a short note on what you expected versus what you got.