# Equipment Vendor API (for standalone clients)

At EGYM, we believe that fitness is the soul of healthy living. Work together with partners to help us bringing new ways of working out to
millions of gym members, and new ways of prescribing exercises to hundred of thousands of gym trainers, all around the world.

EGYM provides a Fitness Platform for the Connected Gym so you can help us with the mission to ***make the gym work for everyone***.
EGYM provides a global account that is not scoped for a specific tenant, brand or gym. The account is called EGYM ID. The EGYM ID allows
users to use different services of the gym. The EGYM ID is used for the login to EGYM hardware and software products and conneceted equipment.

EGYM works with the best of breed of the fitness industry. In this documentation, we provide tools and info needed to build a variety of workout
experiences that integrate directly with the EGYM Ecosystem. We are happy to welcome you as a partner of EGYM.

---

# 📦 Changelog of Documentation

| Version | Changes |
|---------|---------|
| **1.2.0** | ✅ Added support for **Genius Training Plans** — see [`GET /api/v1/cardio/training-plans`] and [`GET /api/v1/strength/training-plans`]|
| **1.1.0** | 🔐 Introduced **NFC-based login** via Apple/Google Wallet — see [`POST /api/v1/oauth/token`](#tag/OAuth/operation/token) |

---

# 🔐 Authentication

The Equipment Vendor API authentication is based on the OAuth 2.0 as specified in the [RFC6749](https://tools.ietf.org/html/rfc6749),
more concretely on the [Resource Owner Password Credentials Grant](https://tools.ietf.org/html/rfc6749#page-37) due to constraint
environment that can be found in our partner devices, i.e. devices with no screen or using the RFID for user identification.

Currently, different methods for obtaining the Access Token are made available:

- By specifying **user credentials**
- By specifying **RFID**
- **By specifying NFC (Wallet) credentials** *(since v1.1.0)*

The OAuth `client_id` and `client_secret` are issued by EGYM to each partner (vendor) for each gym. These are used in a `Basic` authentication header as:

```
Authorization: Basic Base64(client_id:client_secret)
```

---

## 🔑 User Credentials (EGYM ID)

_This is the classic Resource Owner Password Grant._


```http
POST /api/v1/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=password&machine_type=bike&serial_number=ser123&username=johndoe&password=•••
```

---

## 📶 User RFID


```http
POST /api/v1/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=rfid&machine_type=bike&serial_number=ser123&rfid=AB12CD34&rfid_format=MIFARE
```

---

## 📱 NFC Login (Apple / Google Wallet)

_Introduced in v1.1.0_

This method uses NFC payloads from Apple/Google Wallet. Use `grant_type=nfc` and supply:

- `payload`: the NFC data string
- `transponder_type`: either `APPLE` or `GOOGLE`
- One of:
  - `issuer_id`: the Wallet issuer identifier (e.g., `com.egym.apple`)
  - `configuration_index`: the DotOrigin VTAP slot ID

Examples:

```APPLE
POST /api/v1/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=nfc&machine_type=bike&serial_number=ser123&payload=abc123&transponder_type=APPLE&issuer_id=com.egym.apple
```

```GOOGLE
POST /api/v1/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=nfc&machine_type=bike&serial_number=ser123&payload=abc123&transponder_type=GOOGLE&issuer_id=123456789
```

```VTAP
POST /api/v1/oauth/token
Authorization: Basic <Base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=nfc&machine_type=bike&serial_number=ser123&payload=abc123&configuration_index=2
```


## 📜 Terms and Conditions Handling

Some users may not have accepted the latest EGYM Terms and Conditions (T&C). In that case, the user details will indicate that the user did not accepted them yet and partners must handle T&C interaction:

### 1. Retrieve the T&C and privacy policy

```T&C
GET /api/v1/ressources/terms-and-conditions
Content-Type: text/html

locale=en_US
```

```PP
GET /api/v1/ressources/privacy-policy
Content-Type: text/html

locale=en_US
```
Response will be terms.


### 2. Prompt the user to accept or decline

- If **accepted**, proceed to step 3
- If **declined**, exit the login flow gracefully

### 3. Submit confirmation of acceptance

```http
PUT /api/v1/users/terms-and-conditions
Authorization: Bearer {access_token}
Content-Type: application/json

locale=en_US
```

---

## ⏱ Rate Limit

Authentication is rate-limited per `client_id`: **10 requests per second**.

---

# 🔄 Integration Flow Overview

```plaintext
[Authenticate (POST /oauth/token)]
              ↓
[Get User Details (GET /users)]
              ↓
  ┌────────────────────────────┬────────────────────────────┐
  │                            │                            │
  │   Fitness Equipment        │   Measurement Devices       │
  │                            │                            │
  │ - Get Training Plan        │ - Submit Measurements       │
  │   → GET /training-plans    │   → POST /measurements/*    │
  │ - Submit Workout           │                            │
  │   → POST /workouts         │                            │
  └────────────────────────────┴────────────────────────────┘
```

---

# ⚠️ Error Handling

All endpoints return descriptive errors when something goes wrong.

### Common HTTP Status Codes

| Code | Meaning         | Notes |
|------|------------------|-------|
| 200  | OK               | Success |
| 204  | No Content       | Success, no response body |
| 400  | Bad Request      | Validation or field error |
| 401  | Unauthorized     | Missing or invalid auth - credentials are invalid |
| 403  | Forbidden        | Insufficient permission - endpoint is not available for equipment type|
| 404  | Not Found        | Resource doesn't exist - unknown RFID|
| 500  | Internal Error   | Something unexpected |

### Sample Error Response

```json
{
  "message": "Invalid input",
  "fieldErrors": [
    {
      "name": "username",
      "message": "Must not be null"
    }
  ]
}
```

---

If you have any questions or need help integrating, contact us at [integrations@egym.com](mailto:integrations@egym.com).

---

# 📝 Integration FAQ – Standalone Devices API

This section addresses common technical integration questions specific to the **Standalone Devices** model.

## 1. Supported Login Types
- **EGYM ID Login** (`grant_type=password`): EGYM Username & password
- **RFID Login** (`grant_type=rfid`): RFID number + format
- **NFC Login** (`grant_type=nfc`): NFC payload + issuer ID or configuration index

## 2. Handling Terms & Conditions
If the user has not accepted the latest Terms & Conditions (T&C):
1. Retrieve T&C URL: `GET /users/{userId}/terms`
2. Display link to user for acceptance/rejection
3. If accepted: `POST /users/{userId}/terms/accept`
4. If rejected: exit the login flow gracefully

## 3. Key Endpoints for Standalone Integrations
- Authentication: `POST /oauth/token`
- User details: `GET /users`
- Training plan: `GET /training-plans`
- Workout results: `POST /workouts`
- Measurements: `POST /measurements/*`

## 4. Error Handling Best Practices
- **401 Unauthorized**: Invalid/missing credentials or token
- **403 Forbidden**: Permission issue
- **429 Too Many Requests**: Rate limit exceeded; retry after delay
- Important: Provide meaningful error messages to the user (not just error codes, ideally with localized description), or silently retry when user experience requires

## 5. Rate Limits
- Authentication: 10 requests/second per `client_id`
- Other endpoints: See API documentation

## 6. Testing
- Use the **EGYM Sandbox** with provided test credentials.
- Test credentials are prodvided by EGYM
- Test login flows, training plan retrieval, workout submission, and T&C handling

## 7. What if I send the same measurement twice?**
Use a different `uniqueMeasurementId` each time.

## .When should I use `issuerId` vs `configurationIndex` in NFC?**
These are alternatives for identifying the wallet pass source. Provide one depending on the integration project with EGYM. Configuration Index is only supported when using the Dot Origin VTAP readers.


Version: 1.2.0
License: Pending License

## Servers

Test (ext-1)
```
https://partner-api.ext-1.test.co.egym.coffee
```

Production
```
https://partner-api.api.egym.com
```

## Security

### user

Type: http
Scheme: bearer
Bearer Format: JWT

### partner

Type: oauth2

## Download OpenAPI description

[Equipment Vendor API (for standalone clients)](https://developer.egym.com/_bundle/equipment/partner-api.yaml)

## OAuth

### Login

 - [POST /api/v1/oauth/token](https://developer.egym.com/equipment/partner-api/oauth/token.md): This endpoint logs in the user and returns the access token

### well-known

 - [GET /api/v1/oauth/.well-known/jwks.json](https://developer.egym.com/equipment/partner-api/oauth/wellknown.md): This endpoint returns a JSON Web Key (JWK) set.

## Partners

### info

 - [GET /api/v1/partners/info](https://developer.egym.com/equipment/partner-api/partners/info.md): This endpoint returns the partner information which is related to the given credentials, if these credentials are invalid it will return a HTTP 401 UNAUTHORIZED error code.

## Body Measurement

### Get Body Measurement

 - [GET /api/v1/measurements/body](https://developer.egym.com/equipment/partner-api/body-measurement/getuserbodymeasurements.md): This endpoint retrieves the latest body measurement of the user

### Create Body Measurement

 - [POST /api/v1/measurements/body](https://developer.egym.com/equipment/partner-api/body-measurement/createbodymeasurement.md): This endpoint creates a body measurement for the user

### Get Body History for a user

 - [GET /api/v1/measurements/body/history](https://developer.egym.com/equipment/partner-api/body-measurement/getuserbodyhistory.md): This endpoint retrieves body measurements history for the user with pagination support

## Cardio Measurement

### Get Cardio Measurement

 - [GET /api/v1/measurements/cardio](https://developer.egym.com/equipment/partner-api/cardio-measurement/getusercardiomeasurements.md): This endpoint retrieves the latest cardio measurement of the user

### Create Cardio Measurement

 - [POST /api/v1/measurements/cardio](https://developer.egym.com/equipment/partner-api/cardio-measurement/createcardiomeasurement.md): This endpoint creates a cardio measurement for the user

### Get Cardio History for a user

 - [GET /api/v1/measurements/cardio/history](https://developer.egym.com/equipment/partner-api/cardio-measurement/getusercardiohistory.md): This endpoint retrieves cardio measurements history for the user with pagination support

## Flexibility Measurement

### Get Flexibility Measurement

 - [GET /api/v1/measurements/flexibility](https://developer.egym.com/equipment/partner-api/flexibility-measurement/getuserflexibilitymeasurements.md): This endpoint retrieves the latest flexibility measurement of the user

### Create Flexibility Measurement

 - [POST /api/v1/measurements/flexibility](https://developer.egym.com/equipment/partner-api/flexibility-measurement/createflexibilitymeasurement.md): This endpoint creates a Flexibility measurement for the user

### Get Flexibility History for a user

 - [GET /api/v1/measurements/flexibility/history](https://developer.egym.com/equipment/partner-api/flexibility-measurement/getuserflexibilityhistory.md): This endpoint retrieves flexibility measurements history for the user with pagination support

## User

### User Details

 - [GET /api/v1/users](https://developer.egym.com/equipment/partner-api/user/getuser.md): This endpoint returns a user

### User Details

 - [PUT /api/v1/users](https://developer.egym.com/equipment/partner-api/user/updateuser.md): This endpoint updates the current user. The endpoint is only enabled if there is a specific use case to update user records.

### Accept Terms and Conditions

 - [PUT /api/v1/users/terms-and-conditions](https://developer.egym.com/equipment/partner-api/user/accepttermsandconditions.md): This endpoint when invoked will save the information that the user accepted the eGym Terms and Conditions.

### Set user's avatar

 - [PUT /api/v1/users/image](https://developer.egym.com/equipment/partner-api/user/uploaduserimage.md): This endpoint sets the user's avatar.

### Assign RFID

 - [POST /api/v1/users/rfid](https://developer.egym.com/equipment/partner-api/user/assignrfid.md): This endpoint assigns one RFID to the user. If the RFID is already assigned to another user, it will be re-assigned to this user.

## Image

### Image

 - [GET /api/v1/images/{imageId}](https://developer.egym.com/equipment/partner-api/image/getimage.md): This endpoint returns the specified image

## Statistics

### User Activity Level

 - [GET /api/v1/users/activity-levels](https://developer.egym.com/equipment/partner-api/statistics/getuseractivityinformation.md): This endpoint will return activity level summary of the user.

### User Points

 - [GET /api/v1/points](https://developer.egym.com/equipment/partner-api/statistics/getworkoutpoints.md): This endpoint returns the EGYM activity points of the user.

## Machine

### Machine heartbeat

 - [POST /api/v1/machines/heartbeat](https://developer.egym.com/equipment/partner-api/machine/machineheartbeat.md): This endpoint receives machine heartbeat requests (signals)

## Resource

### Terms and Conditions

 - [GET /api/v1/resources/terms-and-conditions](https://developer.egym.com/equipment/partner-api/resource/gettermsandconditions.md): This endpoint returns the EGYM terms and conditions

### Privacy Policy

 - [GET /api/v1/resources/privacy-policy](https://developer.egym.com/equipment/partner-api/resource/getprivacypolicy.md): This endpoint returns the EGYM privacy policy

## Strength Workouts

### Create Workout

 - [POST /api/v1/strength/workouts](https://developer.egym.com/equipment/partner-api/strength-workouts/createworkout.md): This endpoint creates a strength workout

### Get Training Plans

 - [GET /api/v1/strength/training-plans](https://developer.egym.com/equipment/partner-api/strength-workouts/findalltrainingplans.md): This endpoint returns a user strength training plan

## Cardio Workouts

### Create Workout

 - [POST /api/v1/cardio/workouts](https://developer.egym.com/equipment/partner-api/cardio-workouts/createworkout_1.md): This endpoint creates a cardio workout

### Get Training Plans

 - [GET /api/v1/cardio/training-plans](https://developer.egym.com/equipment/partner-api/cardio-workouts/findalltrainingplans_1.md): This endpoint returns a user cardio training plan

## Open Exercise Workouts

### Create

 - [POST /api/v1/open-exercises/workouts](https://developer.egym.com/equipment/partner-api/open-exercise-workouts/create.md): This endpoint creates an open exercise workout

## Cardio Test

### Update Test

 - [PUT /api/v1/cardio/tests/{cardioTestId}](https://developer.egym.com/equipment/partner-api/cardio-test/updatetest.md): This endpoint should be invoked in order to create a new step into an ongoing cardio test

### Postpone Reminder

 - [PUT /api/v1/cardio/reminders](https://developer.egym.com/equipment/partner-api/cardio-test/postponereminder.md): This endpoint should be invoked in order to postpone the reminder of a cardio test

### Initialise Test

 - [POST /api/v1/cardio/tests](https://developer.egym.com/equipment/partner-api/cardio-test/initialisetest.md): This endpoint should be invoked in order to create and initialize a cardio test for a user

