A modern Home Assistant custom integration for Oura Ring using the v2 API with OAuth2 authentication.
- OAuth2 Authentication: Secure authentication using Home Assistant's application credentials
- Comprehensive Data: Access all Oura Ring data including sleep, readiness, and activity metrics
- Historical Data Loading: Automatically loads 30 days of historical data on first setup (configurable 7-90 days)
- HACS Compatible: Easy installation and updates via HACS
- Modern Architecture: Built following the latest Home Assistant standards (2025)
- Efficient Updates: Uses DataUpdateCoordinator for optimal data fetching
- Sleep Score
- Total Sleep Duration
- Deep Sleep Duration
- REM Sleep Duration
- Light Sleep Duration
- Awake Time
- Sleep Efficiency
- Restfulness
- Sleep Latency
- Sleep Timing
- Deep Sleep Percentage
- REM Sleep Percentage
- Time in Bed
- Readiness Score
- Temperature Deviation
- Resting Heart Rate Score (contribution score, not actual BPM)*
- HRV Balance Score (contribution score, not actual HRV)*
Note: Sensors marked with * may be unavailable if Oura doesn't have sufficient data to calculate the contributor score.
- Activity Score
- Steps
- Active Calories
- Total Calories
- Target Calories
- High Activity Time
- Medium Activity Time
- Low Activity Time
- Current Heart Rate (latest reading)
- Average Heart Rate (from recent readings)
- Minimum Heart Rate (from recent readings)
- Maximum Heart Rate (from recent readings)
- Average Sleep HRV (heart rate variability during sleep)
Total: 30 sensors
Click the button above to add this repository to HACS, or follow these manual steps:
- Open HACS in your Home Assistant instance
- Click on "Integrations"
- Click the three dots in the top right corner
- Select "Custom repositories"
- Add this repository URL:
https://github.com/louispires/oura-v2-custom-component - Select category: "Integration"
- Click "Add"
- Find "Oura Ring" in the integration list and click "Download"
- Restart Home Assistant
- Copy the
custom_components/ouradirectory to yourconfig/custom_components/directory - Restart Home Assistant
- Go to Oura Cloud
- Sign in with your Oura account
- Click "Create a New Application"
- Fill in the application details:
- Application Name: Home Assistant
- Application Website: Your Home Assistant URL
- Redirect URI:
https://my.home-assistant.io/redirect/oauth
- Save the Client ID and Client Secret
- In Home Assistant, go to Settings → Devices & Services
- Click on Application Credentials (in the top menu)
- Click Add Application Credential
- Note: You may see either a dropdown to select "Oura Ring" OR a generic form - both work!
- Enter your Client ID and Client Secret from Step 1
- Click Create
Important: Application Credentials is just for storing OAuth credentials. You won't see Oura Ring listed as an active integration here.
Now you can add the actual integration:
- In Home Assistant, go to Settings → Devices & Services
- Click Add Integration
- Search for "Oura Ring" - you should see it here!
- Click on it and follow the OAuth2 authentication flow
- You'll be redirected to Oura's website to authorize the integration
- After authorization, you'll be redirected back to Home Assistant
- The integration will be configured and sensors will start appearing
Once configured, sensors will appear under the Oura Ring integration. You can use these sensors in:
- Dashboards: Display your sleep, readiness, and activity data with beautiful charts
- Automations: Trigger actions based on your Oura Ring data
- Scripts: Use sensor values in your scripts
- Templates: Create custom sensors based on Oura data
For dashboard examples using ApexCharts, see the Dashboard Examples section below.
automation:
- alias: "Low Sleep Alert"
trigger:
- platform: numeric_state
entity_id: sensor.oura_sleep_score
below: 70
action:
- service: notify.mobile_app
data:
message: "Your sleep score is low. Consider resting today."The integration polls the Oura API with a configurable update interval (default: 5 minutes). You can configure this interval:
- Go to Settings → Devices & Services
- Find "Oura Ring" and click CONFIGURE
- Set your desired update interval (1-60 minutes)
- Set historical data days (7-90 days) - only loaded on first setup
- Click SUBMIT
The integration will automatically reload with the new interval. The default 5-minute interval is optimized to:
- Provide timely updates
- Minimize API calls
- Respect Oura's rate limits
On first setup, the integration automatically fetches historical data (default: 30 days) to populate your dashboards immediately. This means:
✅ Instant dashboard population - Your charts show data from day one
✅ No waiting period - See trends and patterns immediately
✅ One-time fetch - Historical data is only loaded once during initial setup
✅ Configurable - Choose 7-90 days of history based on your needs
After the initial historical load, the integration fetches only new data during regular updates (every 5 minutes by default), keeping API usage minimal.
The integration uses Home Assistant's Long-Term Statistics system to store historical data:
- Initial Setup: When you first add the integration, it fetches 30 days (or your configured amount) of historical data
- Statistics Import: All historical data points are imported as long-term statistics with proper timestamps
- Database Storage: Data is stored in Home Assistant's statistics database (separate from state history)
- Immediate Availability: All history graphs, ApexCharts, and Energy dashboard cards can access this data immediately
- Daily Updates: Ongoing updates only fetch new data (typically 1 day), which is much more efficient
Benefits of Long-Term Statistics:
- 📊 Works with all history visualization cards (ApexCharts, History Graph, Statistics Graph)
- 💾 Efficient database storage (optimized for long-term data)
- 🔄 Properly timestamped (each data point has the correct historical date)
- ⚡ Fast queries (statistics database is optimized for time-series data)
- 🎯 No fake "state changes" - clean, accurate historical data
The apexcharts-card is a highly customizable graphing card that works great with Oura data. Install it via HACS first.
Track your sleep, readiness, and activity scores over the past week:
yaml
type: custom:apexcharts-card
header:
show: true
title: Oura Scores
show_states: true
colorize_states: true
graph_span: 7d
span:
end: day
all_series_config:
type: column
opacity: 0.7
stroke_width: 8
group_by:
func: last
duration: 1d
series:
- entity: sensor.oura_sleep_score
name: Sleep
color: "#5E97F6"
- entity: sensor.oura_readiness_score
name: Readiness
color: "#FFA600"
- entity: sensor.oura_activity_score
name: Activity
color: "#00D9FF"
yaxis:
- min: 0
max: 100
apex_config:
tickAmount: 5Detailed sleep breakdown with durations:
yaml
type: custom:apexcharts-card
graph_span: 7d
header:
show: true
show_states: true
colorize_states: true
title: Sleep
standard_format: true
yaxis:
- id: left
opposite: false
min: 0
max: 10
apex_config:
title:
text: Total Sleep
- id: right
opposite: true
min: 0
max: 8
apex_config:
title:
text: Breakdown
series:
- entity: sensor.oura_sleep_score
name: Score
show:
in_chart: false
color: white
- entity: sensor.oura_average_heart_rate
name: Avg HR
show:
in_chart: false
- entity: sensor.oura_minimum_heart_rate
name: Lowest HR
show:
in_chart: false
- entity: sensor.oura_time_in_bed
name: In Bed
color: grey
type: area
show:
in_chart: true
in_header: false
yaxis_id: left
group_by:
duration: 1d
func: last
- entity: sensor.oura_total_sleep_duration
name: Total Sleep
color: purple
type: area
show:
in_chart: true
in_header: false
yaxis_id: left
group_by:
duration: 1d
func: last
- entity: sensor.oura_rem_sleep_duration
name: REM
color: "#20bf6b"
type: column
show:
in_chart: true
in_header: false
yaxis_id: right
group_by:
duration: 1d
func: last
- entity: sensor.oura_deep_sleep_duration
name: Deep
color: "#45aaf2"
type: column
show:
in_chart: true
in_header: false
yaxis_id: right
group_by:
duration: 1d
func: last
- entity: sensor.oura_light_sleep_duration
name: Light
color: "#fed330"
type: column
show:
in_chart: true
in_header: false
yaxis_id: right
group_by:
duration: 1d
func: last
- entity: sensor.oura_awake_time
name: Awake
color: "#fc5c65"
type: column
show:
in_chart: true
in_header: false
yaxis_id: right
group_by:
duration: 1d
func: lastMonitor your sleep efficiency over time:
yaml
type: custom:apexcharts-card
header:
show: true
title: Sleep Efficiency
show_states: true
graph_span: 14d
span:
end: day
series:
- entity: sensor.oura_sleep_efficiency
name: Efficiency
color: '#4CAF50'
stroke_width: 3
type: line
curve: smooth
group_by:
func: last
duration: 1d
yaxis:
- min: 0
max: 100
apex_config:
tickAmount: 5Track heart rate scores and HRV:
yaml
type: custom:apexcharts-card
header:
show: true
title: Heart Health
show_states: true
graph_span: 7d
span:
end: day
series:
- entity: sensor.oura_resting_heart_rate
name: Resting HR
color: "#E91E63"
stroke_width: 2
type: line
curve: smooth
group_by:
func: last
duration: 1d
yaxis_id: hr
- entity: sensor.oura_hrv_balance
name: HRV Balance
color: "#00BCD4"
stroke_width: 2
type: line
curve: smooth
group_by:
func: last
duration: 1d
yaxis_id: hrv
- entity: sensor.oura_average_sleep_hrv
name: Sleep HRV
color: "#287233"
stroke_width: 2
type: line
curve: smooth
group_by:
func: last
duration: 1d
yaxis_id: hrv
yaxis:
- id: hr
min: 40
max: 80
apex_config:
tickAmount: 4
title:
text: BPM
- id: hrv
opposite: true
min: 0
max: 100
apex_config:
tickAmount: 4
title:
text: HRVyaml
type: custom:apexcharts-card
header:
show: true
title: Daily Activity
show_states: true
graph_span: 7d
span:
end: day
series:
- entity: sensor.oura_steps
name: Steps
color: '#4CAF50'
stroke_width: 2
type: column
opacity: 0.7
group_by:
func: last
duration: 1d
yaxis_id: steps
- entity: sensor.oura_active_calories
name: Calories
color: '#FF9800'
stroke_width: 2
type: line
curve: smooth
group_by:
func: last
duration: 1d
yaxis_id: calories
yaxis:
- id: steps
apex_config:
tickAmount: 4
title:
text: Steps
- id: calories
opposite: true
apex_config:
tickAmount: 4
title:
text: CaloriesTrack body temperature trends:
yaml
type: custom:apexcharts-card
header:
show: true
title: Temperature Deviation
show_states: true
graph_span: 30d
span:
end: day
series:
- entity: sensor.oura_temperature_deviation
name: Deviation
color: '#FF5722'
stroke_width: 2
type: line
curve: smooth
group_by:
func: last
duration: 1d
yaxis:
- min: -2
max: 2
apex_config:
tickAmount: 4
decimalsInFloat: 1For a quick overview without ApexCharts:
yaml
type: entities
title: Oura Ring Summary
entities:
- entity: sensor.oura_sleep_score
secondary_info: last-changed
name: Sleep Score
- entity: sensor.oura_readiness_score
secondary_info: last-changed
name: Readiness Score
- entity: sensor.oura_activity_score
secondary_info: last-changed
name: Activity Score
- type: divider
- entity: sensor.oura_total_sleep_duration
secondary_info: last-changed
name: Total Sleep
- entity: sensor.oura_time_in_bed
name: Time in Bed
secondary_info: last-changed
- entity: sensor.oura_deep_sleep_duration
secondary_info: last-changed
name: Deep Sleep
- entity: sensor.oura_rem_sleep_duration
secondary_info: last-changed
name: REM Sleep
- type: divider
- entity: sensor.oura_steps
secondary_info: last-changed
name: Steps Today
- entity: sensor.oura_active_calories
secondary_info: last-changed
name: Active Calories
- entity: sensor.oura_current_heart_rate
secondary_info: last-changed
- entity: sensor.oura_average_heart_rate
secondary_info: last-changed
- entity: sensor.oura_minimum_heart_rate
secondary_info: last-changed
- entity: sensor.oura_maximum_heart_rate
secondary_info: last-changedVisual representation of your scores:
yaml
type: horizontal-stack
cards:
- type: gauge
entity: sensor.oura_sleep_score
name: Sleep
needle: true
min: 0
max: 100
severity:
green: 85
yellow: 70
red: 0
- type: gauge
entity: sensor.oura_readiness_score
name: Readiness
needle: true
min: 0
max: 100
severity:
green: 85
yellow: 70
red: 0
- type: gauge
entity: sensor.oura_activity_score
name: Activity
needle: true
min: 0
max: 100
severity:
green: 85
yellow: 70
red: 0If you encounter authentication issues:
- Verify your Client ID and Client Secret are correct
- Ensure the Redirect URI matches exactly in both Oura Cloud and Home Assistant
- Check Home Assistant logs for specific error messages
- Try removing and re-adding the integration
If some sensors are not appearing:
- Ensure your Oura Ring is synced with the Oura app
- Check that you have recent data in the Oura app
- Wait for the next update cycle (default: 5 minutes)
- Check Home Assistant logs for errors
Some sensors may show as "unavailable" when Oura doesn't have sufficient data:
- Resting Heart Rate Score: Requires sufficient heart rate measurements during rest periods
- HRV Balance Score: Requires sufficient HRV data collection (usually from sleep)
This is normal behavior, especially:
- In the first few days of wearing your ring
- After periods of not wearing the ring
- If you haven't had sufficient sleep for HRV measurements
- During data processing delays
These sensors will automatically become available once Oura collects and processes the necessary data.
If you see rate limiting errors:
- The integration is designed to respect Oura's API limits
- Avoid manually triggering updates too frequently
- Check if you have other integrations also accessing the Oura API
This integration is built using modern Home Assistant patterns:
- OAuth2 Flow: Uses Home Assistant's built-in OAuth2 implementation
- DataUpdateCoordinator: Efficient data fetching and update management
- Type Hints: Full type hint coverage for better code quality
- Async: All operations are asynchronous
- Error Handling: Comprehensive error handling and logging
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
- Installation Guide - Detailed setup instructions
- Quick Reference - Quick reference for common tasks
- Troubleshooting - Common issues and solutions
- Redirect URI Fix - OAuth redirect URI troubleshooting
- Project Summary - Technical overview and architecture
This project is licensed under the MIT License.
- Original Oura Component: nitobuendia/oura-custom-component
- Oura Ring API: Oura Cloud API Documentation
- Development assisted by: Claude Sonnet 4.5 (Anthropic AI)
If this integration is helpful, feel free to Buy Me a Coffee; or check other options on the Github ❤️ Sponsor link on the top of this page.
If you encounter any issues or have questions:
- Check the Issues page
- Create a new issue with detailed information
- Include relevant logs from Home Assistant
This is an unofficial integration and is not affiliated with or endorsed by Oura Health Oy.