Skip to content

Run scripts unattended

Run a Python script on a schedule, on a server or in CI, with no browser to sign in. The example exports the past week's activities to a parquet file every night.

1. Get the tokens

On your own machine, sign in once:

from sweatstack import Client

client = Client()
client.authenticate()
print(client.api_key.get_secret_value())
print(client.refresh_token.get_secret_value())

The access token expires. The refresh token lets the SDK get a new access token without a browser. Treat both like passwords.

For a script that only ever reads your own data, an API key from Settings → API works too.

2. Set them in the environment

On the server, set both as environment variables, for example as secrets in your CI or scheduler:

export SWEATSTACK_API_KEY="..."
export SWEATSTACK_REFRESH_TOKEN="..."

Don't call authenticate() in the script. Client() reads both variables. When the access token expires, the SDK refreshes it and saves the new one in the user's data directory.

3. Write the script

from datetime import date, timedelta

from sweatstack import Client

with Client(max_retries=4) as client:
    week = client.activities.list(start=date.today() - timedelta(days=7), output="polars")
week.write_parquet(f"activities-{date.today()}.parquet")

max_retries=4 makes the script retry a failed read four times instead of twice, so a short outage doesn't fail the nightly run. See Errors.

4. Fail loudly

A scheduled script has no one watching it. Exit with a clear message and a non-zero status when the sign-in fails:

import sys

from sweatstack import Client, SweatStackAuthError, SweatStackTokenRefreshError

try:
    with Client() as client:
        print(client.whoami().display_name)
except (SweatStackAuthError, SweatStackTokenRefreshError) as error:
    sys.exit(f"SweatStack sign-in failed, get new tokens: {error}")

SweatStackTokenRefreshError means the refresh token is expired or revoked. Repeat step 1 to get new tokens.

Complete script
# /// script
# requires-python = ">=3.10"
# dependencies = ["sweatstack[polars]"]
# ///
import sys
from datetime import date, timedelta

from sweatstack import Client, SweatStackAuthError, SweatStackTokenRefreshError

try:
    with Client(max_retries=4) as client:
        week = client.activities.list(
            start=date.today() - timedelta(days=7), output="polars"
        )
except (SweatStackAuthError, SweatStackTokenRefreshError) as error:
    sys.exit(f"SweatStack sign-in failed, get new tokens: {error}")

week.write_parquet(f"activities-{date.today()}.parquet")
print(f"Exported {week.height} activities")

Run it with uv run export.py.