Sign in with SweatStack¶
One button on your app. No signup form, no password to reset, no onboarding questionnaire. The user authenticates with the wearable account they already have (Garmin, Intervals.icu, and more as we add them), SweatStack creates their SweatStack account in the background, and your app receives an OAuth2 access token. It's the same token every SweatStack integration uses, so there's nothing new to learn on the API side.
This is the front door to an app built on SweatStack. One button replaces your entire login and registration stack.
What your users' SweatStack account brings with it¶
The reason to make this your whole login, and not only a data connector behind a settings page, is what arrives with the account. A single authorization hands your app data you would otherwise collect with forms or derive with a pipeline:
-
Identity ·
profile
Email address and name. No signup form, no email-verification round-trip.
-
Dailies ·
data:read
Body mass, resting heart rate, HRV, sleep, and the rest of the user's dailies.
-
Performance profile ·
data:read
Thresholds, training zones, VO2max, FTP, and intensity-duration models from the user's tests and metabolic profile.
-
History ·
data:read
Years of activity data, normalized across every wearable, backfilled while the user signs in.
What you don't build¶
Because the account carries all of that, this is the work you no longer have to do:
- Signup, password storage, password reset, and email verification
- An onboarding questionnaire asking the user for their weight, thresholds, or training zones
- A separate OAuth app and set of credentials at Garmin, Intervals.icu, and every platform after them
- Schema normalization across a dozen device formats
- A backfill pipeline for historical data
You ship the button. SweatStack ships everything behind it.
The flow¶
For a first-time user:
- They tap Sign in with SweatStack in your app.
- On the SweatStack sign-in page, which carries your app's name, they pick the wearable they already use (Garmin, Intervals.icu, and so on) or an email magic link.
- They authorize on their wearable. If they don't have a SweatStack account yet, SweatStack creates one.
- Your app's consent screen appears. If the wearable didn't share an email address (Garmin doesn't), the same screen asks for one. SweatStack sends a "Confirm your email for {your app}" message, and the user continues without waiting for it. The page behind that link carries your app's name and a Back to {your app} link to the URL on your app's profile.
- Your app receives the authorization code and exchanges it for tokens.
Three to four taps, and no SweatStack account required up front. A returning user who already linked that wearable is signed straight in, in the same number of taps.
One thing can happen between steps 3 and 4. If a Garmin user leaves the activity-export or historical-data toggle off on Garmin's permission screen, SweatStack shows them what that means right away, with a button to go back and switch it on. It's never a required step: "Continue anyway" takes them to your consent screen. Catching it there, while the user still has Garmin's screen in mind, is what keeps activity_history_not_granted from becoming the first thing your app has to explain. See why a user has no data for the case where they continue anyway.
It's standard OAuth2¶
Nothing changes on the API side. Your app starts the normal OAuth2 / OIDC authorization-code flow against https://app.sweatstack.no/oauth/authorize, exactly as it would for any provider. SweatStack handles wearable authentication, account creation, email collection, and consent, then redirects back to you with an authorization code.
If you can integrate any OAuth2 provider, you already know how to do this. See OAuth2 for the full walk-through, or the quick reference if you've integrated an OAuth2 provider before.
The button¶
Canonical label: "Sign in with SweatStack." It reads as identity, the way "Sign in with Google" and "Sign in with Apple" do, and it's the label that tells a first-time user this is how they get in. "Continue with SweatStack" is an accepted variant.
Add a subtitle. Your end users don't know the SweatStack name yet, and an unfamiliar word on a sign-in button costs you conversion, not us. Name the accounts they do recognize, right under the label:
Sign in with SweatStack Use your Garmin, Wahoo or Intervals.icu account
Use the official mark from Brand assets. Two rules:
- Don't frame the button so it implies SweatStack endorses your app. It signals integration, not endorsement.
- Don't translate the SweatStack name. Brand names stay in their original form.
Already have your own login?¶
Adding SweatStack to an app that already has its own accounts, for example a settings page with a row of "Connect Garmin" and "Connect Strava" buttons? It's the exact same flow. Label the button "Connect with SweatStack" to match that context if you like: same authorization URL, same tokens, your wording. You give up the free login step, but you keep everything the account carries. To send each button straight to its provider, see Send users straight to one provider.
Send users straight to one provider¶
Add integration= to the authorization URL to skip the sign-in chooser and send the user straight to one provider. Use it when your app supports a single wearable, or when you want your own per-provider buttons ("Connect Garmin", "Connect Intervals.icu") instead of one SweatStack button.
Tell the user they're connecting through SweatStack
This path sends the user straight to the provider, and the provider's own permission screen (Garmin's, for example) asks them to grant SweatStack access to their data, not the app they came from. A user who has never heard of SweatStack can be surprised by that, and some will back out. They also end up with a SweatStack account that holds the connection. Set both expectations before they start: tell them your app connects through SweatStack, on or near the button ("Connect Garmin through SweatStack") or in the surrounding copy. That's your responsibility, not SweatStack's.
https://app.sweatstack.no/oauth/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope=data:read&integration=garmin_connect
Values: garmin_connect, intervals_icu, wahoo. One per request. A misspelled value returns 422, so a typo fails your first test instead of silently falling back to the full chooser. For per-provider buttons, use one URL per provider.
| Who arrives | What happens |
|---|---|
| Not signed in | Straight to the provider, then your consent screen. No chooser. |
| Not signed in, provider already linked to an account | Signed into that account, then consent. |
| Signed in, has the provider | Consent, as always. |
| Signed in, without the provider | Sent to connect it first, then consent. |
This path skips the chooser, so there is no email sign-in on it. Leave email_auth_mode out.
Edge case: an email-first user meeting the provider for the first time
A person who already has a SweatStack account by email, has never linked this provider, and meets it for the first time through your button gets a new account linked to the provider. The consent screen then asks them for an email and tells them it belongs to another account. That screen offers "sign in with your email instead" and returns them to your consent screen as their real account. If they connect the provider from there, SweatStack reports that it is already linked to the account that was just created. The fix is the existing procedure. It is rare: it needs an email-first SweatStack user who has never connected their wearable.
Button copy for this pattern is on the brand page.
Why this exists¶
The default OAuth2 flow assumes the user already has an account with the provider. For almost every new SweatStack user, that assumption is wrong: they have a Garmin account, not a SweatStack account. So SweatStack lets them sign in with the account they do have, and creates the SweatStack account for them.
The mental model to design around: SweatStack is the account, and the wearable is how the user signs into it. Not a connector bolted onto your login. The login itself.
Supported wearables¶
- Garmin Connect
- Intervals.icu
- Wahoo
The list grows as we add platforms. The same OAuth2 endpoints work for all of them. SweatStack handles the per-platform specifics internally.
The fastest way to understand the flow is to run it yourself. The live demo runs the real OAuth2 flow and shows exactly what your app receives at each step: the authorization redirect, the user's profile and email, and their history backfilling while you watch.