La API de Google Health proporciona extremos de agregación dedicados que agrupan y resumen los registros de salud en períodos. En lugar de recuperar y sumar registros sin procesar individuales en el cliente, usa los extremos de agregación para calcular métricas (como totales, promedios, mínimos y máximos) en un flujo de datos conciliado:
- El extremo
rollUpagrega datos en intervalos de tiempo físicos en UTC con una duración de ventana configurable en segundos (windowSize). - El extremo
dailyRollUpagrega datos de uno o más días calendario (windowSizeDays) con la hora civil relativa al reloj local del usuario.
Ambos extremos concilian automáticamente los datos superpuestos en los dispositivos conectados y excluyen los períodos en los que no se usa el wearable para los tipos de datos de wearables que admiten la detección de uso.
Compara los extremos de agregación
Elige el extremo de agregación que coincida con la forma en que tu aplicación agrupa y muestra las métricas de salud de series temporales:
| Función | Extremo rollUp |
Extremo dailyRollUp |
|---|---|---|
| Solicitud HTTP | POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:rollUp |
POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:dailyRollUp |
| Representación del tiempo | Tiempo físico en UTC (startTime y endTime en formato RFC 3339). |
Hora civil (start y end como objetos CivilDateTime). |
| Parámetro de ventana | windowSize (duración de la cadena obligatoria en segundos, mínimo "1s"). |
windowSizeDays (cantidad de días opcional, expresada como número entero; el valor predeterminado es 1). |
| Objeto de respuesta | RollupDataPoint |
DailyRollupDataPoint |
| Orden de las respuestas | Orden cronológico inverso (la ventana más reciente primero) | Orden cronológico inverso (la ventana más reciente primero) |
| Ideal para | Gráficos intradía, histogramas por hora o minuto, y análisis de UTC de duración fija. | Paneles diarios, tendencias de varios días y resúmenes que tienen en cuenta los viajes entre zonas horarias o el horario de verano. |
Ambos extremos aplican límites máximos de rango de consulta según el tipo de datos:
- Se aplica un rango de consulta máximo de 14 días a
calories-in-heart-rate-zone,heart-rate,active-minutesytotal-calories. - Se aplica un rango de consulta máximo de 90 días a todos los demás tipos de datos admitidos.
Para verificar qué tipos de datos admiten rollup y dailyRollup, consulta la referencia de los
tipos de datos de la API de Google Health.
Agrega datos en intervalos de tiempo físicos
Usa el extremo rollUp para agregar datos durante un tiempo físico range (en UTC) agrupados por una duración de ventana en segundos (windowSize).
Cuando llames al extremo rollUp, proporciona un cuerpo de solicitud JSON que contenga el
range cerrado-abierto (startTime inclusive, endTime exclusivo) y
windowSize. Ten en cuenta los siguientes requisitos de windowSize:
- La duración de
windowSizedebe ser de al menos 1 segundo ("1s"). La API rechaza las duraciones de menos de un segundo, cero o negativas con un error400 Bad Request(INVALID_ROLLUP_WINDOW). - Para evitar una distribución desigual de los datos agregados en los subbuckets, elige
un
windowSizeque sea igual o mayor que la resolución de almacenamiento subyacente del tipo de datos (como"60s"para intervalos de pasos de 1 minuto). Para obtener más detalles, consulta Período de resumen y resolución de almacenamiento.
Por ejemplo, la siguiente solicitud acumula los recuentos de pasos en intervalos de 1 minuto (60s):
Solicitud
POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:rollUp
Authorization: Bearer access-token
Accept: application/json
{
"range": {
"startTime": "2026-02-17T17:00:00Z",
"endTime": "2026-02-17T17:59:59Z"
},
"windowSize": "60s"
}Respuesta
{
"rollupDataPoints": [
{
"startTime": "2026-02-17T17:55:00Z",
"endTime": "2026-02-17T17:56:00Z",
"steps": {
"countSum": "72"
}
},
{
"startTime": "2026-02-17T17:54:00Z",
"endTime": "2026-02-17T17:55:00Z",
"steps": {
"countSum": "85"
}
},
...
]
}Agrega datos de varios días calendario
Usa el extremo dailyRollUp para agregar datos de un solo día calendario o de varios días (windowSizeDays). Proporciona la hora civil de cierre y apertura range (start y end) en el cuerpo de la solicitud. Según el tipo de datos, el extremo devuelve valores agregados, como la suma o el promedio de cada período civil.
Debido a que dailyRollUp opera en el tiempo civil con las compensaciones de UTC registradas con
cada dato, concilia automáticamente las duraciones variables de los días causadas por
las transiciones del horario de verano o los viajes por zonas horarias.
Por ejemplo, la siguiente solicitud agrega recuentos de pasos durante un solo día civil (windowSizeDays: 1):
Solicitud
POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:dailyRollUp
Authorization: Bearer access-token
Accept: application/json
{
"range": {
"start": {
"date": {
"year": 2026,
"month": 2,
"day": 26
},
"time": {
"hours": 0,
"minutes": 0,
"seconds": 0,
"nanos": 0
}
},
"end": {
"date": {
"year": 2026,
"month": 2,
"day": 26
},
"time": {
"hours": 23,
"minutes": 59,
"seconds": 59,
"nanos": 0
}
}
},
"windowSizeDays": 1
}Respuesta
{
"rollupDataPoints": [
{
"civilStartTime": {
"date": {
"year": 2026,
"month": 2,
"day": 26
},
"time": {}
},
"civilEndTime": {
"date": {
"year": 2026,
"month": 2,
"day": 26
},
"time": {
"hours": 23,
"minutes": 59,
"seconds": 59
}
},
"steps": {
"countSum": "3822"
}
}
]
}Agrega por familia de fuentes de datos
Tanto rollUp como dailyRollUp aceptan un campo dataSourceFamily opcional en
el cuerpo de la solicitud JSON para restringir la agregación a grupos de fuentes específicos:
- La opción
users/me/dataSourceFamilies/all-sources(predeterminada) agrega los datos conciliados en todas las fuentes propias y de terceros registradas. - La opción
users/me/dataSourceFamilies/google-wearablesagrega los datos registrados por los dispositivos de seguimiento wearable de Google y Fitbit, y excluye los datos registrados manualmente y los estimados por el teléfono. - La opción
users/me/dataSourceFamilies/google-sourcesagrega datos de fuentes propias de Google y Fitbit, incluidos los monitores de actividad wearable, Health Connect y las entradas manuales en apps propias.
Para conocer todos los requisitos de los parámetros y ver ejemplos de solicitudes y respuestas, consulta Filtra por familia de fuentes de datos en la guía Filtrar datos.
Período de resumen y resolución de almacenamiento
Aunque el extremo rollUp acepta cualquier windowSize de 1 segundo ("1s") o más, los diferentes tipos de datos registran y conservan las mediciones con diferentes tasas de muestreo o duraciones de intervalos en el almacenamiento subyacente. Por ejemplo,
las métricas de actividad física de wearables, como steps, distance,
active-minutes y active-energy-burned, suelen registrarse en intervalos de 1 minuto
(60s).
En la siguiente tabla, se enumeran las resoluciones de almacenamiento subyacentes y los valores mínimos recomendados de windowSize para los tipos de datos comunes:
| Resolución de almacenamiento | Mínimo recomendado: windowSize |
Tipos de datos |
|---|---|---|
1 segundo (1s) |
"1s" |
heart-rate |
1 minuto (60s) |
"60s" |
active-energy-burned, active-minutes, active-zone-minutes, altitude, calories-in-heart-rate-zone, distance, floors, steps, time-in-heart-rate-zone, total-calories |
Cuando se agregan tipos de datos de intervalo, el extremo rollUp coloca cada dato registrado en el bucket que contiene el startTime del dato. La API
no divide, interpola ni distribuye datos de intervalos en buckets de
subintervalos.
Si especificas un windowSize que es menor que el intervalo de almacenamiento de datos
subyacente (por ejemplo, si solicitas una ventana de 10 segundos para steps almacenado en
intervalos de 1 minuto), ocurrirá lo siguiente:
- El primer subintervalo que coincide con el
startTimedel intervalo (por ejemplo, de10:00:00a10:00:10) recibe el recuento acumulado de todo el minuto (por ejemplo, los 100 pasos registrados para ese minuto). - Los subbuckets restantes dentro de ese mismo minuto (de
10:00:10a10:00:20, de10:00:20a10:00:30, etcétera) no reciben datos, ya que no comienza ningún intervalo dentro de esas ventanas.
Esto produce datos con picos en los que el valor de todo el intervalo se concentra en la primera subventana, como se muestra en la Figura 1.
Para obtener agregaciones significativas y distribuidas de manera uniforme, siempre establece windowSize en una duración igual o mayor que la resolución de almacenamiento subyacente del tipo de datos de destino (por ejemplo, "60s" o más para steps). Para conocer la resolución de almacenamiento y la ventana de resumen mínima recomendada de cada tipo de datos, consulta la referencia de los tipos de datos de la API de Google Health.
Agrupación en buckets cuando el rango no es un múltiplo del tamaño de la ventana
Si el intervalo solicitado no es un múltiplo exacto de windowSize (o
windowSizeDays), el intervalo cronológico final se trunca en el extremo superior
del intervalo y abarca una duración más corta que el tamaño de la ventana. La API acepta tu solicitud sin modificaciones y no realiza redondeos, cambios de hora ni interpolación de datos.
Para abarcar todo el rango solicitado, la API usa la división de límite superior para calcular la cantidad total de ventanas de agregación:
Number of windows = ceiling(Range duration / Window size)
Cada bucket comienza de forma secuencial desde el principio de tu rango. Si agregas otra ventana de tamaño completo que se extiende más allá de la hora de finalización solicitada, la ventana final se trunca (se fija) en la hora de finalización del intervalo.
Cómo funciona la asignación de buckets
Cuando solicitas resúmenes con rangos no divisibles, la API aplica las siguientes reglas:
- La asignación de buckets comienza al principio del rango solicitado
(
range.startTimeorange.start) y avanza según el tamaño de la ventana (windowSizeowindowSizeDays). - El bucket cronológico final se limita al final del rango solicitado (
range.endTimeorange.end), lo que abarca una duración más corta que el tamaño de la ventana solicitada. - Los objetos
RollupDataPointoDailyRollupDataPointque se devuelven incluyen sus propias marcas de tiempo de inicio y finalización explícitas, que puedes usar para inspeccionar la duración real del bucket truncado. - Debido a que la API devuelve datos de resumen en orden cronológico inverso (primero los más recientes), el bucket cronológico final (el bucket truncado) aparece como el primer elemento (
index 0) en la lista que se muestra.
En la figura 2, se ilustra cómo la API agrupa un rango no divisible hacia adelante desde
range.startTime, fija el bucket final en range.endTime y devuelve los
buckets resultantes en orden cronológico inverso.
Ejemplo de un rango de 12 minutos con una ventana de 5 minutos
Supongamos que un cliente solicita un resumen en un intervalo de 12 minutos con un windowSize de 5 minutos ("300s"):
- El valor de
range.startTimees10:00:00Z. - El valor de
range.endTimees10:12:00Z, para una duración total de 12 minutos. - El valor de
windowSizees"300s"(5 minutos).
Como 12 minutos no es un múltiplo exacto de 5 minutos (12 = 5 * 2 + 2),
la API calcula la cantidad de ventanas como ceiling(12 / 5) = 3. Esto produce
tres buckets cronológicos:
| Bucket | Intervalo | Duración | Estado del período |
|---|---|---|---|
| Bucket 1 | [10:00:00Z, 10:05:00Z) |
5 minutos | Ventana completa |
| Bucket 2 | [10:05:00Z, 10:10:00Z) |
5 minutos | Ventana completa |
| Bucket 3 | [10:10:00Z, 10:12:00Z) |
2 minutos | Se truncó en range.endTime |
Impacto en los valores agregados
Debido a que la ventana cronológica final tiene una duración más corta, las métricas aditivas (como la suma o el recuento de pasos) son más bajas en el bucket truncado debido al período más corto.
Si un usuario camina a un ritmo constante de 100 pasos por minuto durante todo este intervalo de 12 minutos, los buckets contienen los siguientes totales:
- El bucket 1 (de
10:00:00Za10:05:00Z) registra 500 pasos (5 minutos a 100 pasos por minuto). - El intervalo 2 (de
10:05:00Za10:10:00Z) registra 500 pasos (5 minutos a 100 pasos por minuto). - El intervalo 3 (de
10:10:00Za10:12:00Z) registra 200 pasos (2 minutos a 100 pasos por minuto).
El recuento de pasos más bajo de 200 pasos en el bucket 3 se debe a la duración de 2 minutos de la ventana truncada, no a una disminución en la actividad del usuario. Cuando traces o analices estos datos, normaliza los recuentos con la duración explícita de cada bucket para evitar presentar una caída engañosa en la actividad del usuario.
En la Figura 3, se comparan los totales de pasos aditivos sin procesar (countSum) con las tasas normalizadas por duración en los tres buckets.
Ejemplo de respuesta de la API que muestra el orden
Debido a que la API devuelve los resultados en orden cronológico inverso, el bucket truncado aparece como el primer elemento de la lista que se muestra:
{
"rollupDataPoints": [
{
"startTime": "2026-08-20T10:10:00Z",
"endTime": "2026-08-20T10:12:00Z",
"steps": {
"countSum": "200"
}
},
{
"startTime": "2026-08-20T10:05:00Z",
"endTime": "2026-08-20T10:10:00Z",
"steps": {
"countSum": "500"
}
},
{
"startTime": "2026-08-20T10:00:00Z",
"endTime": "2026-08-20T10:05:00Z",
"steps": {
"countSum": "500"
}
}
]
}