Skip to main content

PyPI - Downloads PyPI - Downloads

Unofficial Basic-Fit API Client

Disclaimer: This is an unofficial Python client for the Basic-Fit app API. It is not affiliated with, endorsed by, or in any way connected to Basic-Fit N.V. Use it with your own account, at your own risk.

Introduction

The Unofficial Basic-Fit API Client is an asynchronous Python library for the backend that powers the Basic-Fit mobile app. It lets you read your membership details, gym visit history, in-club body-composition measurements and achievement badges, and it exposes the public workout, recipe and club-finder content library. The client handles the OAuth2 token lifecycle — including Basic-Fit's rotating refresh tokens — so you can focus on the data.

Features

  • Authentication Management: Keeps a valid access token, refreshes automatically when it expires, and correctly persists the rotating refresh token Basic-Fit hands back on every refresh.
  • One-time browser login (PKCE): A helper that builds the authorize URL and exchanges the returned code for tokens. The sign-in itself happens in a real browser because the login page is protected by a bot-challenge WAF.
  • Membership info: Name, membership type, home club, card/membership number, add-ons and outstanding-debt flag.
  • Visit history: Full activity feed with a convenience filter for physical gym check-ins.
  • Body measurements: Weight, fat %, muscle, water and more from the in-club scales.
  • Badges: Earned achievement badges.
  • Content library: Search the workout catalog, the recipe catalog (with macros) and the club finder — all via the app's public Contentful endpoint.
  • Typed models: Every response is parsed into a documented dataclass, with the raw payload kept on .raw for anything not yet modelled.

Features to be Added

  • Workout progress / logging endpoints
  • Club busyness time-series helpers

(feel free to PR if you manage to implement any of these features)

Installation

Ensure you have Python 3.11 or higher installed. You can install the package using pip:

pip install basicfit

Or, from a checkout:

pip install -r requirements.txt

Authentication

Basic-Fit uses OAuth2 Authorization Code + PKCE. The login page (login.basic-fit.com) sits behind an Imperva browser challenge, so it can't be automated headlessly — you sign in once in a normal browser. The token endpoint (auth.basic-fit.com) is not challenged, so all refreshes after that first login happen automatically in the background.

Refresh tokens rotate. Every refresh returns a new refresh token and invalidates the old one. Always persist the token set after each call — use the token_updated callback below and you never have to think about it.

One-time browser login

import asyncio
import aiohttp
from basicfit import AuthManager, TokenSet, start_login, parse_redirect

async def login():
    challenge = start_login()
    print("Open this URL and sign in:\n", challenge.authorize_url)
    # Your browser will try to open a
    # com.basicfit.trainingapp:/oauthredirect?code=... URL — copy it from the
    # address bar and paste it here:
    redirect = input("Paste the redirect URL: ").strip()
    code = parse_redirect(redirect, expected_state=challenge.state)

    async with aiohttp.ClientSession() as session:
        tokens = await AuthManager.async_exchange_code(
            session, code, challenge.verifier
        )
    # Persist this — it's all you need next time.
    print(tokens.to_dict())

asyncio.run(login())

Reusing a stored token

import json
from basicfit import BasicFitClient, TokenSet

def save(tokens):  # called automatically after every rotation
    with open("tokens.json", "w") as fh:
        json.dump(tokens.to_dict(), fh)

with open("tokens.json") as fh:
    tokens = TokenSet.from_dict(json.load(fh))

client = BasicFitClient.create(tokens, token_updated=save)

Or, if you only have the raw refresh token string:

client = BasicFitClient.from_refresh_token("<refresh-token>", token_updated=save)

Usage

The client manages its own aiohttp session (pass your own via session= if you prefer) and works as an async context manager.

import asyncio
from basicfit import BasicFitClient, TokenSet

async def main():
    async with BasicFitClient.from_refresh_token("<refresh-token>") as client:
        # Membership
        member = await client.get_member()
        print(member.name, member.membership_type, member.home_club)

        # Gym visits (last 30 days by default; accepts date ranges, max 365 days)
        visits = await client.get_visits()
        print(f"{len(visits)} visits")
        for v in visits[:5]:
            print(v.date, v.club)

        # Body composition (most recent first)
        for m in await client.get_body_measurements(limit=3):
            print(m.date, m.weight, "kg", m.fat, "% fat")

        # Achievement badges
        for b in await client.get_badges():
            print(b.name, b.earned_at)

asyncio.run(main())

Content library

The workout, recipe and club look-ups hit Basic-Fit's public content endpoint and don't require authentication (they work even before login):

async with BasicFitClient.from_refresh_token("<refresh-token>") as client:
    workouts = await client.search_workouts("full body", limit=5)
    for w in workouts:
        print(w.name, w.duration_min, "min", w.body_parts)

    recipes = await client.search_recipes("protein", limit=5)
    for r in recipes:
        print(r.name, r.kcal, "kcal", r.protein_g, "g protein")

    clubs = await client.search_clubs(city="Groningen")
    for c in clubs:
        print(c.display_name, c.address, "closed" if c.closed else "open")
        print(client.club_image_url(c.kp_number))

Quickstart script

examples/quickstart.py runs the whole flow end to end: it does the one-time browser login, stores the token in tokens.json, and prints your membership, recent visits, latest weight and badge count. On later runs it reuses (and silently rotates) the stored token.

python examples/quickstart.py

Home Assistant

A companion Home Assistant integration built on this package lives at HA-Basic-Fit — install it via HACS to get your visits, membership, weight and badges as sensors.

Notes

  • Locales: the content library uses Contentful locale codes (en-US, nl, fr, es, de) — note nl, not nl-NL. The client normalises unknown values to en-US.
  • Ranges: the activities endpoint accepts spans up to 365 days; longer ranges are clamped.
  • Errors: the package raises BasicFitAuthError (sign in again), BasicFitAPIError (bad response, carries status_code), BasicFitNetworkError (timeout/connection) and BasicFitValidationError (bad arguments) — all subclasses of BasicFitError.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

basicfit-1.0.0.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

basicfit-1.0.0-py3-none-any.whl (20.6 kB view details)

Uploaded Python 3

File details

Details for the file basicfit-1.0.0.tar.gz.

File metadata

  • Download URL: basicfit-1.0.0.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for basicfit-1.0.0.tar.gz
Algorithm Hash digest
SHA256 98a29fbc7d7edac4bfe2ff376d3e838ce52203fe352fb8b14d2e22ce797d83c4
MD5 d4e107b46b427f7a1dd61318b0dbeba7
BLAKE2b-256 6328dacf906fd9a4191f66b39fe90571b3c4ed2a296f704c6ac4397047cc0acb

See more details on using hashes here.

File details

Details for the file basicfit-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: basicfit-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 20.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for basicfit-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 164b4d8f60f1c00ad29801d18110313e0a021e1a336c1ca3e02e38ece5c22e83
MD5 ba0b5d9f89089cfe7a21e3dd5c0f46f7
BLAKE2b-256 15308ddc93fa8818f2c6ff2138fe9d879e58c980571510b62b53d1a7d9e2e3e3

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page