Skip to content

A Ruby client for the Garmin Connect API. Provides access to health, fitness, activity, and device data from your Garmin account.

License

Notifications You must be signed in to change notification settings

DRBragg/garmin_connect

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GarminConnect

A Ruby client for the Garmin Connect API. Provides access to health, fitness, activity, and device data from your Garmin account.

Inspired by python-garminconnect, rebuilt idiomatically for Ruby.

Installation

Add to your Gemfile:

gem "garmin_connect"

Or install directly:

gem install garmin_connect

Quick Start

require "garmin_connect"

# Login with credentials (tokens are saved to ~/.garminconnect automatically)
client = GarminConnect::Client.new(email: "you@example.com", password: "your-password")
client.login

# Subsequent sessions resume from saved tokens (no re-login for ~1 year)
client = GarminConnect::Client.new
client.login

# Get today's stats
puts client.daily_summary
puts client.heart_rates
puts client.sleep_data
puts client.stress

Authentication

The gem uses the same OAuth flow as the Garmin Connect mobile app:

  1. SSO login with your email/password
  2. Exchange for an OAuth1 token (~1 year lifetime)
  3. Exchange OAuth1 for an OAuth2 Bearer token (~20 hours)
  4. Auto-refresh when the OAuth2 token expires

MFA Support

If your account has MFA enabled, the gem prompts via $stdin by default. You can provide a custom handler:

client = GarminConnect::Client.new(
  email: "you@example.com",
  password: "your-password",
  mfa_handler: -> { print "MFA code: "; gets.chomp }
)
client.login

Token Storage

Tokens are saved to ~/.garminconnect by default. You can customize this:

# Custom directory
client = GarminConnect::Client.new(token_dir: "/path/to/tokens")

# Base64-encoded string (useful for environment variables)
encoded = client.dump_tokens
client = GarminConnect::Client.new(token_string: encoded, token_dir: nil)

# Disable persistence entirely
client = GarminConnect::Client.new(token_dir: nil)

Token Interoperability

Token files are compatible with garth (the Python auth library). If you have existing tokens from the Python library, point token_dir at the same directory.

API Reference

User & Profile

client.user_settings           # Measurement system, sleep settings, etc.
client.user_profile            # Profile configuration
client.personal_information    # Age, gender, email, biometric profile
client.display_name            # "YourDisplayName"
client.full_name               # "Your Full Name"
client.unit_system             # "statute_us" or "metric"

Daily Health

client.daily_summary(date)      # Steps, calories, distance, active minutes
client.heart_rates(date)        # Heart rate data with resting HR
client.resting_heart_rate(start_date, end_date)
client.hrv(date)                # Heart rate variability
client.sleep_data(date)         # Sleep stages, duration, scores
client.stress(date)             # All-day stress levels
client.body_battery(start, end) # Body battery reports
client.body_battery_events(date)
client.steps_data(date)         # Steps chart data
client.floors(date)             # Floors climbed
client.respiration(date)        # Respiration rate
client.spo2(date)               # Blood oxygen
client.intensity_minutes(date)  # Intensity minutes
client.daily_events(date)       # Auto-detected activities
client.request_reload(date)     # Request data reload from device

Activities

# Listing
client.activities(start: 0, limit: 20)
client.activities_by_date("2026-01-01", "2026-01-31")
client.activity_count
client.last_activity

# Details
client.activity(activity_id)
client.activity_details(activity_id)
client.activity_splits(activity_id)
client.activity_typed_splits(activity_id)
client.activity_split_summaries(activity_id)
client.activity_weather(activity_id)
client.activity_hr_zones(activity_id)
client.activity_power_zones(activity_id)
client.activity_exercise_sets(activity_id)
client.activity_types

# CRUD
client.create_activity(payload_hash)
client.rename_activity(activity_id, "Morning Run")
client.update_activity_type(activity_id, type_dto)
client.delete_activity(activity_id)

# Download & Upload
client.download_activity(activity_id, format: :original) # :tcx, :gpx, :kml, :csv
client.upload_activity("/path/to/file.fit")

# Progress
client.progress_summary("2026-01-01", "2026-12-31", metric: "distance")

Body Composition & Weight

client.body_composition(start_date, end_date)
client.weigh_ins(start_date, end_date)
client.daily_weigh_ins(date)
client.add_weigh_in(84.5, date: "2026-02-11", unit_key: "kg")
client.delete_weigh_in(date, weight_pk)

Hydration

client.hydration(date)
client.log_hydration(250, date: "2026-02-11")   # 250 ml
client.log_hydration(-250, date: "2026-02-11")  # Subtract

Blood Pressure

client.blood_pressure(start_date, end_date)
client.log_blood_pressure(systolic: 120, diastolic: 80, pulse: 65)
client.delete_blood_pressure(date, version)

Advanced Metrics

client.max_metrics(date)                # VO2 Max
client.training_readiness(date)         # Training readiness score
client.training_status(date)            # Aggregated training status
client.endurance_score(date)            # Single day
client.endurance_score(start_date: s, end_date: e) # Date range
client.hill_score(date)
client.race_predictions                 # 5k, 10k, half, full marathon
client.fitness_age(date)
client.lactate_threshold                # Latest
client.lactate_threshold_history(start_date, end_date)
client.cycling_ftp                      # Functional Threshold Power

Historical Data

client.daily_steps(start_date, end_date)       # Auto-chunked at 28 days
client.weekly_steps(end_date, weeks: 52)
client.weekly_stress(end_date, weeks: 52)
client.weekly_intensity_minutes(start_date, end_date)

Devices & Gear

# Devices
client.devices
client.device_settings(device_id)
client.last_used_device
client.primary_training_device
client.device_solar_data(device_id, start_date, end_date)
client.device_alarms                     # Alarms across all devices

# Gear
client.gear
client.activity_gear(activity_id)
client.gear_stats(gear_uuid)
client.gear_defaults
client.set_gear_default(gear_uuid, activity_type)
client.link_gear(gear_uuid, activity_id)
client.unlink_gear(gear_uuid, activity_id)
client.gear_activities(gear_uuid)

Badges, Challenges & Goals

client.earned_badges
client.available_badges
client.in_progress_badges
client.adhoc_challenges
client.badge_challenges
client.available_badge_challenges
client.non_completed_badge_challenges
client.virtual_challenges
client.personal_records
client.goals(status: "active")

Workouts & Training Plans

client.workouts(start: 0, limit: 20)
client.workout(workout_id)
client.download_workout(workout_id)
client.create_workout(payload_hash)
client.scheduled_workout(id)
client.training_plans
client.training_plan(plan_id)
client.adaptive_training_plan(plan_id)

Wellness & Misc

client.menstrual_data(date)
client.menstrual_calendar(start_date, end_date)
client.pregnancy_summary
client.lifestyle_logging(date)
client.graphql(query_string, variables: {})

Error Handling

begin
  client.daily_summary
rescue GarminConnect::UnauthorizedError
  # Token expired or invalid
rescue GarminConnect::TooManyRequestsError
  # Rate limited, back off
rescue GarminConnect::NotFoundError
  # Resource doesn't exist
rescue GarminConnect::ServerError
  # Garmin's servers are having issues
rescue GarminConnect::HTTPError => e
  # Any other HTTP error
  puts e.status
  puts e.body
rescue GarminConnect::AuthenticationError
  # Login/token issues
rescue GarminConnect::Error
  # Catch-all for gem errors
end

Development

git clone https://github.com/drbragg/garmin_connect.git
cd garmin_connect
bundle install
bundle exec rspec

License

MIT License. See LICENSE.

About

A Ruby client for the Garmin Connect API. Provides access to health, fitness, activity, and device data from your Garmin account.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages