本页简要介绍了 REST API 惯例,并提供了常见 Google Health API 任务的索引以及每个任务的示例。
REST API 惯例
Google Health API 遵循 Google API 改进提案 (AIP) 标准,特别是 AIP-127(HTTP 和 gRPC 转码)以及 AIP-131 至 AIP-135(标准方法)。这些标准定义了如何将数据从 proto 消息映射到 HTTP 请求。
查询参数
当数据是网址的一部分时,会使用查询参数。这主要用于 GET 请求(提取资源)或 LIST 请求(过滤/分页),但也用于 DELETE 操作。
- 展示位置:附加到网址中
?之后。 - 语法:以
&分隔的键值对。 - 映射:请求消息中不属于网址路径模板的每个字段都会映射到查询参数。
- 最适合:简单类型(字符串、整数、枚举)和重复字段。
语法示例:
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"
请求正文
当数据会修改资源的状态或数据量过大而无法放入网址中时,会使用请求正文。正文通常是资源的 JSON 表示法。通常用于 POST、PATCH 和 PUT 操作。
- 放置位置:位于 HTTP 载荷内(在网址中不可见)。
- 语法:格式为 JSON 对象。
- 映射:在
google.api.http注释中定义。body: "*"表示整个消息都是正文。body: "resource_name"表示只有 proto 中的特定字段是正文。
- 最适合:复杂对象、嵌套消息和敏感数据。
语法示例:
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"
}混合式
在符合 AIP-134 标准的 Update 方法或 PATCH 操作中,两者都会使用。网址包含资源名称,正文包含更新后的资源数据,而查询参数(通常为 update_mask)用于指定要更改的字段。
PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
Content-Type: application/json
{
"endpointUri": "https://myapp.com/new-webhooks/health"
}
主要区别一览
| 功能 | 查询参数 | 请求正文 |
|---|---|---|
| AIP 指南 | 用于搜索、过滤和读取操作。 | 用于写入操作。 |
| 公开范围 | 在浏览器历史记录和服务器日志中可见。 | 隐藏在网址中。 |
| 复杂性 | 仅限平面或重复结构。 | 支持深度嵌套的 JSON 对象。 |
| 编码 | 必须经过网址编码(例如,空格会变成 %20)。 |
标准 JSON 编码。 |
日期
Google Health API 中的所有日期均以 YYYY-MM-DD 格式显示。Nutrition API 支持 ISO-8601 标准的日期值,但需满足以下条件:
- 4 位数年份
YYYY - 0000-9999 范围内的年份值
- 不强制执行 ISO-8601 标准或其他纪元隐含的开始日期限制
标头
执行 Google Health API 端点需要使用适当的标头和访问令牌。建议为 GET 和 POST 请求添加以下标头:
Authorization: Bearer access-token Accept: application/json
API 任务索引
本部分提供了常见 Google Health API 任务的索引以及每个任务的示例。
获取 Fitbit 或 Google 用户 ID
用户通过 Google OAuth 2.0 同意授权后,令牌响应不包含 Fitbit 或 Google 用户 ID。如需获取用户 ID,请调用 getIdentity 端点。getIdentity 会同时返回 Fitbit 旧版用户 ID 和 Google 用户 ID。
我们建议您在用户通过 OAuth 表示同意后,立即调用 getIdentity 端点并存储这两个用户 ID。这可确保您的集成具有向后和向前兼容性。
例如:
请求
GET https://health.googleapis.com/v4/users/me/identity Authorization: Bearer access-token Accept: application/json
响应
{
"name": "users/me/identity",
"legacyUserId": "A1B2C3",
"healthUserId": "111111256096816351"
}获取全天收集的当日数据或详细数据
使用特定数据类型的 list 端点可获取在支持的时间间隔内收集的该数据类型的全天数据(包括日内数据或详细数据)。
例如:
请求
GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints Authorization: Bearer access-token Accept: application/json
响应
{
"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"
}按时间段的民用开始时间过滤数据
使用 list 端点和 filter 参数按民用时间或时间间隔过滤数据。
例如:
请求
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
响应
{
"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"
}按样本观测的实际时间过滤数据
使用 list 端点和 filter 参数按样本观测实际时间过滤数据。
例如:
请求
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
响应
{
"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": ""
}按数据源(例如穿戴式设备)过滤数据
使用 reconcile 端点可按已协调的流中的“数据源系列”获取数据。
以下示例展示了如何仅过滤 2026 年 3 月 3 日之后记录的睡眠数据:
请求
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
响应
{
"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": ""
}汇总一段时间范围内的数据点
使用 rollUp 端点可返回基于以秒为单位的窗口的数据点聚合,该窗口位于基于用户实际时间(以 UTC 为单位)的 datetime 范围内。
调用 rollUp 端点时,您必须提供表示用户民用时间所需日期范围的请求正文。例如:
请求
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"
}响应
{
"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"
}
},
...
]
}汇总单日或多日的数据
如果您想汇总单日或多日(即 windowSize)的数据,应使用 dailyRollUp 端点。在请求正文中提供所需时间段的左闭右开民用时间范围。系统会根据数据类型,提供相应时间间隔内的总和或平均值。
例如:
请求
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
}响应
{
"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"
}
}
]
}插入或更新用户的健康数据
使用 patch 端点插入或更新用户的 Fitbit 应用数据。
以下示例展示了用户在“Scales R Us”公司生产的名为“HumanScale”的体重秤上记录体脂的情况。用户在 2026-03-10 的新体脂读数为 20%。
请求
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
}
}响应
{
"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
}
}
}删除用户健康数据
使用 batchDelete 端点可删除用户的一系列 Fitbit 应用数据。
以下示例展示了用户之前在体重秤上记录了体脂,但现在想要删除该记录的情况。使用原始插播操作中的 user-id 和 data-point-id:
请求
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"
]
}响应
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.devicesandservices.health.v4main.BatchDeleteDataPointsResponse"
}
}