What active_hours measures
active_hours is the number of distinct clock hours in the local day during which the user moved. It is an integer from 0 to 18. Where steps measures how much a user moved, active hours measures how much of the day the movement was spread across.
| Field | active_hours |
|---|---|
| Unit | Hours, 0 to 18 |
| Reported | Daily |
| Window | Midnight to midnight, profile local time |
| Wearable required | No |
| API | GET /api/v1/profile/biomarker/{externalId}?categories=activity&types=active_hours plus a date range |
| Webhook | BiomarkerCreatedIntegrationEvent. Entries update in place, upsert on id. |
Data sources
Active hours has no sensor of its own and no platform equivalent. It is derived entirely from step samples.
| Platform | Derived from | Notes |
|---|---|---|
| iOS, HealthKit | stepCount | Same samples as the steps biomarker |
| Android, Health Connect | StepsRecord | Same samples as the steps biomarker |
| Android, device sensor | Phone step counter | SDK fallback, ranks last |
| Direct integrations | Provider-dependent | Wherever the provider supplies steps |
| Wearable required | No |
Apple’s Stand hours, Fitbit’s hourly activity, and Garmin’s move bar are related ideas but are not what this field reports, and none of them is read. Because it derives from steps, active hours comes from whichever source won best-source selection for activity that day.
How Sahha calculates active_hours
- Take the winning source’s step samples for the local day and group them by the clock hour their end time falls in.
- An hour is active when its samples total at least 100 steps and at least 60 seconds of recorded stepping.
- Count the active hours and cap the result at 18.
A day with step data but no hour reaching 100 steps produces an active hours value of 0. A day with no step data from the winning source produces no biomarker at all. Absence means no data, not zero.
Interpreting the value
What counts as a lot. The Activity Score goal is 10 hours. As a rough guide rather than a Sahha population figure, a day with a walking commute, a lunch walk, and a few breaks lands around 6 to 10. A desk day with one workout lands around 2 to 4.
Read it next to steps. The two together describe the pattern:
| Steps | Active hours | What it usually means |
|---|---|---|
| High | High | Movement throughout the day |
| High | Low | One long session, then sitting |
| Low | High | Frequent short movement, little sustained walking |
| Low | Low | A sedentary day, or the phone stayed on the desk |
Today’s value is partial. At 11am the maximum possible is roughly 3 or 4. Do not compare today’s count against yesterday’s total.
Phone-only users read low. Steps taken without the phone in a pocket or bag are not recorded, and that is most often short movement around the home or office, which is exactly what this metric rewards. A watch wearer with the same behaviour will show more active hours.
Related scores and insights
Score factor. Active hours is a factor, under the name active_hours, in the Activity, Wellbeing, and Mental Wellbeing scores, with unit hour and goal 10. Credit is linear, with a floor so that zero active hours still earns partial credit:
| Active hours | Factor score |
|---|---|
| 0 | 0.23 |
| 2 | 0.38 |
| 4 | 0.54 |
| 6 | 0.69 |
| 8 | 0.85 |
| 10 and above | 1.00 |
For the current day the factor is projected forward, the same way as steps: the waking day is treated as 8am to midnight and the count so far is divided by the fraction that has elapsed. The stored factor value and the biomarker are never scaled.
Trend. An active_hours trend is available on the factor score, on a 0 to 1 index.
Comparison. There is no comparison insight for active hours. Use steps for population benchmarks.
Use cases
A break-up-sitting nudge. Query today’s active hours around midday. If it is at or below 1 by 1pm on a weekday, send one prompt for a short walk. Cap it at one prompt per day. The reward loops tutorial shows how to derive the threshold from the user’s own history instead of a fixed number.
GET /api/v1/profile/biomarker/{externalId}?categories=activity&types=active_hours&startDateTime=2026-09-01&endDateTime=2026-09-02A “why did my Activity Score drop” explanation. When steps are near baseline and active hours are well below it, the movement was concentrated. That is a sentence you can show the user, and it is the most common reason a good step day gets a middling score.
A consistency streak. Count days with active hours at or above the user’s recent typical value. Unlike a step streak, one long walk does not satisfy it.
Limitations
- The 100-step threshold is per hour, per source. An hour with 90 steps from the phone and 40 from a watch is not active. The two are never combined.
- Hours follow the sample end time. A walk from 9:55 to 10:05 is credited to the hour its sample ends in, which depends on how the source split the recording.
- The cap hides late nights. Someone active from 6am to midnight scores 18, the same as someone active from 6am to 11pm. Do not use active hours to detect very long days.
- No data is not zero. A missing biomarker means the winning source recorded no steps at all that day. Show it as unknown.
- It is not Apple Stand hours. Users who compare the two numbers will find they differ. Stand hours count a minute of standing; active hours require 100 steps.
Related guides
- Steps for the volume this metric is derived from and how the source is chosen
- Active duration for total minutes of movement rather than hours touched
- Activity intensity for sedentary time, the inverse view of the same day
- Activity Score explained for how the six factors combine
- Data dictionary in the developer docs