Skip to content

Tests

client.tests: /api/v1/tests/...

Bases: Resource

Tests: fitness assessments with structured results (thresholds, VO2max, critical power).

app_metadata cached property

This app's metadata on tests: set(test_id, data=...) and delete.

create(*, sport, start, title=None, end=None, results=None, tags=None)

Creates a test.

Endpoint: POST /api/v1/tests/

Parameters:

  • sport (Sport | str) –

    The sport.

  • start (datetime) –

    When the test started. Must be timezone-aware.

  • title (str | None, default: None ) –

    A title.

  • end (datetime | None, default: None ) –

    When the test ended. Must be timezone-aware. Defaults to start plus three hours, server-side.

  • results (TestResults | None, default: None ) –

    Structured results: thresholds, capacities, and so on.

  • tags (list[str] | None, default: None ) –

    Tags.

Returns:

Raises:

  • ValueError –

    If start or end is timezone-naive.

  • SweatStackAPIError –

    If the API request fails.

Examples:

from datetime import datetime, timezone

from sweatstack import Client, Marker, TestResults

client = Client()
test = client.tests.create(
    sport="cycling",
    start=datetime(2026, 5, 1, 9, 0, tzinfo=timezone.utc),
    title="Lactate step test",
    results=TestResults(lt1=Marker(power=210), lt2=Marker(power=285)),
)

delete(test_id)

Deletes a test.

Endpoint: DELETE /api/v1/tests/{test_id}

Parameters:

  • test_id (str) –

    The test's ID.

Raises:

Examples:

from sweatstack import Client

client = Client()
client.tests.delete("test_123")

list(*, start=None, end=None, sport=None, tags=None, created_by=None, limit=50, offset=0, output=None)

list(*, start: date | None = None, end: date | None = None, sport: SportParam | None = None, tags: TagParam | None = None, created_by: str | None = None, limit: int = 50, offset: int = 0, output: Literal['models'] | None = None) -> builtins.list[TestSummary]
list(*, start: date | None = None, end: date | None = None, sport: SportParam | None = None, tags: TagParam | None = None, created_by: str | None = None, limit: int = 50, 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, created_by: str | None = None, limit: int = 50, 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, created_by: str | None = None, limit: int = 50, offset: int = 0, output: Literal['arrow']) -> pa.Table

Lists tests, newest first.

Endpoint: GET /api/v1/tests/

Parameters:

  • start (date | None, default: None ) –

    Only tests on or after this date.

  • end (date | None, default: None ) –

    Only tests on or before this date.

  • sport (SportParam | None, default: None ) –

    One sport or a list; a test matches any of them.

  • tags (TagParam | None, default: None ) –

    One tag or a list; a test must have all of them.

  • created_by (str | None, default: None ) –

    Only tests created by this app (client ID).

  • limit (int, default: 50 ) –

    How many tests 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 tests to skip.

  • output (ListOutput | None, default: None ) –

    "models" (default), "pandas", "polars" or "arrow".

Returns:

  • list[TestSummary] | DataFrame | DataFrame | Table –

    TestSummary objects, or a frame with one row per test; results is flattened to

  • list[TestSummary] | DataFrame | DataFrame | Table –

    dotted columns in pandas and a struct in Polars and Arrow.

Raises:

Examples:

from sweatstack import Client

client = Client()
tests = client.tests.list(sport="cycling", output="pandas")

replace(test_id, *, sport, start, title=None, end=None, results=None, tags=None)

Replaces every field of a test.

Endpoint: PUT /api/v1/tests/{test_id}

Every field you leave out is cleared. To change one field, retrieve the test first and pass all its fields back.

Parameters:

  • test_id (str) –

    The test's ID.

  • sport (Sport | str) –

    The sport.

  • start (datetime) –

    When the test started. Must be timezone-aware.

  • title (str | None, default: None ) –

    A title.

  • end (datetime | None, default: None ) –

    When the test ended. Must be timezone-aware.

  • results (TestResults | None, default: None ) –

    Structured results.

  • tags (list[str] | None, default: None ) –

    Tags.

Raises:

Examples:

from sweatstack import Client

client = Client()
test = client.tests.retrieve("test_123")
client.tests.replace(
    test.id, sport=test.sport, start=test.start, end=test.end,
    title="Renamed", results=test.results, tags=test.tags,
)

retrieve(test_id, *, trace_resolution=TraceResolution.auto)

Retrieves a test with its traces and the activities it overlaps.

Endpoint: GET /api/v1/tests/{test_id}

Parameters:

  • test_id (str) –

    The test's ID.

  • trace_resolution (TraceResolution | str, default: auto ) –

    Which traces the traces list holds (activities is always matched by time overlap). Sent as the traces query parameter.

    • "auto" (default): traces inside the test's time range, plus traces linked to this test, minus traces linked to another test.
    • "linked": only traces linked to this test, whatever their timestamp.

Returns:

  • TestDetails ( TestDetails ) –

    The test with its traces and activities.

Raises:

Examples:

from sweatstack import Client

client = Client()
test = client.tests.retrieve("test_123", trace_resolution="linked")
print([trace.lactate for trace in test.traces])

Bases: _RecordAppMetadata

This app's metadata on tests. Requires an app token.

delete(test_id)

Deletes this app's metadata from a test.

Endpoint: DELETE /api/v1/tests/{test_id}/app-metadata

Parameters:

  • test_id (str) –

    The test's ID.

Raises:

Examples:

from sweatstack import Client

client = Client(api_key="app-user-token")
client.tests.app_metadata.delete("test_123")

set(test_id, *, data)

Replaces this app's metadata on a test.

Endpoint: PUT /api/v1/tests/{test_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 test when read with an app token.

Parameters:

  • test_id (str) –

    The test's ID.

  • data (dict[str, Any]) –

    Any JSON-serialisable dict, at most 1 KB and 32 levels deep.

Raises:

Examples:

from sweatstack import Client

client = Client(api_key="app-user-token")  # e.g. user.client in FastAPI
client.tests.app_metadata.set("test_123", data={"reviewed": True})