Extremos

En esta página, se proporciona una descripción general de las convenciones de la API de REST, junto con un índice de las tareas comunes de la API de Google Health y ejemplos de cada una.

Convenciones de la API de REST

La API de Google Health sigue los estándares de las Propuestas de mejora de la API de Google (AIP), específicamente AIP-127 (Transcodificación de HTTP y gRPC) y AIP-131 a AIP-135 (Métodos estándar). Estos estándares definen cómo se asignan los datos de un mensaje proto a una solicitud HTTP.

Parámetros de consulta

Los parámetros de consulta se usan cuando los datos forman parte de la URL. Esto es principalmente para las solicitudes GET (recuperar un recurso) o LIST (filtrado o paginación), pero también se usa para las operaciones DELETE.

  • Ubicación: Se agrega a la URL después de un ?.
  • Sintaxis: Pares clave-valor separados por &.
  • Asignación: Cada campo del mensaje de solicitud que no forma parte de la plantilla de ruta de acceso de la URL se asigna a un parámetro de consulta.
  • Ideal para: Tipos simples (cadenas, números enteros, enumeraciones) y campos repetidos.

Ejemplo de sintaxis:

GET https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints?page_size=10&filter=data_type.interval.start_time >= "2025-10-01T00:00:00Z"

Cuerpo de la solicitud

El cuerpo de la solicitud se usa cuando los datos modifican el estado de un recurso o son demasiado grandes para una URL. Por lo general, el cuerpo es una representación JSON del recurso en sí. Se usa, por lo general, para las operaciones POST, PATCH y PUT.

  • Ubicación: Dentro de la carga útil de HTTP (no visible en la URL).
  • Sintaxis: Formateado como un objeto JSON.
  • Asignación: Definido en la google.api.http anotación.
    • body: "*" significa que todo el mensaje es el cuerpo.
    • body: "resource_name" significa que solo un campo específico en el proto es el cuerpo.
  • Ideal para: Objetos complejos, mensajes anidados y datos sensibles.

Ejemplo de sintaxis:

POST https://health.googleapis.com/v4/users/me/dataTypes/data-type/dataPoints:rollUp
Content-Type: application/json

{
  "range": {
    "startTime": "2025-11-05T00:00:00Z",
    "endTime": "2025-11-13T00:00:00Z"
  },
  "windowSize": "3600s"
}

El caso híbrido

En un método Update compatible con AIP-134 o una operación PATCH, se usan ambos. La URL contiene el nombre del recurso, el cuerpo contiene los datos del recurso actualizado y un parámetro de consulta (por lo general, update_mask) especifica qué campos cambiar.

PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
Content-Type: application/json

{
  "endpointUri": "https://myapp.com/new-webhooks/health"
}

Diferencias clave de un vistazo

Función Parámetros de búsqueda Cuerpo de la solicitud
Orientación de la AIP Se usa para buscar, filtrar y realizar operaciones de lectura. Se usa para operaciones de escritura.
Visibilidad Visible en el historial del navegador y los registros del servidor. Oculto de la URL.
Complejidad Se limita a estructuras planas o repetidas. Admite objetos JSON anidados en profundidad.
Codificación Debe estar codificado como URL (por ejemplo, los espacios se convierten en %20). Codificación JSON estándar.

Fechas

Todas las fechas de la API de Google Health se muestran en el formato YYYY-MM-DD. La API de Nutrition admite el estándar ISO-8601 para los valores de fecha con las siguientes condiciones:

  • Un año de 4 dígitos YYYY
  • Valores de año dentro del rango de 0000 a 9999
  • No se aplica ninguna restricción de fecha de inicio implícita en el estándar ISO-8601 ni en otra época.

Encabezados

Para ejecutar los extremos de la API de Google Health, es necesario usar los encabezados y el token de acceso adecuados. Se recomienda el siguiente encabezado para las solicitudes GET y POST:

Authorization: Bearer access-token
Accept: application/json

Índice de tareas de la API

En esta sección, se proporciona un índice de las tareas comunes de la API de Google Health y ejemplos de cada una.

Obtén el ID de usuario de Fitbit o Google

Después de que un usuario da su consentimiento a través de Google OAuth 2.0, la respuesta del token no contiene el ID de usuario de Fitbit o Google. Para obtener el ID de usuario, llama al getIdentity extremo. getIdentity muestra el ID de usuario heredado de Fitbit y el ID de usuario de Google.

Te recomendamos que, en cuanto un usuario nuevo dé su consentimiento a través de OAuth, llames al extremo getIdentity y almacenes ambos IDs de usuario. Esto proporciona compatibilidad con versiones anteriores y posteriores en tu integración.

Por ejemplo:

Solicitud

GET https://health.googleapis.com/v4/users/me/identity
Authorization: Bearer access-token
Accept: application/json

Respuesta

{
  "name": "users/me/identity",
  "legacyUserId": "A1B2C3",
  "healthUserId": "111111256096816351"
}

Obtén datos detallados o intradía recopilados durante un día

Usa el list extremo para un tipo de datos específico para obtener datos detallados o intradía recopilados durante el día en intervalos admitidos para ese tipo de datos.

Por ejemplo:

Solicitud

GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints
Authorization: Bearer access-token
Accept: application/json

Respuesta

{
  "dataPoints": [
    {
      "dataSource": {
        "recordingMethod": "PASSIVELY_MEASURED",
        "device": {
          "manufacturer": "",
          "displayName": "Charge 6"
        },
        "platform": "FITBIT"
      },
      "steps": {
        "interval": {
          "startTime": "2026-03-04T07:05:00Z",
          "startUtcOffset": "0s",
          "endTime": "2026-03-04T07:06:00Z",
          "endUtcOffset": "0s",
          "civilStartTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 4
            },
            "time": {
              "hours": 7,
              "minutes": 5
            }
          },
          "civilEndTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 4
            },
            "time": {
              "hours": 7,
              "minutes": 6
            }
          }
        },
        "count": "40"
      }
    },
...
  ],
  "nextPageToken": "Xm5h-6L0viZxIlRuWjx5bmvy98zj85uG34tuMn16mu2pntsnZI32iqhq"
}

Filtra datos por una hora de inicio civil de intervalo

Usa el extremo list con un parámetro filter para filtrar datos por hora civil o un intervalo.

Por ejemplo:

Solicitud

GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints?filter=steps.interval.civil_start_time >= "2026-03-04T00:00:00"
Authorization: Bearer access-token
Accept: application/json

Respuesta

{
  "dataPoints": [
    {
      "dataSource": {
        "recordingMethod": "PASSIVELY_MEASURED",
        "device": {
          "manufacturer": "",
          "displayName": "Charge 6"
        },
        "platform": "FITBIT"
      },
      "steps": {
        "interval": {
          "startTime": "2026-03-04T07:05:00Z",
          "startUtcOffset": "0s",
          "endTime": "2026-03-04T07:06:00Z",
          "endUtcOffset": "0s",
          "civilStartTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 4
            },
            "time": {
              "hours": 7,
              "minutes": 5
            }
          },
          "civilEndTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 4
            },
            "time": {
              "hours": 7,
              "minutes": 6
            }
          }
        },
        "count": "40"
      }
...
  ],
  "nextPageToken": "Xm5h-6L0viZxIlRuQjp5bml1bZ4ve2dhNmZvMnt4Yn7qIGQhbHN3YQ"
}

Filtra datos por una hora física de observación de muestra

Usa el extremo list con un parámetro filter para filtrar datos por hora física de observación de muestra.

Por ejemplo:

Solicitud

GET https://health.googleapis.com/v4/users/me/dataTypes/body-fat/dataPoints?filter=body_fat.sample_time.physical_time >= "2026-03-01T00:00:00Z"
Authorization: Bearer access-token
Accept: application/json

Respuesta

{
  "dataPoints": [
    {
      "name": "users/2515055256096816351/dataTypes/body-fat/dataPoints/1234567890",
      "dataSource": {
        "recordingMethod": "UNKNOWN",
        "application": {
          "packageName": "",
          "webClientId": "",
          "googleWebClientId": "google-web-client-id"
        },
        "platform": "GOOGLE_WEB_API"
      },
      "-->bodyFat<--": {
        "sampleTime": {
          "physicalTime": "2026-03-10T10:00:00Z",
          "utcOffset": "0s",
          "civilTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 10
            },
            "time": {
              "hours": 10
            }
          }
        },
        "percentage": 20
      }
    }
  "nextPageToken": ""
}

Filtra datos por fuentes de datos, como wearables

Usa el reconcile extremo para obtener datos de una "familia de fuentes de datos" específica. Para ello, especifica el parámetro dataSourceFamily como un parámetro de consulta.

En la siguiente tabla, se describen las opciones dataSourceFamily admitidas:

Opción Descripción
users/me/dataSourceFamilies/all-sources Valor predeterminado. Incluye datos de todas las fuentes de datos disponibles.
users/me/dataSourceFamilies/google-wearables Incluye datos de dispositivos de seguimiento de Google y Fitbit (como los dispositivos de seguimiento de Fitbit y Pixel Watch). Excluye los datos registrados manualmente.
users/me/dataSourceFamilies/google-sources Incluye datos de origen de Google, como datos de dispositivos de seguimiento y datos registrados manualmente.

Este es un ejemplo de cómo filtrar solo el sueño registrado por el dispositivo de seguimiento para el día después del 2026-03-03:

Solicitud

GET https://health.googleapis.com/v4/users/me/dataTypes/sleep/dataPoints:reconcile?dataSourceFamily=users/me/dataSourceFamilies/google-wearables&filter=sleep.interval.civil_end_time >= "2026-03-03"
Authorization: Bearer access-token
Accept: application/json

Respuesta

{
  "dataPoints": [
    {
      "name": "users/2515055256096816351/dataTypes/sleep/dataPoints/2724123844716220216",
      "dataSource": {
        "recordingMethod": "DERIVED",
        "device": {
          "displayName": "Charge 6"
        },
        "platform": "FITBIT"
      },
      "sleep": {
        "interval": {
          "startTime": "2026-03-03T20:57:30Z",
          "startUtcOffset": "0s",
          "endTime": "2026-03-04T04:41:30Z",
          "endUtcOffset": "0s"
        },
        "type": "STAGES",
        "stages": [
          {
            "startTime": "2026-03-03T20:57:30Z",
            "startUtcOffset": "0s",
            "endTime": "2026-03-03T20:59:30Z",
            "endUtcOffset": "0s",
            "type": "AWAKE",
            "createTime": "2026-03-04T04:43:40.937183Z",
            "updateTime": "2026-03-04T04:43:40.937183Z"
          },
…
          {
            "startTime": "2026-03-04T04:07:30Z",
            "startUtcOffset": "0s",
            "endTime": "2026-03-04T04:41:30Z",
            "endUtcOffset": "0s",
            "type": "AWAKE",
            "createTime": "2026-03-04T04:43:40.937183Z",
            "updateTime": "2026-03-04T04:43:40.937183Z"
          }
        ],
        "metadata": {
          "stagesStatus": "SUCCEEDED",
          "processed": true,
          "main": true
        },
        "summary": {
          "minutesInSleepPeriod": "464",
          "minutesAfterWakeUp": "0",
          "minutesToFallAsleep": "0",
          "minutesAsleep": "407",
          "minutesAwake": "57",
          "stagesSummary": [
            {
              "type": "AWAKE",
              "minutes": "56",
              "count": "12"
            },
            {
              "type": "LIGHT",
              "minutes": "198",
              "count": "19"
            },
            {
              "type": "DEEP",
              "minutes": "114",
              "count": "10"
            },
            {
              "type": "REM",
              "minutes": "94",
              "count": "4"
            }
          ]
        },
        "createTime": "2026-03-04T04:43:40.337983Z",
        "updateTime": "2026-03-04T04:43:40.937183Z"
      }
    }
  ],
  "nextPageToken": ""
}

Agrega datos en un período

Usa el rollUp extremo para mostrar el agregado de datos según una ventana en segundos, en el rango datetime según la hora física de los usuarios (en UTC).

Cuando llames al extremo rollUp, debes proporcionar el cuerpo de la solicitud que representa el período requerido en la hora civil del usuario. Por ejemplo:

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": "30s"
}

Respuesta

{
  "rollupDataPoints": [
    {
      "startTime": "2026-02-17T17:55:00Z",
      "endTime": "2026-02-17T17:55:30Z",
      "steps": {
        "countSum": "41"
      }
    },
    {
      "startTime": "2026-02-17T17:54:00Z",
      "endTime": "2026-02-17T17:54:30Z",
      "steps": {
        "countSum": "31"
      }
    },
...
  ]
}

Agrega datos en un solo día o en varios días

Se debe usar el dailyRollUp extremo cuando deseas agregar datos en un solo día o en varios días, lo que se conoce como windowSize. Proporciona el rango de hora civil cerrado-abierto para el intervalo requerido en el cuerpo de la solicitud. Según el tipo de datos, recibirás la suma o el promedio durante el intervalo.

Por ejemplo:

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"
      }
    }
  ]
}

Inserta o actualiza los datos de salud de un usuario

Usa el patch endpoint para insertar o actualizar los datos de app de Fitbit de un usuario.

Este es un ejemplo en el que un usuario registró su grasa corporal en una balanza llamada "HumanScale" de la empresa "Scales R Us". La nueva lectura de grasa corporal del usuario es del 20% para la fecha del 2026-03-10.

Solicitud

PATCH https://health.googleapis.com/v4/users/me/dataTypes/body-fat/dataPoints/1234567890
Authorization: Bearer access-token
content-length: 329

{
  "name": "bodyFatName",
  "dataSource": {

    "recordingMethod": "ACTIVELY_MEASURED",
    "device": {
      "formFactor": "SCALE",
      "manufacturer": "Scales R Us",
      "displayName": "HumanScale"
    }
  },
  "bodyFat": {
    "sampleTime": {
      "physicalTime": "2026-03-10T10:00:00Z"
    },
    "percentage": 20
  }
}

Respuesta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4main.DataPoint",
    "name": "users/2515055256096816351/dataTypes/body-fat/dataPoints/1234567890",
    "dataSource": {
      "recordingMethod": "ACTIVELY_MEASURED",
      "device": {
        "formFactor": "SCALE",
        "manufacturer": "Scales R Us",
        "displayName": "HumanScale"
      },
      "application": {
        "googleWebClientId": "618308034039.apps.googleusercontent.com"
      },
      "platform": "GOOGLE_WEB_API"
    },
    "bodyFat": {
      "sampleTime": {
        "physicalTime": "2026-03-10T10:00:00Z"
      },
      "percentage": 20
    }
  }
}

Registra un alimento

Para registrar un alimento, envía una solicitud POST al extremo nutrition-log dataPoints. El cuerpo de la solicitud contiene un DataPoint con un objeto nutritionLog. Para obtener más información, consulta la guía de Nutrition.

Por ejemplo:

Solicitud

POST https://health.googleapis.com/v4/users/me/dataTypes/nutrition-log/dataPoints
Authorization: Bearer access-token
Content-Type: application/json

{
  "nutritionLog": {
    "interval": {
      "startTime": "2026-06-16T12:00:00Z",
      "endTime": "2026-06-16T12:30:00Z"
    },
    "foodDisplayName": "Banana",
    "mealType": "LUNCH",
    "energy": {
      "kcal": 105
    },
    "totalCarbohydrate": {
      "grams": 27
    },
    "totalFat": {
      "grams": 0.3
    }
  }
}

Respuesta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4.DataPoint",
    "name": "users/2515055256096816351/dataTypes/nutrition-log/dataPoints/567890",
    "dataSource": {
      "recordingMethod": "ACTIVELY_MEASURED",
      "platform": "GOOGLE_WEB_API"
    },
    "nutritionLog": {
      "interval": {
        "startTime": "2026-06-16T12:00:00Z",
        "startUtcOffset": "0s",
        "endTime": "2026-06-16T12:30:00Z",
        "endUtcOffset": "0s"
      },
      "energy": {
        "kcal": 105
      },
      "totalCarbohydrate": {
        "grams": 27
      },
      "totalFat": {
        "grams": 0.3
      },
      "mealType": "LUNCH",
      "foodDisplayName": "Banana"
    }
  }
}

Borra los datos de salud del usuario

Usa el batchDelete método para borrar un array de datos de app de Fitbit de un usuario.

Este es un ejemplo en el que un usuario registró previamente su grasa corporal en una balanza, pero quiere borrar el registro. Usa el user-id y data-point-id de la acción de inserción original:

Solicitud

POST https://health.googleapis.com/v4/users/me/dataTypes/body-fat/dataPoints:batchDelete
Authorization: Bearer access-token
Accept: application/json
content-length: 93

{
  "names": [
    "users/2515055256096816351/dataTypes/body-fat/dataPoints/1234567890"
  ]
}

Respuesta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4main.BatchDeleteDataPointsResponse"
  }
}

Encuentra información del dispositivo

Usa el list extremo para recuperar la lista de dispositivos vinculados a la cuenta de un usuario. Esto incluye la información del modelo del dispositivo (deviceVersion) y la última vez que se sincronizó con la app para dispositivos móviles de Google Health (lastSyncTime).

La configuración de la lista y la información de sincronización son útiles para solucionar problemas de sincronización o recuperar datos históricos desde la última hora de sincronización.

Por ejemplo:

Solicitud

GET https://health.googleapis.com/v4/users/me/pairedDevices
Authorization: Bearer access-token
Accept: application/json

Respuesta

{
  "pairedDevices": [
    {
      "name": "users/me/pairedDevices/123456",
      "deviceType": "TRACKER",
      "batteryStatus": "High",
      "batteryLevel": 88,
      "lastSyncTime": "2026-03-04T07:05:00Z",
      "deviceVersion": "Charge 6",
      "macAddress": "00:11:22:33:44:55",
      "features": [
        "STEPS",
        "HEART_RATE"
      ]
    }
  ]
}

Consulta datos históricos

Uno de los beneficios principales de la API de Google Health es la capacidad de hacer un seguimiento del rendimiento de un usuario y supervisar sus signos vitales de salud durante períodos prolongados. Puedes consultar los datos de un usuario desde el momento en que se registraron; la API no impone limitaciones ni restricciones sobre la cantidad de datos históricos que puede consumir tu aplicación.

Sin embargo, la consulta de datos históricos aún se rige por los límites de frecuencia estándar estándar. Para administrar la estabilidad del sistema y evitar cargas útiles excesivas, la API de Google Health usa la paginación automática con tamaños de página específicos del extremo. Ten en cuenta los siguientes límites y comportamientos:

  • Paginación automática: Si consultas un intervalo de datos largo, la API solo mostrará la primera página de resultados hasta el límite de tamaño de página para ese extremo, junto con un nextPageToken. Debes usar el nextPageToken para solicitar las páginas posteriores.
  • Tamaños de página variables: Los límites máximos dependen del extremo y del tipo de datos. Para la mayoría de los tipos de datos, los tamaños de página tienen un límite máximo de 10,000. Sin embargo, para ciertos tipos de datos, como exercise y sleep, el tamaño de página predeterminado y máximo está limitado a 25. Por ejemplo, si un cliente solicita todos los datos de sueño de los últimos 10 años, la API solo mostrará 25 sesiones de sueño en la primera página.
  • Restricciones del período de resumen: Para los extremos de resumen y agregación de datos (como rollUp y dailyRollUp), los períodos de consulta están restringidos según el tipo de datos:
    • Un período máximo de 14 días para calories-in-heart-rate-zone, heart-rate, active-minutes y total-calories.
    • Un período máximo de 90 días para todos los demás tipos de datos de resumen.

Según el volumen de datos históricos que necesite tu aplicación, recuperar todo el conjunto de datos requerirá paginar las páginas de forma secuencial. Ten esto en cuenta cuando diseñes el proceso de sincronización de datos de tu aplicación.

Para garantizar un rendimiento óptimo y evitar errores de la API, sigue estos lineamientos cuando consultes datos históricos:

Sincronización de datos por fases (carga activa versus carga en frío)

  • Carga "activa" inicial: Recupera y renderiza solo los datos más recientes de 7 a 14 días durante la secuencia de carga principal. Esto garantiza que los usuarios vean los datos de inmediato sin esperar consultas de larga duración.
  • Carga "inactiva" en segundo plano: Delega la recuperación de datos históricos más antiguos a una cola asíncrona de menor prioridad o a un proceso en segundo plano después de que se renderice la IU principal.

Fragmentación de consultas para la agregación

  • Dado que los extremos de resumen y resumen diario aplican un límite máximo de período (14 o 90 días según el tipo de datos), debes dividir las consultas de agregación históricas grandes en intervalos secuenciales más pequeños dentro de estos límites.
  • Procesa por lotes o secuencia estas subconsultas de forma segura para respetar los límites de simultaneidad y mantener indicadores de progreso de la IU constantes.

Aprovecha los resúmenes agregados previamente

Reestructura los paneles de descripción general y los gráficos de tendencias para usar extremos de resumen agregados previamente (como DailyRollUpDataPoints). Esto reducirá drásticamente la sobrecarga de procesamiento en el backend y el tiempo de transferencia de red al cliente.

Manejo de errores resistente (reintentos inteligentes)

  • Implementa un manejo estricto de la retirada exponencial cuando encuentres límites de frecuencia (429 Too Many Requests) y tiempos de espera agotados de la puerta de enlace del servidor (504 Gateway Timeout). Nunca reintentes cargas útiles grandes y fallidas de inmediato. Los reintentos instantáneos multiplican la congestión del backend y agravan la degradación del sistema.