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 keeps the new one for the rest of the run; the variables are not changed.
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.