Webhook abonelikleri

Google Health API, kullanıcının sağlık verileri değiştiğinde uygulamanızın anlık bildirimler almasına olanak tanır. Sunucunuz, değişiklikleri sorgulamak yerine Google Health API'de veri kullanılabilir hale gelir gelmez bir HTTPS POST isteği webhook alır.

Desteklenen veri türleri

Webhook bildirimleri aşağıdaki veri türleri için desteklenir:

Tablo: Webhook desteği sunan Google Health API veri türleri
Veri türü Kullanılabilir
işlemler
Kapsam
Aktif Dakikalar
dataType: active-minutes
filter parameter: active_minutes
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika

Uyumlu cihazlar

  • Fitbit Air
  • Fitbit Alta
  • Fitbit Alta HR
  • Fitbit Blaze
  • Fitbit Charge 2
  • Fitbit Charge 3
  • Fitbit Flex 2
  • Fitbit Inspire
  • Fitbit Inspire HR
  • Pixel Watch 4
list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Aktif Bölge Dakikası
dataType: active-zone-minutes
filter parameter: active_zone_minutes
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika

Uyumlu cihazlar

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Etkinlik düzeyi
dataType: activity-level
filter parameter: activity_level
Kayıt türü: Aralık
listeleme, mutabakat .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Altitude
dataType: altitude
filter parameter: altitude
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika
list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Kan Şekeri
dataType: blood-glucose
filter parameter: blood_glucose
Kayıt türü: Örnek
list, get, reconcile, rollup, dailyRollup .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Vücut Yağ Yüzdesi
dataType: body-fat
filter parameter: body_fat
Kayıt türü: Örnek

Uyumlu cihazlar

list, get, reconcile, rollup, dailyRollup, create, update, batchDelete .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Nabız Bölgesinde Yakılan Kalori
dataType: calories-in-heart-rate-zone
filter parameter: calories_in_heart_rate_zone
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika
rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Günlük Nabız Değişkenliği
dataType: daily-heart-rate-variability
filter parameter: daily_heart_rate_variability
Kayıt türü: Günlük

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Günlük Nabız Bölgeleri
dataType: daily-heart-rate-zones
filter parameter: daily_heart_rate_zones
Kayıt türü: Günlük
listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Günlük Oksijen Doygunluğu
dataType: daily-oxygen-saturation
filter parameter: daily_oxygen_saturation
Kayıt türü: Günlük

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Günlük Solunum Hızı
dataType: daily-respiratory-rate
filter parameter: daily_respiratory_rate
Kayıt türü: Günlük

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Günlük Dinlenme Nabzı
dataType: daily-resting-heart-rate
filter parameter: daily_resting_heart_rate
Kayıt türü: Günlük

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Günlük Uyku Sıcaklığı Değişimleri
dataType: daily-sleep-temperature-derivations
filter parameter: daily_sleep_temperature_derivations
Kayıt türü: Günlük

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Mesafe
dataType: distance
filter parameter: distance
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika

Uyumlu cihazlar

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Egzersiz
dataType: exercise
filter parameter: exercise
Kayıt türü: Oturum

Uyumlu cihazlar

list, get, reconcile, create, update, batchDelete .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Katlar
dataType: floors
filter parameter: floors
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika
reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Nabız
dataType: heart-rate
filter parameter: heart_rate
Kayıt türü: Örnek
Depolama çözünürlüğü: 1 saniye

Uyumlu cihazlar

list, reconcile, rollup, dailyRollup .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Nabız Değişkenliği
dataType: heart-rate-variability
filter parameter: heart_rate_variability
Kayıt türü: Örnek

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Boy
dataType: height
filter parameter: height
Kayıt türü: Örnek
list, get, reconcile, create, update, batchDelete .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Sıvı Alımı Günlüğü
dataType: hydration-log
filter parameter: hydration_log
Kayıt türü: Oturum
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete .nutrition.readonly
.nutrition.writeonly
Beslenme Günlüğü
dataType: nutrition-log
filter parameter: nutrition_log
Kayıt türü: Oturum

Uyumlu cihazlar

list, get, reconcile, rollup, dailyRollup, create, update, batchDelete .nutrition.readonly
.nutrition.writeonly
Solunum Hızı Uyku Özeti
dataType: respiratory-rate-sleep-summary
filter parameter: respiratory_rate_sleep_summary
Kayıt türü: Örnek

Uyumlu cihazlar

listeleme, mutabakat .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
Maksimum oksijen tüketimi koşusu
dataType: run-vo2-max
filter parameter: run_vo2_max
Kayıt türü: Örnek

Uyumlu cihazlar

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Hareketsiz Dönem
dataType: sedentary-period
filter parameter: sedentary_period
Kayıt türü: Aralık

Uyumlu cihazlar

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Uyku
dataType: sleep
filter parameter: sleep
Kayıt türü: Oturum

Uyumlu cihazlar

list, get, reconcile, create, update, batchDelete .sleep.readonly
.sleep.writeonly
Adımlar
dataType: steps
filter parameter: steps
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika

Uyumlu cihazlar

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Nabız Bölgesinde Geçirilen Süre
dataType: time-in-heart-rate-zone
filter parameter: time_in_heart_rate_zone
Kayıt türü: Aralık
Depolama çözünürlüğü: 1 dakika
list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
Ağırlık
dataType: weight
filter parameter: weight
Kayıt türü: Örnek

Uyumlu cihazlar

list, get, reconcile, rollup, dailyRollup, create, update, batchDelete .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly

Bildirim kapsamları

Bu veri türleri için bildirimler yalnızca kullanıcı ilgili kapsamlardan biri için izin verdiğinde gönderilir:

  • Aktif dakikalar, adım sayısı, rakım, mesafe ve kat verisi türlerini kapsayan Etkinlik:
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly
  • Ağırlık veri türünü kapsayan Sağlık Metrikleri:
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.writeonly
  • Uyku (uyku verileri türünü kapsar):
    • https://www.googleapis.com/auth/googlehealth.sleep.readonly
    • https://www.googleapis.com/auth/googlehealth.sleep.writeonly

IAM hizmet hesapları

Zorunlu olmasa da Google Health API için aboneleri yapılandırırken IAM hizmet hesabı kullanmanızı öneririz. Hizmet hesapları, aşağıdaki özellikler sayesinde uygulama iş yükleri için standart kullanıcı hesaplarına kıyasla daha iyi güvenlik sağlar:

  • Otomatik kısa süreli kimlik bilgileri: Hizmet hesapları, bir Google Cloud yürütme ortamına (ör. Compute Engine, Cloud Run veya Google Kubernetes Engine) eklendiğinde güvenli ve kısa süreli kimlik bilgilerini otomatik olarak alır ve değiştirir. Bu sayede, kalıcı statik anahtarları yönetme ve depolama riskleri ortadan kalkar.
  • En az ayrıcalık ilkesi: Hizmet hesapları, iş yükleri için özel kimlikler sağlar. Bu kullanıcılara yalnızca abone uç noktalarını yönetmek için gereken belirli izinleri verebilir ve Google Cloud kaynaklarınıza daha geniş erişim sağlamalarını önleyebilirsiniz.
  • Yaşam döngüsü bağımsızlığı: Hizmet hesapları, her bir kullanıcının hesabından bağımsız olarak çalışır. Bu sayede, personel değişiklikleri uzun vadeli kimlik doğrulama kararlılığını etkilemez.

Hizmet hesabı oluşturma

Abone uygulamanızı bir hizmet hesabı kullanarak kimlik doğrulaması yapacak şekilde yapılandırmak için:

  1. Hizmet hesabı oluşturun: Google Cloud Console'da projenizin IAM ve Yönetici sayfasına giderek kullanıcı tarafından yönetilen yeni bir hizmet hesabı oluşturun.
  2. Gerekli IAM rollerini verin: Google Cloud projenizdeki aboneleri yönetmek için gereken uygun rolleri hizmet hesabına atayın.
  3. Hizmet hesabını iş yükünüze ekleyin: Abone mantığınızı barındıran ortamı yeni hizmet hesabı olarak çalışacak şekilde yapılandırın. Bu sayede uygulama kodunuz (ör. Google API istemci kitaplıkları), projects.subscribers REST API'yi çağırırken hizmet hesabının kısa süreli kimlik bilgilerini otomatik olarak algılayıp kullanabilir.

CPE rolleri

Google Health API abonelerini veya aboneliklerini yönetmek için API çağrılarını yapan, kimliğine bürünülmüş hizmet hesabına uygun rolü vermeniz gerekir. Gerekli erişim düzeyine bağlı olarak aşağıdaki rollerden birini atayın:

  • Google Health API Okuma
  • Google Health API Düzenleyicisi
  • Google Health API Yöneticisi

Google Health API IAM rolleri ve izinleri hakkında daha fazla bilgi edinin.

Aboneleri yönetme

Bildirim alabilmek için uygulamanızın bildirim alma noktasını temsil eden bir abone kaydetmeniz gerekir. Aboneleri projects.subscribers adresindeki REST API'yi kullanarak yönetebilirsiniz.

Abone uç noktanız HTTPS (TLSv1.2+) kullanmalı ve herkese açık olmalıdır. Abone oluşturma ve güncelleme sırasında Google Health API, uç nokta URI'sinin sahibi olduğunuzdan emin olmak için bir doğrulama sorgulaması gerçekleştirir. Doğrulama başarısız olursa abone oluşturma ve güncelleme işlemleri FailedPreconditionException ile başarısız olur.

Abone oluşturma

Projeniz için yeni bir abone kaydetmek istiyorsanız create uç noktasını kullanın. Şu bilgileri sağlamanız gerekir:

  • project-id: Webhook hizmet hesabının oluşturulduğu proje numarası.
  • subscriberId: Abone için sağladığınız benzersiz tanımlayıcı. Bu kimlik 4 ile 36 karakter arasında olmalı ve normal ifadeyle ([a-z]([a-z0-9-]{2,34}[a-z0-9])) eşleşmelidir.
  • endpointUri: Webhook bildirimlerinin hedef URL'si.
  • subscriberConfigs: Bildirim almak istediğiniz veri türleri ve her birinin abonelik politikası.
  • endpointAuthorization: Uç noktanızın yetkilendirme mekanizması. Bu, sağladığınız bir secret içermelidir. secret değeri, her bildirim mesajıyla birlikte Authorization başlığında gönderilir. Bu jetonu kullanarak gelen isteklerin Google Health API'den geldiğini doğrulayabilirsiniz. Örneğin, Bearer kimlik doğrulaması için secret değerini Bearer R4nd0m5tr1ng123, temel kimlik doğrulaması için ise Basic dXNlcjpwYXNzd29yZA== olarak ayarlayabilirsiniz.

subscriberConfigs içinde her veri türü için subscriptionCreatePolicy değerini ayarlamanız gerekir. Otomatik abonelikleri kullanmak için AUTOMATIC, kullanıcı aboneliklerini kendiniz yönetmek istiyorsanız MANUAL olarak ayarlayın. Her bir seçenekle ilgili daha fazla bilgi için otomatik abonelikler ve manuel abonelikler bölümlerine bakın.

İstek

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": {
    "secret": "Bearer example-secret-token"
  }
}

Yanıt

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

Aboneleri listeleme

Projenize kayıtlı tüm aboneleri almak için list uç noktasını kullanın.

İstek

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

Yanıt

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

Abone güncelleme

Projenizdeki bir aboneyi güncellemek için patch uç noktasını kullanın. Güncellenebilecek alanlar: endpointUri, subscriberConfigs ve endpointAuthorization.

Alanları güncellemek için bir updateMask sorgu parametresi ve istek gövdesi sağlarsınız. updateMask, güncellemek istediğiniz alan adlarının virgülle ayrılmış bir listesini içermelidir. Alan adları için camel case kullanılmalıdır (örneğin, endpointUri). İstek gövdesi, güncellemek istediğiniz alanların yeni değerlerini içeren kısmi bir Subscriber nesnesi içermelidir. Yalnızca updateMask içinde belirtilen alanlar güncellenir. İstek gövdesinde updateMask içinde olmayan alanlar sağlarsanız bunlar yoksayılır.

endpointUri veya endpointAuthorization güncellenirse uç nokta doğrulaması gerçekleştirilir. Ayrıntılar için Uç nokta doğrulaması başlıklı makaleyi inceleyin.

subscriberConfigs güncellenirken bunun bir birleştirme değil, tam değiştirme olduğunu unutmayın. subscriberConfigs, updateMask içinde yer alıyorsa bu abonenin depolanan tüm yapılandırmalarının üzerine istek gövdesinde sağlanan liste yazılır. Yapılandırma eklemek veya kaldırmak için yapılandırmaların tamamını sağlamanız gerekir. Diğer alanları güncelliyorsanız ve mevcut yapılandırmalarınızı korumak istiyorsanız updateMask alanından subscriberConfigs değerini çıkarın.

İstek

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

Yanıt

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

Abone silme

Bir aboneyi projenizden kaldırmak için delete uç noktasını kullanın. Silinen abone artık bildirim almaz.

İstek

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

Yanıt

Silme işlemi başarılı olursa HTTP durumu `200 OK` olan boş bir yanıt gövdesi döndürülür.
{}

Uç nokta doğrulaması

Google Health API, bildirimlerinizin güvenli ve güvenilir bir şekilde teslim edilmesini sağlamak için abone oluşturduğunuzda veya uç nokta yapılandırmasını (endpointUri ya da endpointAuthorization) güncellediğinizde zorunlu iki adımlı doğrulama el sıkışması gerçekleştirir. Bu işlem, API çağrısı sırasında eşzamanlı olarak gerçekleştirilir. Hizmet, Google-Health-API-Webhooks kullanıcı aracısını kullanarak uç nokta URI'nize {"type": "verification"} JSON gövdesiyle iki otomatik POST isteği gönderir.

  • Yetkili El Sıkışma: İlk istek, yapılandırılmış Authorization başlığınızla gönderilir. Sunucunuz 200 OK veya 201 Created durumuyla yanıt vermelidir.
  • Yetkisiz sorgulama: İkinci istek, kimlik bilgileri olmadan gönderilir. Sunucunuz 401 Unauthorized veya 403 Forbidden durumuyla yanıt vermelidir.

Bu el sıkışma, uç noktanızın etkin olduğunu ve güvenliği doğru şekilde uyguladığını doğrular. Adımlardan biri başarısız olursa API isteği FAILED_PRECONDITION hatasıyla başarısız olur. Aboneniz, yalnızca bu el sıkışma başarılı olduktan sonra kaydedilir ve sağlık verileri bildirimlerini almak üzere etkinleştirilir.

Anahtar rotasyonu

endpointAuthorization için anahtarları rotasyona tabi tutmanız gerekiyorsa aşağıdaki adımları uygulayın:

  1. Uç noktanızı hem eski hem de yeni endpointAuthorization değerlerini kabul edecek şekilde yapılandırın.
  2. ?updateMask=endpointAuthorization ile patch isteği kullanarak abone yapılandırmasını yeni endpointAuthorization değeriyle güncelleyin.
  3. 2. adımın başarılı olduğunu onayladıktan sonra uç noktanızı yalnızca yeni endpointAuthorization değerini kabul edecek şekilde yapılandırın.

Kullanıcı abonelikleri

Google Health API, kullanıcı aboneliklerini verimli bir şekilde yönetmenize yardımcı olarak kullanıcı oryantasyonu sırasında manuel kayıt ihtiyacını azaltır.

Otomatik abonelikler

Otomatik abonelikleri kullanmanızı öneririz. Bu özelliği etkinleştirmek için belirli veri türleri için subscriberConfigs politikanızda subscriptionCreatePolicy değerini AUTOMATIC olarak ayarlayın. AUTOMATIC politikasıyla belirttiğiniz dataTypes, Google Health API'nin bildirim gönderdiği veri türleriyle aynıdır. Ancak bu veri türleri için kullanıcı izni de verilmiş olmalıdır.

Kullanıcı, AUTOMATIC politikası olan veri türlerine karşılık gelen kapsamlar için uygulama izni verdiğinde Google Health API, kullanıcı tarafından izin verilen veri türleri ile o kullanıcı için otomatik abone yapılandırması veri türlerinin kesişiminden kaynaklanan veri türlerini otomatik olarak izler ve bunlarla ilgili bildirimler gönderir. Ardından, kullanıcı bu türler için yeni veri oluşturduğunda uç noktanıza bildirimler gönderilir. Bu, abone oluşturmadan önce veya sonra izin veren kullanıcılar için geçerlidir. Bildirimler, abone oluşturulmadan önce oluşturulan veriler için doldurulmaz.

Kullanıcı izni iptal ederse ilgili veri türleri için bildirimler durdurulur. Otomatik abonelikler Google tarafından yönetilir ve tek tek listelenemez veya silinemez. Yalnızca üst abone silindiğinde kaldırılırlar.

Manuel abonelikler

Abone, belirli veri türleri için MANUAL subscription_create_policy olarak yapılandırılmışsa her kullanıcı için açıkça abonelik oluşturmanız ve yönetmeniz gerekir. Abonelik, belirli bir kullanıcıyı tanımlanmış bir veri türü grubu için abone uç noktanıza bağlar. Geliştiriciler, belirli API'leri kullanarak:

  • healthUserId başına (manuel) abonelik oluşturma: Belirli bir kullanıcı için yeni bir abonelik oluşturur. Bu yöntemde, abonenin istenen veri türleri için MANUAL olarak ayarlanmış bir SubscriptionCreatePolicy olması gerekir.
  • Aboneliği güncelleme (manuel): Mevcut bir kullanıcı aboneliğinin veri türlerini günceller.
  • Aboneliği silme (manuel): Belirli bir kullanıcı aboneliğini siler. Silme işleminden sonra abone uç noktanız, ilişkili veri türleri için bu kullanıcıyla ilgili bildirimleri artık almaz.
  • Abonelikleri listeleme (manuel): Belirli bir abonenin tüm etkin aboneliklerini listeler. Sonuçları kullanıcıya veya veri türüne göre filtreleyebilirsiniz.

Bildirimler

Abone olunan bir veri türü için kullanıcı verileri değiştiğinde Google Health API, abone uç nokta URL'sine bir HTTPS POST isteği gönderir.

Bildirim biçimi

Bildirim yükü, veri değişikliğiyle ilgili ayrıntıları (ör. kullanıcı kimliği, veri türü ve zaman aralıkları) içerir. Bu ayrıntıları, güncellenen verileri sorgulamak için kullanabilirsiniz. Birden fazla güncelleme gerçekleştiğinde veya güncellemeler birleştirildiğinde bildirimler toplu olarak işlenir ve bildirim nesnelerinden oluşan bir JSON dizisi olarak yayınlanır.

Bir webhook bildirimi tetiklendiğinde Google Health API, abone uç noktanıza aşağıdaki biçimde bir HTTPS POST isteği gönderir:

Upsert (zaman serisi verileri)

POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "subscription-name",
    "healthUserId": "health-user-id",
    "operation": "UPSERT",
    "dataType": "steps",
    "intervals": [
      {
        "physicalTimeInterval": {
          "startTime": "2026-03-08T01: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"
        }
      }
    ]
  }
}

Silme (zaman serisi verileri)

POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

[
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "subscription-name",
      "healthUserId": "health-user-id",
      "operation": "DELETE",
      "dataType": "steps",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-08-12T12:00:00Z",
            "endTime": "2026-08-12T12:30:00Z"
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-08-12T12:00:00",
            "endTime": "2026-08-12T12:30:00"
          }
        }
      ]
    }
  }
]

Silme (kimliği tanımlayabilen veriler)

POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "subscription-name",
    "healthUserId": "health-user-id",
    "operation": "DELETE",
    "dataType": "sleep",
    "intervals": [
      {
        "physicalTimeInterval": {
          "startTime": "2026-08-12T22:00:00Z",
          "endTime": "2026-08-13T06:00:00Z"
        },
        "civilIso8601TimeInterval": {
          "startTime": "2026-08-12T22:00:00",
          "endTime": "2026-08-13T06:00:00"
        }
      }
    ],
    "recordId": "9875412"
  }
}

Toplu (birden fazla kullanıcı ve veri türü)

POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json

[
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
      "healthUserId": "health-user-id-1",
      "operation": "UPSERT",
      "dataType": "steps",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-03-08T01: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"
          }
        }
      ]
    }
  },
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_WEIGHT",
      "healthUserId": "health-user-id-1",
      "operation": "UPSERT",
      "dataType": "weight",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-03-07T15:14:00Z",
            "endTime": "2026-03-07T15:16:00Z"
          },
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 3,
                "day": 7
              },
              "time": {
                "hours": 7,
                "minutes": 14
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 3,
                "day": 7
              },
              "time": {
                "hours": 7,
                "minutes": 16
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-03-07T07:14:00",
            "endTime": "2026-03-07T07:16:00"
          }
        }
      ]
    }
  },
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
      "healthUserId": "health-user-id-2",
      "operation": "UPSERT",
      "dataType": "steps",
      "intervals": [
        {
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 20
              },
              "time": {
                "hours": 0,
                "minutes": 0
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 21
              },
              "time": {
                "hours": 0,
                "minutes": 0
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-08-20T00:00:00",
            "endTime": "2026-08-21T00:00:00"
          }
        }
      ]
    }
  },
  {
    "data": {
      "version": "1",
      "clientProvidedSubscriptionName": "subscription-name",
      "healthUserId": "health-user-id-2",
      "operation": "UPSERT",
      "dataType": "sleep",
      "intervals": [
        {
          "physicalTimeInterval": {
            "startTime": "2026-08-12T22:00:00Z",
            "endTime": "2026-08-13T06:00:00Z"
          },
          "civilDateTimeInterval": {
            "startDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 12
              },
              "time": {
                "hours": 22,
                "minutes": 0
              }
            },
            "endDateTime": {
              "date": {
                "year": 2026,
                "month": 8,
                "day": 13
              },
              "time": {
                "hours": 6,
                "minutes": 0
              }
            }
          },
          "civilIso8601TimeInterval": {
            "startTime": "2026-08-12T22:00:00",
            "endTime": "2026-08-13T06:00:00"
          }
        }
      ],
      "recordId": "9875412"
    }
  }
]

operation alanı, bildirimi tetikleyen değişiklik türünü gösterir:

  • UPSERT: Herhangi bir veri ekleme veya değiştirme işlemi için gönderilir.
  • DELETE: Kullanıcı verileri açıkça sildiğinde (ör. Fitbit uygulamasını kullanarak dataPoints silme veya API'yi kullanarak toplu silme işlemi gerçekleştirme) gönderilir. Kullanıcının uygulama izinlerini iptal etmesi veya Fitbit hesabını silmesi gibi sistem düzeyinde silme etkinlikleri için webhook bildirimleri gönderilmez.

Yeniden denemeler yinelenen bildirimlerin gönderilmesine neden olabileceğinden, özellikle UPSERT işlemleri için bildirim işleme mantığınızı idempotent yapmanızı öneririz.

clientProvidedSubscriptionName alanı benzersiz bir tanımlayıcıdır:

  • MANUAL politikası olan aboneliklerde bu alan, abonelik oluşturulurken geliştirici tarafından sağlanan kalıcı abonelik adını içerir. Bu, manuel abonelikleri yönetmek için sabit bir kimlik sağlar.
  • AUTOMATIC politikasıyla oluşturulan abonelikler için Google Health API, otomatik olarak şu biçimde bir tanımlayıcı oluşturur ve atar: auto-<project-number>-<subscriber-id>-<WEBHOOK_DATA_TYPE_TOKEN>. Burada:
    • <project-number>, geliştiricinin Google Cloud proje numarasıdır (ör. 362978535920).
    • <subscriber-id>, abonenin kayıt kimliği / abone adıdır (ör. google-health-sync).
    • <WEBHOOK_DATA_TYPE_TOKEN>, belirli veri türünü temsil eden jetondur. Olası tüm jetonlar için Webhook veri türü jetonlarının sözlüğü bölümüne bakın.

Hem manuel hem de otomatik politikalar için clientProvidedSubscriptionName eklenmesi, tüm abonelik türlerinde tutarlı bir bildirim yükü biçimi sağlar.

Kullanıcı kimliği eşleme

healthUserId, verileri değişen kullanıcı için bir Google Health API tanımlayıcısıdır. Uygulamanız birden fazla kullanıcıyı destekliyorsa uygulamanıza izin veren tüm kullanıcılar için bildirim alabilirsiniz. Bildirim aldığınızda, hangi kullanıcının verilerinin değiştiğini belirlemek için healthUserId kullanın. Böylece, kullanıcının verilerini sorgulamak için OAuth kimlik bilgilerini kullanabilirsiniz.

Bir kullanıcının OAuth kimlik bilgilerini healthUserId ile eşlemek için getIdentity uç noktasını kullanın. Kullanıcının healthUserId değerini almak için kullanıcı oryantasyonu sırasında bu uç noktayı kullanıcının kimlik bilgileriyle çağırın ve bu eşlemeyi depolayın. Bu eşleme zaman içinde değişmediğinden süresiz olarak önbelleğe alınabilir. Örnek için Kullanıcı kimliğini alma bölümüne bakın. Bu sayede, bildirimdeki healthUserId değerine göre veri sorgularken doğru kullanıcı kimlik bilgilerini seçebilirsiniz.

Zaman aralıkları

intervals dizisi, değiştirilen verilerin zaman aralıklarını temsil eden bir veya daha fazla nesne içerir:

Alan Tür Zorunlu Açıklama
physicalTimeInterval object Hayır Değiştirilen verilerin UTC fiziksel zaman aralığı (YYYY-MM-DDTHH:MM:SSZ biçimi). Gün içi metrikler için doldurulur; günlük toplamlar ve tam gün etkinlikleri için atlanır.
civilDateTimeInterval object Evet Değiştirilen verilerin sivil (yerel) takvim tarihi ve zaman aralığı (UTC veya saat dilimi farkları olmadan).
civilIso8601TimeInterval object Evet UTC veya saat dilimi farkları olmadan ISO 8601 dizesi (YYYY-MM-DDTHH:MM:SS biçimi) olarak temsil edilen sivil (yerel) zaman aralığı.

Tam günlük etkinlikler ve günlük toplamlar için physicalTimeInterval alanı, bildirim yükünden kasıtlı olarak çıkarılır. Bunun nedeni, tam günlük etkinliklerin nominal sivil tarihlerine göre gruplandırılması ve saat dilimleri arasında geçiş yaparken fiziksel sürelerin yanlış olabilmesidir. Tam gün etkinliklerini işlerken en iyi uygulama olarak civilDateTimeInterval veya civilIso8601TimeInterval alanlarını kullanmanız gerekir. Sivil zaman filtrelerini kullanarak bu veri noktalarını sorgulama hakkında ayrıntılı bilgi için Verileri sivil başlangıç zamanı aralığına göre filtreleme başlıklı makaleyi inceleyin.

Aşağıda, physicalTimeInterval alanının atlandığı tam günlük bir etkinlik için örnek bildirim yükü verilmiştir:

{
  "data": {
    "version": "1",
    "clientProvidedSubscriptionName": "auto-503461148219-lindasubscriber-WEBHOOK_DATA_TYPE_STEPS",
    "healthUserId": "343864966078399341",
    "operation": "UPSERT",
    "dataType": "steps",
    "intervals": [
      {
        "civilDateTimeInterval": {
          "startDateTime": {
            "date": {
              "year": 2026,
              "month": 7,
              "day": 14
            },
            "time": {}
          },
          "endDateTime": {
            "date": {
              "year": 2026,
              "month": 7,
              "day": 15
            },
            "time": {}
          }
        },
        "civilIso8601TimeInterval": {
          "startTime": "2026-07-14T00:00:00",
          "endTime": "2026-07-15T00:00:00"
        }
      }
    ]
  }
}

Webhook veri türü jetonlarının sözlüğü

AUTOMATIC politikası kullanılırken oluşturulan clientProvidedSubscriptionName, veri türüne bağlı olarak aşağıdaki büyük harfli WEBHOOK_DATA_TYPE_* son ek jetonlarından birini içerir:

Webhook Veri Türü Jetonu Karşılık Gelen Veri Türü
WEBHOOK_DATA_TYPE_ACTIVE_MINUTES active-minutes
WEBHOOK_DATA_TYPE_ACTIVE_ZONE_MINUTES active-zone-minutes
WEBHOOK_DATA_TYPE_ACTIVITY_LEVEL activity-level
WEBHOOK_DATA_TYPE_ALTITUDE altitude
WEBHOOK_DATA_TYPE_BLOOD_GLUCOSE blood-glucose
WEBHOOK_DATA_TYPE_BODY_FAT body-fat
WEBHOOK_DATA_TYPE_CALORIES_IN_HEART_RATE_ZONE calories-in-heart-rate-zone
WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_VARIABILITY daily-heart-rate-variability
WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_ZONES daily-heart-rate-zones
WEBHOOK_DATA_TYPE_DAILY_OXYGEN_SATURATION daily-oxygen-saturation
WEBHOOK_DATA_TYPE_DAILY_RESPIRATORY_RATE daily-respiratory-rate
WEBHOOK_DATA_TYPE_DAILY_RESTING_HEART_RATE daily-resting-heart-rate
WEBHOOK_DATA_TYPE_DAILY_SLEEP_TEMPERATURE_DERIVATIONS daily-sleep-temperature-derivations
WEBHOOK_DATA_TYPE_DISTANCE distance
WEBHOOK_DATA_TYPE_EXERCISE exercise
WEBHOOK_DATA_TYPE_FLOORS floors
WEBHOOK_DATA_TYPE_HEART_RATE heart-rate
WEBHOOK_DATA_TYPE_HEART_RATE_VARIABILITY heart-rate-variability
WEBHOOK_DATA_TYPE_HEIGHT height
WEBHOOK_DATA_TYPE_HYDRATION_LOG hydration-log
WEBHOOK_DATA_TYPE_NUTRITION_LOG nutrition-log
WEBHOOK_DATA_TYPE_RESPIRATORY_RATE_SLEEP_SUMMARY respiratory-rate-sleep-summary
WEBHOOK_DATA_TYPE_RUN_VO2_MAX run-vo2-max
WEBHOOK_DATA_TYPE_SEDENTARY_PERIOD sedentary-period
WEBHOOK_DATA_TYPE_SLEEP sleep
WEBHOOK_DATA_TYPE_STEPS steps
WEBHOOK_DATA_TYPE_TIME_IN_HEART_RATE_ZONE time-in-heart-rate-zone
WEBHOOK_DATA_TYPE_WEIGHT weight
WEBHOOK_DATA_TYPE_USER_DELETED user-deleted (sistem etkinliği)
WEBHOOK_DATA_TYPE_USER_REVOKED_ACCESS user-revoked-access (sistem etkinliği)

Güncellemelerin toplanması

Google Health API, ağ trafiğini en aza indirmek için mesajları gruplandırır. Sistem, her grupta en fazla 99 mesaj gönderecek şekilde yapılandırılmıştır. Bu mesajlar, kullanılabilir hale geldikçe otomatik olarak gönderilir.

Mesajlar toplu olarak işlendiğinde yük, birden fazla bildirim nesnesi içeren bir JSON dizisi olarak yayınlanır. Tek bir toplu işlem, birden fazla abone olunan veri türünde birden fazla kullanıcı için güncellemeler içerebilir. Örnek bir yük için Bildirim biçimi bölümündeki Toplu (birden fazla kullanıcı ve veri türü) örneğine bakın.

Bir bildirimi yanıtlama

Sunucunuzun Authorization başlığını doğrulaması, eşzamanlı uç nokta doğrulama el sıkışmasını işlemesi ve veri değişikliği bildirimlerine hemen HTTP 204 No Content durum koduyla yanıt vermesi gerekir. Zaman aşımını önlemek için yanıtı gönderdikten sonra bildirim yükünü eşzamansız olarak işleyin. Google Health API başka bir durum kodu alırsa veya istek zaman aşımına uğrarsa bildirimi daha sonra tekrar göndermeyi dener.

Node.js (Express) örneği:

app.post('/webhook-receiver', (req, res) => {
    if (req.headers.authorization !== EXPECTED_SECRET) {
        return res.status(401).send();
    }
    if (req.body && !Array.isArray(req.body) && req.body.type === 'verification') {
        return res.status(200).send();
    }

    // 1. Immediately acknowledge the notification batch
    res.status(204).send();

    // 2. Normalize single-object or batched array notifications and reconcile asynchronously
    const notifications = Array.isArray(req.body) ? req.body : [req.body];
    setImmediate(async () => {
        for (const notification of notifications) {
            const { healthUserId, dataType, intervals = [] } = notification.data || {};
            console.log(`Update for user ${healthUserId} of type ${dataType}`);
            // Query /v4/users/${healthUserId}/dataTypes/${dataType}/dataPoints:reconcile?filter=...
            // for each interval in `intervals` (using >= and < comparators; for sleep, filter on
            // sleep.interval.end_time or sleep.interval.civil_end_time).
        }
    });
});

Bildirilen her aralık için güncellenmiş verileri almak üzere aralığın zaman aralığına yönelik bir filter ile reconcile uç noktasını çağırın. Bu işlem, bağlı cihazlardan gelen çakışan aralıkları otomatik olarak tekilleştirir. Ayrıntılar ve örnekler için Aralık verilerinin mutabakatı yapılmış bir görünümünü alma başlıklı makaleyi inceleyin.

Veri değişikliği bildirimi aldıktan sonra veritabanınızı güncellemek için kullanılan üç yaygın strateji vardır:

  • Sıraya alma (önerilir): Gelen bildirimleri bir ileti sırasına yerleştirin ve sistem kaynaklarına göre sıradan çıkararak işleyin.
  • Anında alma: Arka ucunuzu, güncellenen verileri almak ve veritabanınıza kaydetmek için Google Health API'yi hemen çağıracak şekilde yönlendirin.
  • Yavaş güncellemeler: Kullanıcının yerel veritabanı kayıtlarını kirli olarak işaretleyin ve güncellenmiş verileri yalnızca kullanıcı uygulamanızı bir sonraki ziyaretinde Google Health API'den alın.

Sıraya alma stratejisi, verileri neredeyse gerçek zamanlı olarak işlemenize olanak tanırken bildirim yoğunluğuna karşı dayanıklı olmanızı sağlar (örneğin, bir hizmet kesintisi nedeniyle bildirimlerin birikerek aynı anda teslim edilmesi). Kaynak tasarrufu yapmak için bu sıraları uzun aralıklı bir toplu işlem planına (örneğin, her 3 saatte bir) göre işlemeyi seçebilirsiniz ancak kullanıcılar genellikle verilerinin neredeyse anlık olarak güncellenmesini bekler.

En iyi uygulamalar

Veri güncellemelerinin güvenilir ve verimli bir şekilde işlenmesini sağlamak için aşağıdaki en iyi uygulamaları izleyin:

  • Subscription API'yi kullanın: Uç noktaları yoklamak yerine, bir kullanıcının indirilecek yeni verileri olduğunda bildirim almak için Subscription API'yi kullanın.
  • Bildirimleri ayrı ayrı sıraya koyun ve işleyin: Abonelik bildirimlerini aldığınızda bunları bir sıraya koyun ve sisteminizin kaynaklarına göre ayrı ayrı işleyin. İsteği hemen onaylayarak webhook uç noktasını hafif tutun.

İmza doğrulama

Webhook bildirimlerinin gerçekliğini sağlamak için her giden webhook bildiriminin ham JSON yükü, Tink'in PublicKeySign'ı kullanılarak özel bir anahtarla imzalanır ve istekteki GOOGLE-HEALTH-API-SIGNATURE HTTP üstbilgisinde Base64 kodlu imza sağlanır. Bu imzalama anahtarları her 30 günde bir otomatik olarak değiştirilir ve ilgili resmi ortak anahtar grubu, https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json kalıcı URL'sinde JSON dosyası olarak dağıtılır.

İmzayı doğrulama

Tink'i kullanma (Önerilir): Geliştiriciler, Tink'in PublicKeyVerify temel öğesini kullanarak imzayı doğrulayabilir. Kalıcı URL'den ortak anahtar grubunu alın, anahtar grubuyla PublicKeyVerify temel öğesini örneklendirin ve kodu çözülmüş GOOGLE-HEALTH-API-SIGNATURE üst bilgisini ham webhook JSON yüküne göre doğrulayın.

Manuel Doğrulama (Tink Olmadan): Geliştiriciler Tink'i kullanmamayı tercih ederlerse aşağıdaki adımları uygulayarak imzayı manuel olarak doğrulayabilirler:

  1. 5 baytlık Tink ön ekini (1 baytlık sürüm ön eki ve 4 baytlık keyId içerir) gerçek DER kodlamalı imzadan ayırmak için GOOGLE-HEALTH-API-SIGNATURE başlığının Base64 kodunu çözer.
  2. JSON anahtar grubunu https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json adresinden alın.
  3. Ayrıştırılmış keyId ile eşleşen anahtarı bulun ve değer alanının Base64 kodunu çözün. Bu alan, serileştirilmiş bir EcdsaPublicKey protokol arabelleği içerir.
  4. Bu ikili yükten big-endian x ve y koordinatlarını (Protobuf etiketleri 3 ve 4) çıkarın.
  5. Ayıklanan x ve y koordinatlarını kullanarak yerleşik bir kriptografi kitaplığında standart bir ECDSA P-256 ortak anahtarını örneklendirin.
  6. SHA-256 algoritmasını kullanarak ham webhook JSON yükünü ayıklanan DER imzasıyla doğrulayın.

Abone durumu ve kurtarma

Abone uç noktanız kullanılamaz hale gelirse veya hata durum kodu (204 dışında herhangi bir kod) döndürürse Google Health API, bekleyen bildirimleri 7 güne kadar saklar ve eksponansiyel geri yükleme ile teslimatı yeniden dener.

Uç noktanız tekrar yayına girip 204 ile yanıt verdiğinde API, depolanan mesajların birikmiş işlerini otomatik olarak yayınlar. 7 günden eski bildirimler silinir ve kurtarılamaz.

Sık karşılaşılan hatalar

Hata kodu Mesaj Açıklama Öneri
400 Hatalı İstek Kaynak adındaki proje numarası geçersiz İstek URL'sinde proje numarası yerine Google Cloud proje kimliğinizi kullanarak bir aboneyi silerken veya güncellerken. Bu, projects.subscribers uç noktasını kullanan webhook abonelikleri için geçerlidir. İstek URL'sinde proje kimliğini değil, Google Cloud proje numaranızı kullanın.
403 Yasak Arayanın izni yok İstek URL'sinde proje numarası yerine Google Cloud proje kimliğinizi kullanarak abone oluştururken veya listelerken. Bu, projects.subscribers uç noktasını kullanan webhook abonelikleri için geçerlidir. İstek URL'sinde proje kimliğini değil, Google Cloud proje numaranızı kullanın.