ExOura.Workout (ex_oura v2.0.0)
View SourceAPI functions for retrieving Oura workout data.
Workout data includes both auto-detected workouts and manually entered workout sessions. This data provides detailed information about exercise sessions including duration, intensity, calories burned, heart rate zones, and workout-specific metrics.
Workout Types
The Oura Ring can detect various types of workouts:
- Auto-detected: Walking, running, cycling, and other activities automatically recognized
- Manual entries: Workouts manually logged by the user in the Oura app
- Heart rate based: Workouts identified through elevated heart rate patterns
Data Availability
Workout data is available shortly after the workout session ends. Historical workout data can be retrieved for up to 2 years.
Workout Metrics
Each workout record includes:
- Activity type and source (auto-detected vs manual)
- Start and end times
- Duration and intensity
- Calories burned
- Average and maximum heart rate
- Time in different heart rate zones
- Motion count and intensity patterns
Common Use Cases
- Exercise tracking and performance analysis
- Workout pattern identification
- Integration with fitness applications
- Building comprehensive health dashboards
- Correlating workouts with recovery metrics
OAuth2 Scope Required
Requires the "workout" scope to access workout data.
Rate Limits
All endpoints are subject to the standard Oura API rate limits:
- 5000 requests per day
- 300 requests per minute
Summary
Functions
Retrieves multiple workout records for a specified date range.
Retrieves a single workout record by its document ID.
Types
@type document_id() :: String.t()
@type end_date() :: Date.t()
@type next_token() :: String.t() | nil
@type opts() :: Keyword.t()
@type single_workout_response() :: {:ok, ExOura.Client.WorkoutModel.t()} | {:error, term()}
@type start_date() :: Date.t()
@type workout_response() :: {:ok, ExOura.Client.MultiDocumentResponseWorkoutModel.t()} | {:error, term()}
Functions
@spec multiple_workout(start_date(), end_date(), next_token(), opts()) :: workout_response()
Retrieves multiple workout records for a specified date range.
Returns paginated workout data including both auto-detected and manually logged workouts. This endpoint is essential for comprehensive exercise and activity tracking.
Parameters
start_date
- The start date for the data range (Date struct, inclusive)end_date
- The end date for the data range (Date struct, inclusive)next_token
- Optional token for pagination (from previous response)opts
- Optional keyword list of additional parameters
Options
:timeout
- Request timeout in milliseconds (defaults to configured timeout)
Returns
{:ok, response}
- Success with workout data and optional next_token{:error, reason}
- Error with details about what went wrong
Examples
# Get workouts for January 2025
{:ok, workouts} = ExOura.Workout.multiple_workout(
~D[2025-01-01],
~D[2025-01-31]
)
# Analyze workout patterns
workouts.data
|> Enum.group_by(& &1.activity)
|> Enum.each(fn {activity_type, workouts} ->
count = length(workouts)
avg_duration = workouts |> Enum.map(& &1.duration) |> Enum.sum() |> div(count)
IO.puts("#{activity_type}: #{count} workouts, avg duration: #{avg_duration}s")
end)
# Filter high-intensity workouts
high_intensity_workouts = workouts.data
|> Enum.filter(fn workout ->
workout.intensity == "high" or
(workout.average_heart_rate && workout.average_heart_rate > 150)
end)
# Handle pagination for large date ranges
{:ok, page1} = ExOura.Workout.multiple_workout(
~D[2024-01-01],
~D[2024-12-31]
)
if page1.next_token do
{:ok, page2} = ExOura.Workout.multiple_workout(
~D[2024-01-01],
~D[2024-12-31],
page1.next_token
)
end
Response Structure
The response contains:
data
- List of workout recordsnext_token
- Token for next page (nil if no more data)
Each workout record includes:
id
- Unique workout identifieractivity
- Type of activity (e.g., "walking", "running", "cycling")source
- How the workout was detected ("autodetected", "manual", "confirmed")day
- Date of the workout (YYYY-MM-DD)start_datetime
- When the workout startedend_datetime
- When the workout endedduration
- Workout duration in secondsintensity
- Intensity level ("low", "medium", "high")calories
- Calories burned during the workoutaverage_heart_rate
- Average heart rate (if available)maximum_heart_rate
- Peak heart rate (if available)heart_rate_zones
- Time spent in different HR zonesmotion_count
- Movement intensity data
@spec single_workout(document_id(), opts()) :: single_workout_response()
Retrieves a single workout record by its document ID.
Use this function when you need detailed information about a specific workout session. This is useful for in-depth analysis of individual exercise sessions.
Parameters
document_id
- The unique identifier for the workout documentopts
- Optional keyword list of additional parameters
Options
:timeout
- Request timeout in milliseconds (defaults to configured timeout)
Returns
{:ok, workout}
- Success with single workout record{:error, reason}
- Error with details (e.g., document not found)
Examples
# Get detailed workout information
{:ok, workout} = ExOura.Workout.single_workout("workout_2025-01-15T14-30-00")
IO.puts("Activity: #{workout.activity}")
IO.puts("Duration: #{workout.duration} seconds")
IO.puts("Calories: #{workout.calories}")
IO.puts("Average HR: #{workout.average_heart_rate} bpm")
# Analyze heart rate zones
case ExOura.Workout.single_workout("workout_id") do
{:ok, workout} ->
if workout.heart_rate_zones do
IO.puts("Time in zones: #{inspect(workout.heart_rate_zones)}")
end
{:error, reason} ->
IO.puts("Error: #{inspect(reason)}")
end
# Check workout source and intensity
{:ok, workout} = ExOura.Workout.single_workout("workout_id")
case {workout.source, workout.intensity} do
{"autodetected", "high"} ->
IO.puts("High-intensity workout automatically detected")
{"manual", _} ->
IO.puts("Manually logged workout")
_ ->
IO.puts("Regular detected workout")
end
Response Structure
Returns a single workout record with the same comprehensive metrics as described in
multiple_workout/4
, but without the pagination wrapper.
Workout Analysis Tips
- Use
source
to distinguish between auto-detected and manual workouts intensity
provides a quick assessment of workout difficulty- Heart rate data (when available) offers detailed cardiovascular insights
- Motion count can indicate movement patterns and workout variability