This repository outlines the structure of The Gym's API. With the example code, you will be able to query any API endpoint to programatically retrieve data about your gym profile.
As The Gym Group's App is just a templated app for "egym" by NetPuse, this may work for any other of their Apps too.
The web app renders your statistics server side. Web scraping is gross. To retrieve our gym statistics we opt for the mobile API.
The login mechanism requires slighty different headers to the rest of the API:
POST https://thegymgroup.netpulse.com/np/exerciser/login
{"username": "USERNAME",
"password": "PIN"}
{
"accept": "application/json",
"accept-encoding": "gzip",
"connection": "Keep-Alive",
"host": "thegymgroup.netpulse.com",
"user-agent": "okhttp/3.12.3",
"x-np-api-version": "1.5",
"x-np-app-version": "6.5.1",
"x-np-user-agent": "clientType=MOBILE_DEVICE; devicePlatform=ANDROID; deviceUid=; applicationName=The Gym Group; applicationVersion=5.0; applicationVersionCode=38",
"content-type": "application/x-www-form-urlencoded",
"content-length":"*CALCULATE CONTENT LENGTH HERE*"
}
You can set the x-np-app-version header to a value greater than the current version, such as 9999. This forces the API to use the latest available version, even if the app has been updated. This is an easy workaround to avoid issues where old versions of the API stop working after updates.
When you log in, the response will contain a Set-Cookie header. Use this header for other API requests.
The login response will return general user information including your user UUID. Use this for other API requests too.
GET https://thegymgroup.netpulse.com/np/exercisers/*USER_UUID*/check-ins/history?endDate=2022-10-09T15:02:56
{
"accept": "application/json",
"accept-encoding": "gzip",
"connection": "Keep-Alive",
"cookie": *COOKIE*,
"host": "thegymgroup.netpulse.com",
"user-agent": "okhttp/3.12.3",
"x-np-api-version": "1.5",
"x-np-app-version": "6.5.1",
"x-np-user-agent": "clientType=MOBILE_DEVICE; devicePlatform=ANDROID; deviceUid=; applicationName=The Gym Group; applicationVersion=5.0; applicationVersionCode=38"
}
Documented by decompiling The Gym Group Android APK (com.netpulse.mobile.thegymgroup) and testing endpoints against the live API.
https://thegymgroup.netpulse.com
All endpoint paths below are relative to this base. The base URL is dynamic per brand — other NetPulse/egym white-label apps use different hostnames.
Authentication is cookie-based via a JSESSIONID cookie. Log in first, then the cookie store handles subsequent authenticated requests automatically.
Every request must include:
| Header | Value | Notes |
|---|---|---|
User-Agent |
okhttp/3.12.3 |
The Android app's HTTP client user-agent |
Accept |
application/json |
|
X-NP-API-Version |
1.5 |
|
X-NP-APP-Version |
Numeric app version (e.g. 9999) |
Must be a number |
X-NP-User-Agent |
See below | Semicolon-separated key=value pairs |
The X-NP-User-Agent header format:
clientType=MOBILE_DEVICE; devicePlatform=ANDROID; deviceUid=<device-uuid>; applicationName=The Gym Group; applicationVersion=<version-name>; applicationVersionCode=<version-code>
Standard username/password login.
Content-Type: application/x-www-form-urlencoded
Form Parameters:
| Parameter | Type | Description |
|---|---|---|
username |
string | Email address |
password |
string | PIN / passcode |
Response: 200 OK
{
"username": "user@example.com",
"uuid": "18fe83d6-c80c-4d21-a64f-b6277c418c97",
"sessionId": "...",
"isVerified": true,
"isEmailVerified": true,
"clubChainName": "The Gym Group",
"homeClubUuid": "1bdeaf9b-37b1-42ee-9a6c-b8d82b86b7ad",
"homeClubName": "London Acton",
"firstName": "...",
"lastName": "...",
"chainUuid": "...",
"timeZone": "Europe/London",
"timeZoneOffset": "...",
"measurementUnit": "...",
"isGuestUser": false,
"isHasMessages": false,
"isProfileComplete": true,
"isShowPT": false,
"expirationTime": 0,
"accountStatus": "Active",
"googleWalletUrl": "..."
}A JSESSIONID cookie is set — use a cookie jar for all subsequent requests.
OAuth2 login (used for social sign-in).
Logs out and invalidates the session.
List classes for a gym location.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
startDateTime |
long | Yes | Start of range (epoch milliseconds) |
endDateTime |
long | Yes | End of range (epoch milliseconds) |
exerciserUuid |
string | Yes | Logged-in user's UUID |
type |
string | No | Filter by class type |
Response: 200 OK — Array of class objects
[
{
"brief": {
"id": "class-uuid-here",
"name": "SGT-Functional Conditioning",
"type": "...",
"free": true,
"booked": false,
"waitlisted": false,
"maxCapacity": 16,
"totalBooked": 3,
"waitlistCapacity": 0,
"waitlistBooked": 0,
"startDateTime": 1771678200000,
"endDateTime": 1771681800000,
"instructor": {
"fullName": "Instructor Name"
},
"activity": {
"description": "A full body workout..."
},
"availableOptions": { ... },
"childCare": false,
"availableSpots": ["1", "2", "3"],
"customInfo": [],
"clubUuid": "1bdeaf9b-37b1-42ee-9a6c-b8d82b86b7ad",
"liveStreamClass": false,
"cancelled": false
},
"details": null,
"attendeeDetails": {
"id": "...",
"booked": false,
"waitlistBooked": false,
"waitlistPosition": null,
"productAvailability": null,
"availableActions": [],
"spotBooked": null
}
}
]Notes:
startDateTimeandendDateTimeare epoch millisecondsinstructor.fullNamemay be empty for some gyms- The
briefwrapper is always present in list responses cancelledindicates whether the class itself has been cancelled by the gym
Get details for a single class.
Response: Single class object (same shape as array items above).
Get the user's booked classes (my schedule).
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
startDateTime |
long | No | Start of range (epoch milliseconds) |
endDateTime |
long | No | End of range (epoch milliseconds) |
clubUuid |
string | No | Filter by club |
Response: Array of class objects.
Book a class.
Content-Type: application/x-www-form-urlencoded
Form Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
exerciserUuid |
string | Yes | User's UUID |
spot |
string | No | Spot number (for spot-based booking) |
type |
string | No | Booking type |
Response: 200 OK — Updated class object
Returns a 403 with message "Session is already booked" if already enrolled.
Cancel a class booking.
Content-Type: application/x-www-form-urlencoded
Form Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
exerciserUuid |
string | Yes | User's UUID |
type |
string | No | Cancellation type |
Response: 200 OK — Updated class object (with booked: false)
Update an existing booking (e.g. change spot).
Form Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
exerciserUuid |
string | Yes | User's UUID |
spot |
string | No | New spot number |
Add to a class waitlist.
Form Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
exerciserUuid |
string | Yes | User's UUID |
Remove from a class waitlist.
Form Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
exerciserUuid |
string | Yes | User's UUID |
Get what operations are allowed for a specific club.
Response:
{
"singleClassAccessAllowed": true,
"addToClassAllowed": true,
"removeFromClassAllowed": true,
"addToWaitlistAllowed": true,
"removeFromWaitlistAllowed": true,
"accountBalanceItemsRetrievalAllowed": true,
"filterMyClassesAllowed": true
}Get brand-level allowed options (same response shape).
Get current gym busyness.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
gymLocationId |
string | Yes | Gym location UUID |
Response:
{
"gymLocationId": "1bdeaf9b-37b1-42ee-9a6c-b8d82b86b7ad",
"gymLocationName": "London Acton",
"currentCapacity": 42,
"currentPercentage": 15,
"status": "OPEN",
"historical": [...]
}Get historical busyness patterns.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
dayOfWeek |
string | Yes | Day to query |
Get check-in history.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
startDate |
string | Yes | ISO format YYYY-MM-DDTHH:MM:SS |
endDate |
string | Yes | ISO format YYYY-MM-DDTHH:MM:SS |
Response:
{
"checkIns": [
{
"checkInDate": "2025-01-15T10:30:00",
"timezone": "Europe/London",
"gymLocationName": "London Acton",
"gymLocationAddress": "...",
"duration": 3600000
}
]
}Notes:
durationis in millisecondscheckInDateis in local time (no timezone offset in the string)- Response is not sorted — client must sort
Get the most recent check-in.
Get recurring check-in report subscriptions.
Request a check-in report.
Delete a recurring report subscription.
Get user profile.
Update user profile.
Upload user avatar (multipart image upload).
Remove user avatar.
Change password.
Form Parameters: email, oldPassword, newPassword, confirmPassword
Reset password.
Form Parameters: email, token, secret (optional)
Request passcode reset.
Query Parameters: login (username/email)
Validate XID or email.
Query Parameters: xid or email
Get membership information.
Send barcode for membership lookup.
Form Parameters: barcode
Activate membership.
Form Parameters: barcode or agreement
Get membership barcode.
Get Google Pay JWT barcode.
Query Parameters: appVersion, backgroundColor
Get account balance.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
clubUuid |
string | Club UUID |
itemType |
string | e.g. "class" |
Get available purchase bundles for a club.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
type |
string | "Session" |
name |
string | Bundle name filter |
Purchase a class bundle.
Form Parameters: type, clubUuid, id, type, price, taxRate, quantity
Get payment information.
Get the weekly class schedule template for a club.
Get purchase types available for a club's schedule.
Get notifications list.
Query Parameters: startingFrom
Register FCM push token.
Form Parameters: token, deviceUid, provider, providerId, version
Get active challenges.
Get past challenges.
Get challenge details.
Join a challenge.
Form Parameters: timeZone
Leave a challenge.
Get challenge progress.
Query Parameters: timezone
Get challenge participants.
Query Parameters: pageSize, start
Get challenge prize info.
Get challenge prize image.
Base path: /analysis/api/v1.0
Get activity level definitions.
Query Parameters: languageCode
Get user's current activity level.
Get user's ranking.
Query Parameters: languageCode, shift
Get leaderboard.
Query Parameters: languageCode, size, nextPageToken
Get ranking with leaderboard combined.
Query Parameters: languageCode, size
Send app rating feedback.
Form Parameters: message
Send club visit feedback.
Request a personal trainer.
Form Parameters: type, comments, phone, topic
Request fitness assessment.
Form Parameters: comments, phone
Get refer-a-friend configuration.
Refer a friend (classic).
Form Parameters: email
Refer a friend (extended).
Form Parameters: firstName, lastName, email, phone
Request a trial pass.
Form Parameters: firstName, lastName, homeClub, email, phone
Get TGG check-in checklist.
Get check-in question status/preferences.
Get eGym user account by email.
Register with eGym.
Get eGym linking status.
Link to eGym.
Unlink from eGym.
Accept eGym terms and conditions.
Get or set eGym opt-in preferences.
Set eGym password.
Reset eGym password.
Form Parameters: email
Get connected external workout apps.
List extra/manual barcodes.
Save a new barcode.
Edit a barcode.
Delete a barcode.
Get branding configuration.
Query Parameters: brandId, resourceType
Resolve container/brand.
Query Parameters: keyword, containerAppVersion
Get verification TAN.
Get partner portal token.
Query Parameters: club_uuid
- All timestamps are epoch milliseconds (not seconds)
- Auth is via
JSESSIONIDcookie set during login - POST endpoints for booking/cancel use
application/x-www-form-urlencoded, not JSON - The API is powered by NetPulse/egym and is used by many gym brands — only the base URL differs
- Path parameters use
%sformat substitution in the source (e.g./np/company/%s/class/%s/addExerciser) - Note the inconsistency: some paths use
/exerciser/(singular) and others use/exercisers/(plural) - The
briefwrapper in class responses contains the core class data;detailsandattendeeDetailsmay be null in list responses - Source: Decompiled from APK version with
galaxy_TheGymGroupReleasebuild variant