# Hevy Internal API Endpoints

Documented from dmzoneill/hevyapp-api reverse engineering, community projects, and Hevy-Insights.

## Authentication Methods

### Method 1: Web Login (Internal API)
```
POST https://api.hevyapp.com/login
Headers:
  x-api-key: shelobs_hevy_web
  Content-Type: application/json
  Origin: https://www.hevy.com
Body:
  { "emailOrUsername": "...", "password": "..." }
Response:
  { "auth_token": "..." }
```

### Method 2: Mobile Login (Internal API)
```
POST https://api.hevyapp.com/login
Headers:
  x-api-key: klean_kanteen_insulated
  Content-Type: application/json
Body:
  { "emailOrUsername": "...", "password": "..." }
Response:
  { "auth_token": "..." }
```

### Method 3: OAuth2 (used by Hevy-Insights)
```
POST https://api.hevyapp.com/v1/oauth/token
Headers:
  x-api-key: shelobs_hevy_web
  Content-Type: application/x-www-form-urlencoded
Body:
  grant_type=password&username=...&password=...
Response:
  { "access_token": "...", "token_type": "Bearer", ... }
```

### API Key Header Mapping

| Client | x-api-key Value | Auth Header |
|--------|----------------|-------------|
| Web app | `shelobs_hevy_web` | `auth-token` or `Authorization: Bearer ...` |
| Android | `klean_kanteen_insulated` | `auth-token` |
| Public API (Pro) | User's key | `api-key` |

---

## Documented Internal Endpoints

### GET /account
```
GET https://api.hevyapp.com/account
Auth: auth-token header
Response: {
  id, username, email, full_name, description,
  profile_pic, private_profile,
  follower_count, following_count,
  created_at, last_workout_at, is_coached, ...
}
```

### GET /workout_count
```
GET https://api.hevyapp.com/workout_count
Auth: auth-token header
Response: { "workout_count": 123 }
```

### GET /feed_workouts_paged
```
GET https://api.hevyapp.com/feed_workouts_paged
Auth: auth-token header
Response: {
  "workouts": [{ id, short_id, index, name, description,
    start_time (unix), end_time (unix),
    created_at, updated_at, routine_id,
    user_id, username, profile_image,
    exercises: [{ id, title, exercise_template_id,
      exercise_type, muscle_group,
      sets: [{ id, index, indicator, weight_kg, reps, rpe }]
    }]
  }]
}
```

### GET /routines_sync_batched
```
GET https://api.hevyapp.com/routines_sync_batched
Auth: auth-token header
Response: Batch of routines for sync (structure similar to /v1/routines)
```

### GET /user_preferences
```
GET https://api.hevyapp.com/user_preferences
Auth: auth-token header
Response: User settings (units, theme, workout preferences, etc.)
```

### GET /set_personal_records
```
GET https://api.hevyapp.com/set_personal_records
Auth: auth-token header
Response: Personal records per exercise
```

---

## Public API Endpoints (Pro Required)

Documented at: https://api.hevyapp.com/docs/

```
GET    /v1/workouts                    # Paginated workouts
POST   /v1/workouts                    # Create completed workout
GET    /v1/workouts/{id}               # Get workout
PUT    /v1/workouts/{id}               # Update workout
GET    /v1/workouts/count              # Workout count
GET    /v1/workouts/events             # Update/delete events

GET    /v1/routines                    # Paginated routines
POST   /v1/routines                    # Create routine
GET    /v1/routines/{id}               # Get routine
PUT    /v1/routines/{id}               # Update routine

GET    /v1/routine_folders             # Paginated folders
POST   /v1/routine_folders             # Create folder
GET    /v1/routine_folders/{id}        # Get folder

GET    /v1/exercise_templates          # Paginated exercises
POST   /v1/exercise_templates          # Create custom exercise
GET    /v1/exercise_templates/{id}     # Get exercise

GET    /v1/exercise_history/{id}       # Exercise history

GET    /v1/user/info                   # User info

GET    /v1/body_measurements           # Body measurements
POST   /v1/body_measurements           # Create measurement
GET    /v1/body_measurements/{date}    # Get by date
PUT    /v1/body_measurements/{date}    # Update measurement
```

---

## Webhook Support (v1 API)
```
POST   /v1/webhooks                    # Create webhook subscription
GET    /v1/webhooks                    # List subscriptions
DELETE /v1/webhooks/{id}               # Delete subscription
```

Webhooks fire on:
- `workout.created`
- `workout.updated`
- `workout.deleted`

No `workout.started` or `workout.live` webhook events exist.

---

## Endpoints TO DISCOVER (network capture)

These endpoint patterns are hypothesized based on the Wear OS live sync feature:

```
POST   /workout_sessions               # Start live workout
GET    /workout_sessions/active        # Get active session
PUT    /workout_sessions/{id}          # Update session state
DELETE /workout_sessions/{id}          # Cancel session
POST   /workout_sessions/{id}/sets     # Add set to session

POST   /live_workout/start             # Alternative naming
POST   /live_workout/log_set           # Log a set
GET    /live_workout/state             # Get current state
POST   /live_workout/finish            # Finish and save

wss://api.hevyapp.com/ws               # Possible WebSocket for real-time
wss://api.hevyapp.com/socket.io        # Socket.IO variant
```

Also look for Firebase Realtime Database or Firestore usage:
- Search for `firebaseio.com` in bundle
- Check for `firebase.database()` references

---

## Known API Quirks

1. `@` in text fields causes silent failures (HevySharp workaround: replace with `at`)
2. POST/PUT bodies must be wrapped in resource key: `{"workout": {...}}`
3. PUT must omit read-only fields (`id`, `created_at`, `updated_at`)
4. `x-api-key` header is required even for authenticated requests
5. Auth tokens expire ~15-20 minutes for web sessions
6. Internal API rate limits unknown but likely more lenient than public v1
