ExOura (ex_oura v2.0.2)
View SourceDocumentation for Oura API
Configuration
ExOura can be configured in your config files:
config :ex_oura,
timeout: 10_000,
rate_limiting: [
enabled: true, # Enable/disable rate limiting (default: true)
daily_limit: 5000, # Daily request limit (default: 5000)
per_minute_limit: 300 # Per-minute request limit (default: 300)
],
retry: [
max_retries: 3 # Maximum retry attempts (default: 3)
],
oauth2: [
client_id: "your_client_id",
client_secret: "your_client_secret",
redirect_uri: "your_redirect_uri"
]OAuth2 Authentication (Recommended)
ExOura supports OAuth2 authentication, which is the recommended approach since Personal Access Tokens are being deprecated by Oura by the end of 2025.
OAuth2 Setup
- Register your application at https://cloud.ouraring.com/oauth/applications
- Configure your OAuth2 credentials (see Configuration above)
- Implement the OAuth2 flow in your application
OAuth2 Flow Example
# Step 1: Generate authorization URL
authorization_url = ExOura.OAuth2.authorization_url([
scopes: ["daily", "heartrate", "personal"],
state: "your_state_parameter"
])
# Step 2: After user authorizes, exchange code for tokens
{:ok, tokens} = ExOura.OAuth2.get_token("authorization_code_from_callback")
# Step 3: Use tokens with the client
{:ok, client} = ExOura.Client.start_link([
access_token: tokens.access_token,
refresh_token: tokens.refresh_token
])
# Step 4: Make API calls
{:ok, activity_data} = ExOura.multiple_daily_activity(~D[2025-01-01], ~D[2025-01-31])
# Step 5: Refresh tokens when needed
if ExOura.OAuth2.token_expired?(tokens) do
{:ok, new_tokens} = ExOura.OAuth2.refresh_token(tokens.refresh_token)
# Update your stored tokens...
endRate Limiting
Rate limiting is enabled by default and follows the Oura API limits:
- 5000 requests per day
- 300 requests per minute
You can disable rate limiting entirely by setting enabled: false in the configuration,
or adjust the limits if needed. When disabled, the client will not track or enforce
any rate limits, but will still handle rate limit responses from the API server
in the retry logic.
Retry Logic
ExOura uses Req's built-in retry mechanism with intelligent error handling:
- Automatically retries on server errors (5xx), timeouts (408), and rate limits (429)
- Exponential backoff with jitter to avoid thundering herd problems
- Configurable maximum retry attempts
- Does not retry on client errors (4xx except 408 and 429)
Summary
Functions
Fetches all daily activity data across all pages for the given date range.
Fetches all daily readiness data across all pages for the given date range.
Fetches all daily sleep data across all pages for the given date range.
Fetches all sleep data across all pages for the given date range.
Fetches all workout data across all pages for the given date range.
Generates the OAuth2 authorization URL to redirect users to.
Returns all available OAuth2 scopes.
Create Webhook Subscription
Returns the default OAuth2 scopes used when none are specified.
Delete Webhook Subscription
Exchanges an authorization code for access and refresh tokens.
Get Webhook Subscription
List Webhook Subscription
Retrieves multiple daily activity records for a specified date range.
Multiple Daily Cardiovascular Age
Multiple Daily Readiness
Multiple Daily Resilience
Retrieves multiple daily sleep records for a specified date range.
Multiple Daily Sp02
Multiple Daily Stress
Multiple Enhanced Tag
Multiple Heart Rate
Multiple Rest Mode Period
Multiple Ring Configuration
Multiple Sleep Time
Multiple Tag (Deprecated)
Retrieves multiple workout records for a specified date range.
Refreshes an access token using a refresh token.
Renew Webhook Subscription
Sets the OAuth2 authentication configuration for the client in situations where we want to reconfigure the client at runtime.
Retrieves a single daily activity record by its document ID.
Single Daily Cardiovascular Age
Single Daily Readiness
Single Daily Resilience
Retrieves a single daily sleep record by its document ID.
Single Daily Sp02
Single Daily Stress
Single Enhanced Tag
Retrieves personal information for the authenticated user.
Single Rest Mode Period
Single Ring Configuration
Single Session
Single Sleep
Single Sleep Time
Single Tag (Deprecated)
Single Vo2 Max
Retrieves a single workout record by its document ID.
Returns a stream of all daily activity data for the given date range.
Returns a stream of all workout data for the given date range.
Checks if an access token is expired or will expire soon.
Update Webhook Subscription
Types
@type document_id() :: String.t()
@type end_date() :: Date.t()
@type error() :: {:error, ExOura.Client.HTTPValidationError.t()}
@type next_token() :: String.t() | nil
@type opts() :: Keyword.t()
@type start_date() :: Date.t()
@type webhook() ::
ExOura.Client.CreateWebhookSubscriptionRequest.t()
| ExOura.Client.UpdateWebhookSubscriptionRequest.t()
@type webhook_id() :: String.t()
Functions
@spec all_daily_activity(start_date(), end_date(), opts()) :: {:ok, list()} | error()
Fetches all daily activity data across all pages for the given date range.
This is a convenience function that automatically handles pagination using the Pagination module.
Examples
iex> ExOura.all_daily_activity(~D[2025-01-01], ~D[2025-01-31])
{:ok, [%{id: "activity_1", ...}, %{id: "activity_2", ...}]}
@spec all_daily_readiness(start_date(), end_date(), opts()) :: {:ok, list()} | error()
Fetches all daily readiness data across all pages for the given date range.
@spec all_daily_sleep(start_date(), end_date(), opts()) :: {:ok, list()} | error()
Fetches all daily sleep data across all pages for the given date range.
@spec all_sleep(start_date(), end_date(), opts()) :: {:ok, list()} | error()
Fetches all sleep data across all pages for the given date range.
@spec all_workouts(start_date(), end_date(), opts()) :: {:ok, list()} | error()
Fetches all workout data across all pages for the given date range.
Generates the OAuth2 authorization URL to redirect users to.
Examples
authorization_url = ExOura.authorization_url()
authorization_url = ExOura.authorization_url(scopes: ["daily", "heartrate"], state: "random_state")
Returns all available OAuth2 scopes.
Examples
ExOura.available_scopes()
# => ["email", "personal", "daily", "heartrate", "workout", "tag", "session", "spo2"]
@spec create_webhook_subscription(webhook(), opts()) :: {:ok, ExOura.Client.WebhookSubscriptionModel.t()} | error()
Create Webhook Subscription
Returns the default OAuth2 scopes used when none are specified.
Examples
ExOura.default_scopes()
# => ["personal", "daily"]
@spec delete_webhook_subscription(webhook_id(), opts()) :: :ok | error()
Delete Webhook Subscription
Exchanges an authorization code for access and refresh tokens.
Examples
{:ok, tokens} = ExOura.get_token("authorization_code_from_callback")
@spec get_webhook_subscription(webhook_id(), opts()) :: {:ok, ExOura.Client.WebhookSubscriptionModel.t()} | error()
Get Webhook Subscription
@spec list_webhook_subscriptions(opts()) :: {:ok, [ExOura.Client.WebhookSubscriptionModel.t()]} | error()
List Webhook Subscription
@spec multiple_daily_activity( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailyActivityModel.t()} | error()
Retrieves multiple daily activity records for a specified date range.
Returns paginated daily activity data including steps, calories, activity score, and more. This is one of the most commonly used endpoints for tracking daily movement and activity patterns.
Parameters
start_date- Start date for the data range (Date struct, inclusive)end_date- End date for the data range (Date struct, inclusive)next_token- Optional pagination token from previous responseopts- Additional options (e.g., timeout)
Examples
{:ok, activities} = ExOura.multiple_daily_activity(~D[2025-01-01], ~D[2025-01-31])
activities.data |> Enum.each(&IO.inspect/1)
@spec multiple_daily_cardiovascular_age( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailyCardiovascularAgeModel.t()} | error()
Multiple Daily Cardiovascular Age
@spec multiple_daily_readiness( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailyReadinessModel.t()} | error()
Multiple Daily Readiness
@spec multiple_daily_resilience( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailyResilienceModel.t()} | error()
Multiple Daily Resilience
@spec multiple_daily_sleep( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailySleepModel.t()} | error()
Retrieves multiple daily sleep records for a specified date range.
Returns comprehensive sleep data including sleep score, duration, sleep stages, and sleep quality metrics. Essential for sleep tracking and analysis applications.
Parameters
start_date- Start date for the data range (Date struct, inclusive)end_date- End date for the data range (Date struct, inclusive)next_token- Optional pagination token from previous responseopts- Additional options (e.g., timeout)
Examples
{:ok, sleep_data} = ExOura.multiple_daily_sleep(~D[2025-01-01], ~D[2025-01-31])
sleep_data.data |> Enum.each(fn sleep ->
IO.puts("Sleep score: #{sleep.score}, Duration: #{sleep.total_sleep_duration}min")
end)
@spec multiple_daily_sp02( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailySpO2Model.t()} | error()
Multiple Daily Sp02
@spec multiple_daily_stress( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseDailyStressModel.t()} | error()
Multiple Daily Stress
@spec multiple_enhanced_tag( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseEnhancedTagModel.t()} | error()
Multiple Enhanced Tag
@spec multiple_heart_rate( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.TimeSeriesResponseHeartRateModel.t()} | error()
Multiple Heart Rate
@spec multiple_rest_mode_period( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseRestModePeriodModel.t()} | error()
Multiple Rest Mode Period
@spec multiple_ring_configuration( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseRingConfigurationModel.t()} | error()
Multiple Ring Configuration
@spec multiple_session( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseSessionModel.t()} | error()
Multiple Session
@spec multiple_sleep( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseSleepModel.t()} | error()
Multiple Sleep
@spec multiple_sleep_time( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseSleepTimeModel.t()} | error()
Multiple Sleep Time
@spec multiple_tag( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseTagModel.t()} | error()
Multiple Tag (Deprecated)
Note: This endpoint is deprecated. Use Enhanced Tags instead.
@spec multiple_vo2_max( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseVo2MaxModel.t()} | error()
Multiple Vo2 Max
@spec multiple_workout( start_date(), end_date(), next_token(), opts() ) :: {:ok, ExOura.Client.MultiDocumentResponseWorkoutModel.t()} | error()
Retrieves multiple workout records for a specified date range.
Returns both auto-detected and manually logged workout sessions with detailed metrics including duration, intensity, calories, and heart rate data.
Parameters
start_date- Start date for the data range (Date struct, inclusive)end_date- End date for the data range (Date struct, inclusive)next_token- Optional pagination token from previous responseopts- Additional options (e.g., timeout)
Examples
{:ok, workouts} = ExOura.multiple_workout(~D[2025-01-01], ~D[2025-01-31])
workouts.data |> Enum.each(fn workout ->
IO.puts("#{workout.activity}: #{workout.duration}s, #{workout.calories} cal")
end)
Refreshes an access token using a refresh token.
Examples
{:ok, new_tokens} = ExOura.refresh_token(old_tokens.refresh_token)
@spec renew_webhook_subscription(webhook_id(), opts()) :: {:ok, ExOura.Client.WebhookSubscriptionModel.t()} | error()
Renew Webhook Subscription
@spec set_auth_config(ExOura.OAuth2.oauth2_config()) :: :ok | {:error, term()}
Sets the OAuth2 authentication configuration for the client in situations where we want to reconfigure the client at runtime.
@spec single_daily_activity(document_id(), opts()) :: {:ok, ExOura.Client.DailyActivityModel.t()} | error()
Retrieves a single daily activity record by its document ID.
Use this for fetching detailed activity information for a specific day when you have the document ID.
Parameters
document_id- Unique identifier for the daily activity documentopts- Additional options (e.g., timeout)
Examples
{:ok, activity} = ExOura.single_daily_activity("daily_activity_2025-01-15")
IO.puts("Steps: #{activity.steps}")
@spec single_daily_cardiovascular_age(document_id(), opts()) :: {:ok, ExOura.Client.DailyCardiovascularAgeModel.t()} | error()
Single Daily Cardiovascular Age
@spec single_daily_readiness(document_id(), opts()) :: {:ok, ExOura.Client.DailyReadinessModel.t()} | error()
Single Daily Readiness
@spec single_daily_resilience(document_id(), opts()) :: {:ok, ExOura.Client.DailyResilienceModel.t()} | error()
Single Daily Resilience
@spec single_daily_sleep(document_id(), opts()) :: {:ok, ExOura.Client.DailySleepModel.t()} | error()
Retrieves a single daily sleep record by its document ID.
Use this for detailed sleep analysis of a specific night's sleep session.
Parameters
document_id- Unique identifier for the daily sleep documentopts- Additional options (e.g., timeout)
Examples
{:ok, sleep} = ExOura.single_daily_sleep("daily_sleep_2025-01-15")
IO.puts("Deep sleep: #{sleep.deep_sleep_duration} minutes")
@spec single_daily_sp02(document_id(), opts()) :: {:ok, ExOura.Client.DailySpO2Model.t()} | error()
Single Daily Sp02
@spec single_daily_stress(document_id(), opts()) :: {:ok, ExOura.Client.DailyStressModel.t()} | error()
Single Daily Stress
@spec single_enhanced_tag(document_id(), opts()) :: {:ok, ExOura.Client.EnhancedTagModel.t()} | error()
Single Enhanced Tag
Retrieves personal information for the authenticated user.
Returns demographic and physical information such as age, weight, height, and biological sex. Requires appropriate OAuth2 scopes ('personal' for demographics, 'email' for email).
Parameters
opts- Additional options (e.g., timeout)
Examples
{:ok, info} = ExOura.single_personal_info()
IO.puts("Age: #{info.age}, Weight: #{info.weight}kg")
@spec single_rest_mode_period(document_id(), opts()) :: {:ok, ExOura.Client.RestModePeriodModel.t()} | error()
Single Rest Mode Period
@spec single_ring_configuration(document_id(), opts()) :: {:ok, ExOura.Client.RingConfigurationModel.t()} | error()
Single Ring Configuration
@spec single_session(document_id(), opts()) :: {:ok, ExOura.Client.SessionModel.t()} | error()
Single Session
@spec single_sleep(document_id(), opts()) :: {:ok, ExOura.Client.SleepModel.t()} | error()
Single Sleep
@spec single_sleep_time(document_id(), opts()) :: {:ok, ExOura.Client.SleepTimeModel.t()} | error()
Single Sleep Time
@spec single_tag(document_id(), opts()) :: {:ok, ExOura.Client.TagModel.t()} | error()
Single Tag (Deprecated)
Note: This endpoint is deprecated. Use Enhanced Tags instead.
@spec single_vo2_max(document_id(), opts()) :: {:ok, ExOura.Client.Vo2MaxModel.t()} | error()
Single Vo2 Max
@spec single_workout(document_id(), opts()) :: {:ok, ExOura.Client.WorkoutModel.t()} | error()
Retrieves a single workout record by its document ID.
Use this for detailed analysis of a specific workout session including heart rate zones and comprehensive exercise metrics.
Parameters
document_id- Unique identifier for the workout documentopts- Additional options (e.g., timeout)
Examples
{:ok, workout} = ExOura.single_workout("workout_2025-01-15T14-30-00")
IO.puts("Average HR: #{workout.average_heart_rate} bpm")
@spec stream_daily_activity(start_date(), end_date(), opts()) :: Enumerable.t()
Returns a stream of all daily activity data for the given date range.
This is memory-efficient for processing large datasets as it streams data page by page rather than loading everything into memory at once.
Examples
iex> ExOura.stream_daily_activity(~D[2025-01-01], ~D[2025-01-31])
...> |> Stream.filter(& &1.score > 80)
...> |> Enum.take(10)
@spec stream_workouts(start_date(), end_date(), opts()) :: Enumerable.t()
Returns a stream of all workout data for the given date range.
Checks if an access token is expired or will expire soon.
Examples
ExOura.token_expired?(tokens)
ExOura.token_expired?(tokens, 3600) # 1 hour buffer
@spec update_webhook_subscription(webhook_id(), webhook(), opts()) :: {:ok, ExOura.Client.WebhookSubscriptionModel.t()} | error()
Update Webhook Subscription