端点

本页简要介绍了 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 表示法。通常用于 POSTPATCHPUT 操作。

  • 放置位置:位于 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-iddata-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"
  }
}