Skip to content

Build an app

Ship an app that lets other people sign in with SweatStack and queries the API on their behalf. About fifteen minutes with FastAPI or Streamlit. Pick your stack at the first code block. The choice carries through the page.

Using an AI coding agent?

Install the SweatStack agent skill, then paste this prompt:

Build a FastAPI app that lets users sign in with SweatStack and shows their last ten activities. Use the sweatstack[fastapi] package and the sweatstack.fastapi helpers (configure, instrument, AuthenticatedUser, OptionalUser, urls). Read SWEATSTACK_CLIENT_ID, SWEATSTACK_CLIENT_SECRET, and SWEATSTACK_SESSION_SECRET from environment variables. Set the redirect URI to http://localhost:8000/auth/sweatstack/callback. Follow https://docs.sweatstack.no/getting-started/build/.

Swap FastAPI for Streamlit if that's your stack. The agent skill knows the rest.

1. Sign up

Skip if you already have an account. Otherwise: app.sweatstack.no/register. Free, no credit card.

2. Register an app

Go to app.sweatstack.no/applications/new, name your app, and set the redirect URI to:

http://localhost:8000/auth/sweatstack/callback
http://localhost:8501

The URL in your app that handles the OAuth2 callback, for example http://localhost:3000/auth/callback.

Save the client_id and client_secret. Treat the secret like a password.

3. Install and configure

uv add 'sweatstack[fastapi]'

Put your credentials in a .env file (or your shell):

SWEATSTACK_CLIENT_ID="..."
SWEATSTACK_CLIENT_SECRET="..."
SWEATSTACK_SESSION_SECRET="..."  # see below

Generate SWEATSTACK_SESSION_SECRET once. The helper uses it to encrypt the session stored in the user's cookie:

uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
uv add 'sweatstack[streamlit]'

Put your credentials in a .env file (or your shell):

SWEATSTACK_CLIENT_ID="..."
SWEATSTACK_CLIENT_SECRET="..."

Pick the HTTP and OAuth2 libraries you (or your AI coding agent) prefer. SweatStack uses standard OAuth2 over HTTPS, so any library that implements the spec works. Put your client_id, client_secret, and redirect URI in environment variables.

4. Build it

Create app.py:

import os

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from sweatstack.fastapi import (
    configure, instrument, AuthenticatedUser, OptionalUser, urls,
)

configure(
    client_id=os.environ["SWEATSTACK_CLIENT_ID"],
    client_secret=os.environ["SWEATSTACK_CLIENT_SECRET"],
    session_secret=os.environ["SWEATSTACK_SESSION_SECRET"],
    app_url="http://localhost:8000",
)

app = FastAPI()
instrument(app)


@app.get("/")
def home(user: OptionalUser):
    if user:
        return HTMLResponse(
            f"Welcome, {user.user_id}! "
            f"<a href='/activities'>My activities</a>"
        )
    return HTMLResponse(f"<a href='{urls.login()}'>Login with SweatStack</a>")


@app.get("/activities")
def activities(user: AuthenticatedUser):
    return user.client.activities.list(limit=10)

Run it:

uv run fastapi dev app.py

Open http://localhost:8000, click Login with SweatStack, and authorize the app. SweatStack redirects you back, signed in. Click My activities to see your last ten activities as JSON.

Create app.py:

import os

import streamlit as st
from sweatstack.streamlit import StreamlitAuth

auth = StreamlitAuth(
    client_id=os.environ["SWEATSTACK_CLIENT_ID"],
    client_secret=os.environ["SWEATSTACK_CLIENT_SECRET"],
    redirect_uri="http://localhost:8501",
)

with st.sidebar:
    auth.authenticate()

if not auth.is_authenticated():
    st.write("Please log in to continue.")
    st.stop()

st.write("Welcome to SweatStack.")
activities = auth.client.activities.list(limit=10)
st.dataframe(activities)

Run it:

uv run streamlit run app.py

Open http://localhost:8501, click the login button in the sidebar, and authorize the app. Your last ten activities render in a dataframe.

SweatStack implements the OAuth2 authorization-code flow. Three calls give you a working integration. See OAuth2 & OpenID Connect for PKCE (recommended for SPAs and mobile), refresh tokens, the scope reference, and OIDC discovery.

Step A. Send the user to the authorize endpoint.

https://app.sweatstack.no/oauth/authorize
    ?response_type=code
    &client_id=YOUR_CLIENT_ID
    &redirect_uri=YOUR_REDIRECT_URI
    &scope=data:read

The user signs in, and SweatStack redirects them to your redirect_uri with a ?code=... query parameter.

Step B. Exchange the code for an access token.

curl -X POST https://app.sweatstack.no/api/v1/oauth/token \
  -d "grant_type=authorization_code" \
  -d "code=THE_CODE" \
  -d "redirect_uri=YOUR_REDIRECT_URI" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
const res = await fetch("https://app.sweatstack.no/api/v1/oauth/token", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "authorization_code",
    code: THE_CODE,
    redirect_uri: YOUR_REDIRECT_URI,
    client_id: YOUR_CLIENT_ID,
    client_secret: YOUR_CLIENT_SECRET,
  }),
});
const { access_token } = await res.json();

Step C. Call the API with the token.

curl https://app.sweatstack.no/api/v1/activities/latest \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
const res = await fetch(
  "https://app.sweatstack.no/api/v1/activities/latest",
  { headers: { Authorization: `Bearer ${accessToken}` } },
);
const activity = await res.json();

The API returns the user's most recent activity as JSON.

What's next

You have authentication and a working API call. The next steps depend on what you're building.

  • Browse every endpoint. The API reference covers every route, parameter, and response schema. Run requests live against your account in the API playground.
  • Add real features. See Activities, Dailies, Tests, and Metabolic profile.
  • Drop the SweatStack signup requirement. Sign in with SweatStack lets users authenticate with the wearable account they already have.
  • React to data changes. Webhooks notify you when activities or tests are created, updated, or deleted.
  • Store per-user state without a database. App metadata lets you attach JSON to activities, traces, tests, and users.
  • Skip running infrastructure. SweatStack Pages hosts your app's static frontend.
  • Go commercial. Pricing. Free for community apps.