网络钩子订阅


借助 Google Health API,您的应用可以在用户健康数据发生变化时接收实时通知。您的 服务器无需轮询更改,而是在 Google Health API 中提供数据后立即接收 HTTPS POST 请求(网络钩子) 。

支持的数据类型

以下数据类型支持网络钩子通知:

  • 步数
  • 海拔高度
  • 距离
  • 楼层数
  • 体重
  • 睡眠

只有当用户已针对其中一个相应范围授予同意时,系统才会针对这些数据类型发送通知:

  • 活动,涵盖步数、海拔高度、距离和楼层数数据类型:
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
  • 健康指标,涵盖体重数据类型:
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
  • 睡眠,涵盖睡眠数据类型:
    • https://www.googleapis.com/auth/googlehealth.sleep
    • https://www.googleapis.com/auth/googlehealth.sleep.readonly

管理订阅者

您必须先注册订阅者(代表应用的通知端点),然后才能接收通知。您可以使用 projects.subscribers 提供的 REST API 管理订阅者。

您的订阅者端点必须使用 HTTPS (TLSv1.2+) 且可公开访问。 在创建和更新订阅方期间,Google Health API 会执行验证质询,以确保您拥有端点 URI。如果验证失败,订阅者创建和更新操作也会失败,并显示 FailedPreconditionException

创建订阅者

如需为项目注册新订阅者,请使用 create 端点。您需要提供:

  • endpointUri:网络钩子通知的目标网址。
  • subscriberConfigs:您希望接收通知的数据类型,以及每种数据类型的订阅政策。
  • endpointAuthorization:端点的授权机制。其中必须包含您提供的 authorization_tokenauthorization_token 的值会随每条通知消息一起在 Authorization 标头中发送。您可以使用此令牌来验证传入请求是否来自 Google Health API。例如,您可以将 authorization_token 设置为 Bearer R4nd0m5tr1ng123 以进行 Bearer 身份验证,或设置为 Basic dXNlcjpwYXNzd29yZA== 以进行基本身份验证。
  • subscriberId:您为订阅者提供的唯一标识符。此 ID 的长度必须介于 4 到 36 个字符之间,并且必须与正则表达式 ([a-z]([a-z0-9-]{2,34}[a-z0-9])) 匹配。

subscriberConfigs 中,您必须为每种数据类型设置 subscriptionCreatePolicy。将其设置为 AUTOMATIC 以使用自动订阅,或设置为 MANUAL 以自行管理用户订阅。如需详细了解每个选项,请参阅 自动订阅手动订阅

请求

POST https://health.googleapis.com/v4/projects/project-id/subscribers?subscriberId=subscriber-id
{
  "endpointUri": "https://myapp.com/webhooks/health",
  "subscriberConfigs": [
    {
      "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
      "subscriptionCreatePolicy": "AUTOMATIC"
    },
    {
      "dataTypes": ["sleep"],
      "subscriptionCreatePolicy": "MANUAL"
    }
  ],
  "endpointAuthorization": {
    "authorization_token": "Bearer example-secret-token"
  }
}

响应

{
  "name": "projects/project-id/subscribers/subscriber-id",
  "endpointUri": "https://myapp.com/webhooks/health",
  "state": "ACTIVE",
  "subscriberConfigs": [
    {
      "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
      "subscriptionCreatePolicy": "AUTOMATIC"
    },
    {
      "dataTypes": ["sleep"],
      "subscriptionCreatePolicy": "MANUAL"
    }
  ],
  "endpointAuthorization": {
    "authorizationTokenSet": true
  }
}

列出订阅者

使用 list 端点检索为项目注册的所有订阅者。

请求

GET https://health.googleapis.com/v4/projects/project-id/subscribers

响应

{
  "subscribers": [
    {
      "name": "projects/project-id/subscribers/subscriber-id",
      "endpointUri": "https://myapp.com/webhooks/health",
      "state": "ACTIVE",
      "subscriberConfigs": [
        {
          "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
          "subscriptionCreatePolicy": "AUTOMATIC"
        },
        {
          "dataTypes": ["sleep"],
          "subscriptionCreatePolicy": "MANUAL"
        }
      ],
      "endpointAuthorization": {
        "authorizationTokenSet": true
      }
    }
  ],
  "nextPageToken": ""
}

更新订阅者

使用 patch 端点更新项目中的订阅者。可以更新的字段包括 endpointUrisubscriberConfigsendpointAuthorization

您可以通过提供 updateMask 查询参数和请求正文来更新字段。updateMask 必须包含您要更新的字段名称的英文逗号分隔列表,并使用驼峰式命名法(例如 endpointUri)。请求正文必须包含部分订阅者对象,其中包含您要更新的字段的新值。只有在 updateMask 中指定的字段才会更新。如果您在请求正文中提供的字段不在 updateMask 中,系统会忽略这些字段。

如果您更新 endpointUriendpointAuthorization,系统会执行端点验证。如需了解详情,请参阅端点验证

更新 subscriberConfigs 时,请注意,这是一个 完全替换 ,而不是 合并。如果 subscriberConfigs 包含在 updateMask 中,则该订阅者的所有存储配置都会被请求正文中提供的列表覆盖。如需添加或移除配置,您必须提供完整的配置集。如果您要更新其他字段并希望保留当前配置,请从 updateMask 中省略 subscriberConfigs

请求

PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id?updateMask=endpointUri
{
  "endpointUri": "https://myapp.com/new-webhooks/health"
}

响应

{
  "name": "projects/project-id/subscribers/subscriber-id",
  "endpointUri": "https://myapp.com/new-webhooks/health",
  "state": "ACTIVE",
  "subscriberConfigs": [
    {
      "dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
      "subscriptionCreatePolicy": "AUTOMATIC"
    },
    {
      "dataTypes": ["sleep"],
      "subscriptionCreatePolicy": "MANUAL"
    }
  ],
  "endpointAuthorization": {
    "authorizationTokenSet": true
  }
}

端点验证

为了确保通知传送的安全性和可靠性,每当您创建订阅者或更新其端点配置(endpointUriendpointAuthorization)时,Google Health API 都会执行强制性的两步验证握手。此过程在 API 调用期间同步执行。该服务会向您的端点 URI 发送两个自动 POST 请求, 使用用户代理 Google-Health-API-Webhooks-Verifier,JSON 正文为 {"type": "verification"}

  • 授权握手:第一个请求会随您配置的 Authorization标头一起发送。您的服务器必须返回 200 OK201 Created 状态。
  • 未经授权的质询:第二个请求会在不提供凭据的情况下发送。您的服务器必须返回 401 Unauthorized403 Forbidden 状态。

此握手可确认您的端点处于活跃状态并正确强制执行安全性。如果任一步骤失败,API 请求也会失败,并显示 FAILED_PRECONDITION 错误。只有在此握手成功后,您的订阅者才会保存并激活,以接收健康数据通知。

密钥轮替

如果您需要轮替 endpointAuthorization 的密钥,请按以下步骤操作:

  1. 将端点配置为接受旧值和新值 endpointAuthorization
  2. 使用 patch 请求和 ?updateMask=endpointAuthorization 更新订阅者配置,并提供新的 endpointAuthorization 值 。
  3. 确认第 2 步成功后,将端点配置为仅接受新的 endpointAuthorization 值。

删除订阅者

使用 delete 端点从项目中移除订阅者。删除后,订阅者将不再接收通知。

请求

DELETE https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id

响应

如果删除成功,系统会返回 HTTP 状态为 `200 OK` 的空响应正文。
{}

用户订阅

借助 Google Health API,您可以高效管理用户订阅,从而减少用户入职期间手动注册的需求。

自动订阅

我们建议您使用自动订阅。如需启用此功能,请在特定数据类型的 subscriberConfigs 中将 subscriptionCreatePolicy 设置为 AUTOMATIC。如果您使用 AUTOMATIC 政策指定 dataTypes,则 Google Health API 会针对这些数据类型发送通知,前提是用户也针对这些数据类型授予了用户同意。

当用户针对与具有 AUTOMATIC 政策的数据类型对应的范围授予应用同意时,Google Health API 会自动跟踪并发送通知,通知内容为用户同意的数据类型与该用户的自动订阅者配置数据类型之间的交集所产生的数据类型。然后,每当该用户为这些类型生成新数据时,系统都会向您的端点发送通知。此功能适用于在您创建订阅者之前或之后授予同意的用户。对于在创建订阅者之前生成的数据,系统不会回填通知。

如果用户撤消同意,系统将停止发送相应数据类型的通知。自动订阅由 Google 管理,无法单独列出或删除;只有在删除父级订阅者时,系统才会移除自动订阅。

手动订阅

如果您希望手动管理每个用户的订阅,请在 subscriberConfigs 中将 subscriptionCreatePolicy 设置为 MANUAL。使用此政策时,系统不会自动创建用户订阅。将来,当用于管理手动订阅的 API 可用时,系统会使用此功能。在这些 API 可用之前,我们建议您使用 AUTOMATIC 订阅。

通知

当用户订阅的数据类型的数据发生变化时,Google Health API 会向订阅者端点网址发送 HTTPS POST 请求。

通知格式

通知载荷是一个 JSON 对象,其中包含有关数据更改的详细信息。这包括用户 ID、数据类型和时间间隔,您可以使用这些信息查询更新后的数据。

{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "subscription-name",
    "healthUserId": "health-user-id",
    "operation": "UPSERT",
    "dataType": "steps",
    "intervals": [
      {
        "physicalTimeInterval": {
          "startTime": "2026-03-0B01:29:00Z",
          "endTime": "2026-03-08T01:34:00Z"
        },
        "civilDateTimeInterval": {
          "startDateTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 7
            },
            "time": {
              "hours": 17,
              "minutes": 29
            }
          },
          "endDateTime": {
            "date": {
              "year": 2026,
              "month": 3,
              "day": 7
            },
            "time": {
              "hours": 17,
              "minutes": 34
            }
          }
        },
        "civilIso8601TimeInterval": {
          "startTime": "2026-03-07T17:29:00",
          "endTime": "2026-03-07T17:34:00"
        }
      }
    ]
  }
}

operation 字段表示触发通知的更改类型:

  • UPSERT:针对任何数据添加或修改发送。
  • DELETE:当用户删除数据时,或由于系统事件(例如用户撤消权限或删除账号)而移除数据时发送。

我们建议您将通知处理逻辑设为遵循幂等原则,尤其是对于 UPSERT 操作,因为重试可能会导致发送重复通知。

clientProvidedSubscriptionName 字段是一个唯一标识符。对于具有 MANUAL 政策的订阅,此字段包含在创建订阅时指定的持久性开发者提供的订阅名称。 这为管理手动订阅提供了一个稳定的 ID。对于使用 AUTOMATIC 政策创建的订阅,Google Health API 会自动为每个通知生成并向此字段分配一个唯一标识符(随机 UUID)。为手动和自动政策都添加 clientProvidedSubscriptionName 可确保所有订阅类型的通知载荷格式一致。

healthUserId 是 Google Health API 为数据发生变化的用户提供的标识符。如果您的应用支持多个用户,您可能会收到针对任何已向您的应用授予同意的用户的通知。收到通知后,请使用 healthUserId 确定哪些用户的数据发生了变化,以便您可以使用其 OAuth 凭据查询其数据。

如需将用户的 OAuth 凭据映射到其 healthUserId,请使用 getIdentity 端点。在用户入职期间使用用户的凭据调用此端点,以检索其 healthUserId 并存储此映射。此映射不会随时间变化,因此可以无限期缓存。如需查看示例,请参阅 获取用户 ID。这样,您就可以在根据通知中的 healthUserId 查询数据时选择正确的用户凭据。

回应通知

您的服务器必须立即使用 HTTP 204 No Content 状态代码响应通知。为避免超时,请在发送响应后异步处理通知载荷。如果 Google Health API 收到任何其他状态代码或请求超时,它会在稍后重试发送通知。

Node.js (Express) 示例:

app.post('/webhook-receiver', (req, res) => {
    // 1. Immediately acknowledge the notification
    res.status(204).send();

    // 2. Process the data asynchronously in the background
    const notification = req.body;
    setImmediate(() => {
        console.log(`Update for user ${notification.data.healthUserId} of type ${notification.data.dataType}`);
        // Trigger your data retrieval logic here
    });
});

订阅者状态和恢复

如果您的订阅方端点不可用或返回错误状态代码(除 204 之外的任何代码),Google Health API 会将待处理的通知存储最多 7 天,并使用指数退避算法重试传送。

当您的端点恢复在线并返回 204 时,API 会自动传送存储的消息积压。超过 7 天的通知会被舍弃,无法恢复。