Traces¶
client.traces: /api/v1/traces/...
Bases: Resource
Traces: point measurements such as lactate, RPE or heart rate, optionally linked to a test.
app_metadata
cached
property
¶
This app's metadata on traces: set(trace_id, data=...) and delete.
create(*, timestamp, lactate=None, rpe=None, notes=None, power=None, speed=None, heart_rate=None, vo2=None, tags=None, sport=None, test_id=None)
¶
Creates a trace.
Endpoint: POST /api/v1/traces/
Parameters:
-
timestamp(datetime) –When the measurement was taken. Must be timezone-aware; the offset is stored alongside the instant.
-
lactate(float | None, default:None) –Blood lactate, mmol/L.
-
rpe(int | None, default:None) –Rating of perceived exertion.
-
notes(str | None, default:None) –Free text.
-
power(int | None, default:None) –Power, W.
-
speed(float | None, default:None) –Speed, m/s.
-
heart_rate(int | None, default:None) –Heart rate, bpm.
-
vo2(float | None, default:None) –Oxygen uptake (VO2).
-
tags(list[str] | None, default:None) –Tags.
-
sport(Sport | str | None, default:None) –The sport.
-
test_id(str | None, default:None) –Link the trace to this test. A linked trace belongs to the test whatever its timestamp.
Returns:
-
TraceDetails(TraceDetails) –The created trace.
Raises:
-
ValueError–If
timestampis timezone-naive. -
SweatStackNotFoundError–If
test_iddoes not exist. -
SweatStackAPIError–If the API request fails for any other reason.
Examples:
from datetime import datetime, timezone
from sweatstack import Client
client = Client()
trace = client.traces.create(
timestamp=datetime.now(timezone.utc), lactate=2.1, heart_rate=152, tags=["lactate"]
)
delete(trace_id)
¶
Deletes a trace.
Endpoint: DELETE /api/v1/traces/{trace_id}
Parameters:
-
trace_id(str) –The trace's ID.
Raises:
-
SweatStackNotFoundError–If the trace does not exist.
-
SweatStackAPIError–If the API request fails for any other reason.
Examples:
from sweatstack import Client
client = Client()
client.traces.delete("trace_123")
list(*, start=None, end=None, sport=None, tags=None, limit=100, offset=0, output=None)
¶
list(*, start: date | None = None, end: date | None = None, sport: SportParam | None = None, tags: TagParam | None = None, limit: int = 100, offset: int = 0, output: Literal['models'] | None = None) -> builtins.list[TraceDetails]
list(*, start: date | None = None, end: date | None = None, sport: SportParam | None = None, tags: TagParam | None = None, limit: int = 100, offset: int = 0, output: Literal['pandas']) -> pd.DataFrame
list(*, start: date | None = None, end: date | None = None, sport: SportParam | None = None, tags: TagParam | None = None, limit: int = 100, offset: int = 0, output: Literal['polars']) -> pl.DataFrame
list(*, start: date | None = None, end: date | None = None, sport: SportParam | None = None, tags: TagParam | None = None, limit: int = 100, offset: int = 0, output: Literal['arrow']) -> pa.Table
Lists traces, newest first.
Endpoint: GET /api/v1/traces/
Parameters:
-
start(date | None, default:None) –Only traces on or after this date.
-
end(date | None, default:None) –Only traces on or before this date.
-
sport(SportParam | None, default:None) –One sport or a list; a trace matches any of them.
-
tags(TagParam | None, default:None) –One tag or a list; a trace must have all of them.
-
limit(int, default:100) –How many traces to return. The client pages through the endpoint until it has this many or there are no more.
-
offset(int, default:0) –How many of the newest matching traces to skip.
-
output(ListOutput | None, default:None) –"models"(default),"pandas","polars"or"arrow".
Returns:
-
list[TraceDetails] | DataFrame | DataFrame | Table–TraceDetails objects, or a frame with one row per trace.
Raises:
-
SweatStackAPIError–If the API request fails.
Examples:
from sweatstack import Client
client = Client()
traces = client.traces.list(tags="lactate", limit=50)
replace(trace_id, *, timestamp, lactate=None, rpe=None, notes=None, power=None, speed=None, heart_rate=None, vo2=None, tags=None, sport=None, test_id=None)
¶
Replaces every field of a trace.
Endpoint: PUT /api/v1/traces/{trace_id}
Every field you leave out is cleared, including test_id: a trace linked to a
test is unlinked unless you pass its test_id again. To change one field, retrieve
the trace first and pass all its fields back.
Parameters:
-
trace_id(str) –The trace's ID.
-
timestamp(datetime) –When the measurement was taken. Must be timezone-aware.
-
lactate(float | None, default:None) –Blood lactate, mmol/L.
-
rpe(int | None, default:None) –Rating of perceived exertion.
-
notes(str | None, default:None) –Free text.
-
power(int | None, default:None) –Power, W.
-
speed(float | None, default:None) –Speed, m/s.
-
heart_rate(int | None, default:None) –Heart rate, bpm.
-
vo2(float | None, default:None) –Oxygen uptake (VO2).
-
tags(list[str] | None, default:None) –Tags.
-
sport(Sport | str | None, default:None) –The sport.
-
test_id(str | None, default:None) –The test this trace is linked to;
Noneunlinks it.
Raises:
-
ValueError–If
timestampis timezone-naive. -
SweatStackNotFoundError–If the trace or
test_iddoes not exist. -
SweatStackAPIError–If the API request fails for any other reason.
Examples:
from datetime import datetime, timezone
from sweatstack import Client
client = Client()
client.traces.replace(
"trace_123", timestamp=datetime(2026, 5, 1, 9, 30, tzinfo=timezone.utc), lactate=2.4
)
Bases: _RecordAppMetadata
This app's metadata on traces. Requires an app token.
delete(trace_id)
¶
Deletes this app's metadata from a trace.
Endpoint: DELETE /api/v1/traces/{trace_id}/app-metadata
Parameters:
-
trace_id(str) –The trace's ID.
Raises:
-
SweatStackAuthError–If the client does not hold an app token (403).
-
SweatStackAPIError–If the API request fails for any other reason.
Examples:
from sweatstack import Client
client = Client(api_key="app-user-token")
client.traces.app_metadata.delete("trace_123")
set(trace_id, *, data)
¶
Replaces this app's metadata on a trace.
Endpoint: PUT /api/v1/traces/{trace_id}/app-metadata
The whole dict is replaced; there is no merge. Each app sees only its own metadata,
and it appears as app_metadata on the trace when read with an app token.
Parameters:
-
trace_id(str) –The trace's ID.
-
data(dict[str, Any]) –Any JSON-serialisable dict, at most 1 KB and 32 levels deep.
Raises:
-
SweatStackAuthError–If the client does not hold an app token (403). A personal token, from
authenticate()or an API key, never qualifies. -
SweatStackBadRequestError–If
datais too large (413) or too deep (422). -
SweatStackNotFoundError–If the trace does not exist.
-
SweatStackAPIError–If the API request fails for any other reason.
Examples:
from sweatstack import Client
client = Client(api_key="app-user-token") # e.g. user.client in FastAPI
client.traces.app_metadata.set("trace_123", data={"reviewed": True})