Subskrypcje webhooków


Interfejs Google Health API umożliwia aplikacji otrzymywanie powiadomień w czasie rzeczywistym o zmianach w danych o zdrowiu użytkownika. Zamiast sondowania zmian, serwer otrzymuje żądanie HTTPS POST (webhook) od razu, gdy dane są dostępne w interfejsie Google Health API.

Obsługiwane typy danych

Powiadomienia webhook są obsługiwane w przypadku tych typów danych:

  • Kroki
  • Wysokość
  • Odległość
  • Piętra
  • Waga
  • Sen

Powiadomienia są wysyłane w przypadku tych typów danych tylko wtedy, gdy użytkownik wyraził zgodę na jeden z odpowiednich zakresów:

  • Aktywność, która obejmuje typy danych dotyczące kroków, wysokości, dystansu i pięter:
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
  • Wskaźniki zdrowotne, które obejmują typ danych dotyczących wagi:
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
  • Sen, który obejmuje typ danych o śnie:
    • https://www.googleapis.com/auth/googlehealth.sleep
    • https://www.googleapis.com/auth/googlehealth.sleep.readonly

Zarządzanie subskrybentami

Aby otrzymywać powiadomienia, musisz zarejestrować subskrybenta, który reprezentuje punkt końcowy powiadomień aplikacji. Subskrybentami możesz zarządzać za pomocą interfejsu API REST dostępnego pod adresem projects.subscribers.

Punkt końcowy subskrybenta musi używać protokołu HTTPS (TLSv1.2+) i być publicznie dostępny. Podczas tworzenia i aktualizowania subskrybentów interfejs API Google Health przeprowadza weryfikację, aby upewnić się, że jesteś właścicielem identyfikatora URI punktu końcowego. Jeśli weryfikacja się nie powiedzie, operacje tworzenia i aktualizowania subskrybentów zakończą się niepowodzeniem z błędem FailedPreconditionException.

Tworzenie subskrybenta

Aby zarejestrować nowego subskrybenta w projekcie, użyj punktu końcowego create. Musisz podać te dane:

  • endpointUri: docelowy adres URL powiadomień webhooka.
  • subscriberConfigs: typy danych, dla których chcesz otrzymywać powiadomienia, oraz zasady subskrypcji dla każdego z nich.
  • endpointAuthorization: Mechanizm autoryzacji punktu końcowego. Musi on zawierać podany przez Ciebie znak authorization_token. Wartość authorization_token jest wysyłana w nagłówku Authorization z każdą wiadomością z powiadomieniem. Za pomocą tego tokena możesz sprawdzać, czy żądania przychodzące pochodzą z interfejsu Google Health API. Możesz na przykład ustawić authorization_token na Bearer R4nd0m5tr1ng123 w przypadku uwierzytelniania przy użyciu tokena okaziciela lub na Basic dXNlcjpwYXNzd29yZA== w przypadku uwierzytelniania podstawowego.
  • subscriberId: unikalny identyfikator subskrybenta podany przez Ciebie. Identyfikator musi mieć od 4 do 36 znaków i pasować do wyrażenia regularnego ([a-z]([a-z0-9-]{2,34}[a-z0-9])).

W przypadku każdego typu danych musisz ustawić subscriptionCreatePolicysubscriberConfigs. Ustaw wartość AUTOMATIC, aby używać automatycznych subskrypcji, lub MANUAL, jeśli zamierzasz samodzielnie zarządzać subskrypcjami użytkowników. Więcej informacji o poszczególnych opcjach znajdziesz w sekcjach Subskrypcje automatyczneSubskrypcje ręczne.

Żądanie

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

Odpowiedź

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

Wyświetlanie listy subskrybentów

Użyj punktu końcowego list, aby pobrać wszystkich subskrybentów zarejestrowanych w Twoim projekcie.

Żądanie

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

Odpowiedź

{
  "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": ""
}

Aktualizowanie subskrybenta

Użyj punktu końcowego patch, aby zaktualizować subskrybenta w projekcie. Pola, które można zaktualizować, to endpointUri, subscriberConfigs i endpointAuthorization.

Pola aktualizuje się, podając parametr zapytania updateMask i treść żądania. Parametr updateMask musi zawierać rozdzieloną przecinkami listę nazw pól, które chcesz zaktualizować. Nazwy pól muszą być zapisane w formacie camel case (np. endpointUri). Treść żądania musi zawierać częściowy obiekt Subscriber z nowymi wartościami pól, które chcesz zaktualizować. Aktualizowane są tylko pola określone w updateMask. Jeśli w treści żądania podasz pola, których nie ma w updateMask, zostaną one zignorowane.

Jeśli zaktualizujesz endpointUri lub endpointAuthorization, zostanie przeprowadzona weryfikacja punktów końcowych. Więcej informacji znajdziesz w artykule Weryfikacja punktów końcowych.

Podczas aktualizowania subscriberConfigs pamiętaj, że jest to pełna zamiana, a nie scalanie. Jeśli subscriberConfigs jest uwzględniony w updateMask, wszystkie zapisane konfiguracje subskrybenta zostaną zastąpione listą podaną w treści żądania. Aby dodać lub usunąć konfigurację, musisz podać pełny zestaw konfiguracji. Jeśli aktualizujesz inne pola i chcesz zachować obecne konfiguracje, pomiń subscriberConfigs w updateMask.

Żądanie

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

Odpowiedź

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

Weryfikacja punktów końcowych

Aby zapewnić bezpieczeństwo i niezawodność dostarczania powiadomień, interfejs Google Health API przeprowadza obowiązkową weryfikację dwuetapową za każdym razem, gdy tworzysz subskrybenta lub aktualizujesz jego konfigurację punktu końcowego (endpointUri lub endpointAuthorization). Ten proces jest wykonywany synchronicznie podczas wywołania interfejsu API. Usługa wysyła 2 automatyczne żądania POST do adresu URI punktu końcowego, używając nagłówka User-Agent Google-Health-API-Webhooks-Verifier i treści JSON {"type": "verification"}.

  • Autoryzowane uzgadnianie: pierwsze żądanie jest wysyłane z nagłówkiem Authorization skonfigurowanym przez Ciebie. Serwer musi odpowiadać stanem 200 OK lub 201 Created.
  • Nieautoryzowane wyzwanie: drugie żądanie jest wysyłane bez danych logowania. Serwer musi odpowiadać stanem 401 Unauthorized lub 403 Forbidden.

Ten proces potwierdza, że punkt końcowy jest aktywny i prawidłowo egzekwuje zabezpieczenia. Jeśli którykolwiek z tych kroków się nie powiedzie, żądanie do interfejsu API zakończy się błędem FAILED_PRECONDITION. Dopiero po pomyślnym zakończeniu tego procesu subskrybent zostanie zapisany i aktywny, aby otrzymywać powiadomienia o danych dotyczących zdrowia.

Rotacja kluczy

Jeśli musisz dokonać rotacji kluczy w przypadku endpointAuthorization, wykonaj te czynności:

  1. Skonfiguruj punkt końcowy tak, aby akceptował zarówno stare, jak i nowe wartości endpointAuthorization.
  2. Zaktualizuj konfigurację subskrybenta, podając nową wartość endpointAuthorization, za pomocą żądania patch z parametrem ?updateMask=endpointAuthorization.
  3. Skonfiguruj punkt końcowy tak, aby akceptował tylko nową wartość endpointAuthorization po potwierdzeniu, że krok 2 został wykonany prawidłowo.

Usuwanie subskrybenta

Użyj punktu końcowego delete, aby usunąć subskrybenta z projektu. Po usunięciu subskrybent nie będzie już otrzymywać powiadomień.

Żądanie

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

Odpowiedź

Jeśli usunięcie się powiedzie, zwracana jest pusta treść odpowiedzi z kodem stanu HTTP „200 OK”.
{}

Subskrypcje użytkownika

Interfejs Google Health API pomaga skutecznie zarządzać subskrypcjami użytkowników, co zmniejsza potrzebę ręcznej rejestracji podczas wprowadzania użytkowników.

Automatyczne subskrypcje

Zalecamy korzystanie z automatycznych subskrypcji. Aby włączyć tę funkcję, ustaw wartość subscriptionCreatePolicy na AUTOMATICsubscriberConfigs dla konkretnych typów danych. dataTypes, które określisz w zasadach AUTOMATIC, to te same typy danych, w przypadku których interfejs API Google Health wysyła powiadomienia, pod warunkiem że zgoda użytkownika zostanie również udzielona na te typy danych.

Gdy użytkownik wyrazi zgodę na zakresy aplikacji, które odpowiadają typom danych objętym AUTOMATIC zasadami, interfejs Google Health API automatycznie śledzi typy danych wynikające z części wspólnej typów danych użytkowników, którzy wyrazili zgodę, i typów danych automatycznej konfiguracji subskrybenta dla tego użytkownika, a także wysyła powiadomienia o tych typach danych. Powiadomienia są następnie wysyłane do punktu końcowego za każdym razem, gdy użytkownik generuje nowe dane tych typów. Dotyczy to użytkowników, którzy wyrażą zgodę przed utworzeniem subskrybenta lub po jego utworzeniu. Powiadomienia nie są uzupełniane w przypadku danych wygenerowanych przed utworzeniem subskrybenta.

Jeśli użytkownik wycofa zgodę, powiadomienia dotyczące odpowiednich typów danych przestaną być wysyłane. Subskrypcjami automatycznymi zarządza Google i nie można ich wyświetlać ani usuwać pojedynczo. Są one usuwane tylko wtedy, gdy usunięty zostanie subskrybent nadrzędny.

Subskrypcje ręczne

Jeśli wolisz zarządzać subskrypcjami poszczególnych użytkowników ręcznie, ustaw subscriptionCreatePolicy na MANUAL w subscriberConfigs. Zgodnie z tą zasadą subskrypcje użytkowników nie są tworzone automatycznie. Ta funkcja będzie używana w przyszłości, gdy udostępnimy interfejsy API do zarządzania subskrypcjami ręcznymi. Do czasu udostępnienia tych interfejsów API zalecamy korzystanie z AUTOMATIC subskrypcji.

Powiadomienia

Gdy dane użytkownika zmienią się w przypadku subskrybowanego typu danych, interfejs Google Health API wyśle żądanie HTTPS POST na adres URL punktu końcowego subskrybenta.

Format powiadomienia

Ładunek powiadomienia to obiekt JSON zawierający szczegóły zmiany danych. Obejmuje to identyfikator użytkownika, typ danych i przedziały czasowe, których możesz używać do wysyłania zapytań dotyczących zaktualizowanych danych.

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

Pole operation wskazuje typ zmiany, która wywołała powiadomienie:

  • UPSERT: wysyłany w przypadku dodania lub zmodyfikowania danych.
  • DELETE: wysyłany, gdy użytkownik usunie dane lub gdy dane zostaną usunięte z powodu zdarzenia systemowego, np. gdy użytkownik cofnie uprawnienia lub usunie konto.

Zalecamy, aby logika obsługi powiadomień była idempotentna, zwłaszcza w przypadku operacji UPSERT, ponieważ ponowne próby mogą powodować wysyłanie zduplikowanych powiadomień.

Pole clientProvidedSubscriptionName to unikalny identyfikator. W przypadku subskrypcji objętych MANUAL zasadami to pole zawiera trwałą nazwę subskrypcji podaną przez dewelopera podczas tworzenia subskrypcji. Zapewnia to stabilny identyfikator do zarządzania subskrypcjami ustawianymi samodzielnie. W przypadku subskrypcji utworzonych za pomocą AUTOMATIC zasad interfejs Google Health API automatycznie generuje i przypisuje do tego pola unikalny identyfikator (losowy identyfikator UUID) dla każdego powiadomienia. Uwzględnienie clientProvidedSubscriptionName w przypadku zasad ręcznych i automatycznych zapewnia spójny format ładunku powiadomienia we wszystkich typach subskrypcji.

healthUserId to identyfikator interfejsu API Google Health użytkownika, którego dane uległy zmianie. Jeśli Twoja aplikacja obsługuje wielu użytkowników, możesz otrzymywać powiadomienia dotyczące każdego użytkownika, który wyraził zgodę na korzystanie z niej. Gdy otrzymasz powiadomienie, użyj healthUserId, aby określić, które dane użytkownika uległy zmianie. Dzięki temu możesz użyć jego danych logowania OAuth do wysłania zapytania o jego dane.

Aby zmapować dane logowania OAuth użytkownika na jego healthUserId, użyj punktu końcowego getIdentity. Wywołaj ten punkt końcowy za pomocą danych logowania użytkownika podczas wprowadzania użytkownika, aby pobrać jego healthUserId i zapisać to mapowanie. To mapowanie nie zmienia się z czasem, więc można je przechowywać w pamięci podręcznej bez ograniczeń. Przykład znajdziesz w sekcji Pobieranie identyfikatora użytkownika. Dzięki temu możesz wybrać prawidłowe dane logowania użytkownika podczas wysyłania zapytań o dane na podstawie ikony healthUserId w powiadomieniu.

Podejmowanie działania w związku z powiadomieniem

Serwer musi natychmiast odpowiadać na powiadomienia kodem stanu HTTP 204 No Content. Aby uniknąć przekroczenia limitu czasu, przetwórz ładunek powiadomienia asynchronicznie po wysłaniu odpowiedzi. Jeśli interfejs Google Health API otrzyma inny kod stanu lub żądanie przekroczy limit czasu, ponowi wysyłanie powiadomienia w późniejszym czasie.

Przykład 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
    });
});

Stan subskrybenta i odzyskiwanie

Jeśli punkt końcowy subskrybenta stanie się niedostępny lub zwróci kod stanu błędu (inny niż 204), interfejs Google Health API będzie przechowywać oczekujące powiadomienia przez maksymalnie 7 dni i ponawiać ich dostarczanie z wzrastającym czasem do ponowienia.

Gdy punkt końcowy znów będzie dostępny i odpowie kodem 204, interfejs API automatycznie dostarczy zaległe wiadomości. Powiadomienia starsze niż 7 dni są odrzucane i nie można ich odzyskać.