A tiny, dependency-free Python client for the international OnelapFit / Geoid backend — the cloud behind Magene bike computers (and the third-party rides it aggregates from Strava, Garmin, Wahoo, Komoot, Bryton, Coros …).
It lets you, for your own account:
- ⬇️ Download your rides as raw
.FITfiles (own them, back them up, re-import into intervals.icu, Golden Cheetah, Strava, anywhere). - ⬆️ Upload a GPX route to your account, so it shows up for on-device navigation on the head unit.
No SDK, no scraping of other people's data, no cloud middleman — just your login
talking to api-fitness.rfsvr.com, the data plane for your onelap.com account.
International only. This targets the international backend behind the OnelapFit / Geoid app. The Chinese edition (
onelap.cn) is a separate service and is not supported.
Magene head units upload to OnelapFit, but getting your data out (or a planned
route in) is awkward. OnelapFit/Geoid is also a hub: it pulls rides from other
brands via third-party connectors, so list can surface everything in one place —
each ride carries a source/tag telling you where it came from.
No dependencies — Python 3.8+ standard library only.
git clone https://github.com/czdanika/onelapfit-sync.git
cd onelapfit-sync
cp config.example.ini config.ini
$EDITOR config.ini # your onelap.com email + password, and regionconfig.ini, .gitignore-d by default, holds your credentials — keep it private.
Accounts live on regional backend nodes and every request must send a matching
region. EU accounts are region 2. If login succeeds but ride lists come back
empty, your region is almost certainly wrong — try a different value.
If your account signs in with a Google/Apple/email-code flow and has no
password, set one first (the app's "log in with password" / "forgot password"
screens), then use it here. Alternatively, drop a captured token + uid into
the config and skip the password login entirely.
# list rides from the last 60 days (shows source + whether a .FIT exists)
python3 onelapfit_sync.py list --days 60
# download every ride's .FIT into ./fit/ (skips files already present)
python3 onelapfit_sync.py download --days 120 --out fit/
# upload a GPX route (shows up in the app's route/navigation list)
python3 onelapfit_sync.py upload my-route.gpx
# dry-run: let the server parse the GPX without saving it
python3 onelapfit_sync.py upload my-route.gpx --previewPoint at a different config with --config path/to/config.ini.
Import it into your own project:
from onelapfit_sync import OnelapFit
ol = OnelapFit(account="you@example.com", password="secret", region="2")
ol.login()
# download recent rides
for ride in ol.list_rides(days=30):
path = ol.download_fit(ride, "fit/")
print(ride["name"], ride.get("tag"), path)
# upload a planned route; returns the new route id (nid)
nid = ol.upload_gpx("route.gpx")OnelapFit methods: login(), list_rides(days=…), download_fit(ride, out_dir),
upload_gpx(path, save=True), preview_gpx(path). All network errors with a
non-200 application code raise OnelapFitError.
Every request is signed: sign = md5(path + "?" + sorted(nonce,timestamp,non-empty query) + "key=" + APIKEY). The body is not part of the signature. Passwords are
sent MD5-hashed (the app's scheme). Endpoints used:
| Purpose | Endpoint |
|---|---|
| Login | POST /api/v1/app/login |
| Ride list | GET /api/v1/app/record/riding/list |
| GPX preview / save | POST /api/v1/app/roadbook/gpx/{preview,save} |
See onelapfit_sync.py — it's one small, commented file.
Protocol groundwork from two projects that figured out pieces of this:
- jeromecornet/magpx — route-upload payload.
- just-nobody/onelap-fit-export — request signing + ride list.
Not affiliated with, endorsed by, or connected to Magene or Onelap. This is an interoperability / personal-data-portability tool: it accesses your own account with your own credentials. The signing key is extracted from the public app solely to speak the protocol. The backend is undocumented and may change or break at any time. Use at your own risk and respect OnelapFit's Terms of Service.
MIT — see LICENSE.