Ta strona zawiera omówienie konwencji interfejsu API typu REST oraz indeks typowych zadań interfejsu Google Health API i przykłady każdego z nich.
Konwencje interfejsu API typu REST
Interfejs Google Health API jest zgodny ze standardami Google API Improvement Proposals (AIP), w szczególności z AIP-127 (HTTP and gRPC Transcoding) oraz AIP-131– AIP-135 (Standard Methods). Standardy te określają, jak dane są mapowane z komunikatu proto na żądanie HTTP.
Parametry zapytania
Parametry zapytania są używane, gdy dane są częścią adresu URL. Dotyczy to głównie żądań GET (pobieranie zasobu) lub LIST (filtrowanie/stronicowanie), ale jest też używane w przypadku operacji DELETE.
- Umiejscowienie: dołączane do adresu URL po znaku
?. - Składnia: pary klucz-wartość rozdzielone znakiem
&. - Mapowanie: każde pole w komunikacie żądania, które nie jest częścią szablonu ścieżki URL , jest mapowane na parametr zapytania.
- Najlepsze w przypadku: prostych typów (ciągi znaków, liczby całkowite, wyliczenia) i pól powtarzających się.
Przykładowa składnia:
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"
Treść żądania
Treść żądania jest używana, gdy dane modyfikują stan zasobu lub są zbyt duże, aby można je było umieścić w adresie URL. Treść jest zwykle reprezentacją JSON samego zasobu. Zwykle używana w przypadku operacji POST, PATCH i PUT.
- Umiejscowienie: w ładunku HTTP (niewidoczne w adresie URL).
- Składnia: sformatowana jako obiekt JSON.
- Mapowanie: zdefiniowane w adnotacji
google.api.http.body: "*"oznacza, że cała wiadomość jest treścią.body: "resource_name"oznacza, że tylko określone pole w proto jest treścią.
- Najlepsze w przypadku: złożonych obiektów, zagnieżdżonych wiadomości i danych wrażliwych.
Przykładowa składnia:
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"
}Przypadek hybrydowy
W metodzie Update zgodnej z AIP-134 lub w operacji PATCH używane są obie te metody.
Adres URL zawiera nazwę zasobu, treść zawiera zaktualizowane dane zasobu, a parametr zapytania (zwykle update_mask) określa, które pola należy zmienić.
PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
Content-Type: application/json
{
"endpointUri": "https://myapp.com/new-webhooks/health"
}
Najważniejsze różnice w skrócie
| Funkcja | Parametry zapytania | Treść żądania |
|---|---|---|
| Wskazówki AIP | Używane do wyszukiwania, filtrowania i operacji odczytu. | Używane do operacji zapisu. |
| Widoczność | Widoczne w historii przeglądarki i logach serwera. | Ukryte w adresie URL. |
| Złożoność | Ograniczone do płaskich lub powtarzających się struktur. | Obsługuje głęboko zagnieżdżone obiekty JSON. |
| Kodowanie | Musi być zakodowane na potrzeby adresu URL (np. spacje stają się %20). |
Standardowe kodowanie JSON. |
Daty
Wszystkie daty w interfejsie Google Health API są wyświetlane w formacie YYYY-MM-DD. Interfejs Nutrition API obsługuje standard ISO-8601 w przypadku wartości dat z tymi warunkami:
- 4-cyfrowy rok
YYYY - Wartości roku w zakresie 0000–9999
- Brak egzekwowania ograniczeń daty rozpoczęcia wynikających ze standardu ISO-8601 lub innej epoki
Nagłówki
Wykonanie punktów końcowych interfejsu Google Health API wymaga użycia odpowiednich nagłówków i tokena dostępu. W przypadku żądań GET i POST zalecamy użycie tego nagłówka:
Authorization: Bearer access-token Accept: application/json
Indeks zadań interfejsu API
Ta sekcja zawiera indeks typowych zadań interfejsu Google Health API i przykłady każdego z nich.
Pobieranie identyfikatora użytkownika Fitbita lub Google
Gdy użytkownik wyrazi zgodę za pomocą Google OAuth 2.0, odpowiedź tokena nie będzie zawierać identyfikatora użytkownika Fitbita ani Google. Aby uzyskać identyfikator użytkownika, wywołaj
getIdentity punkt końcowy. getIdentity
zwraca zarówno starszy identyfikator użytkownika Fitbita, jak i identyfikator użytkownika Google.
Zalecamy, aby po wyrażeniu zgody przez nowego użytkownika za pomocą OAuth wywołać punkt końcowy getIdentity i zapisać oba identyfikatory użytkownika. Zapewni to zgodność wsteczną i przyszłą w integracji.
Na przykład:
Żądanie
GET https://health.googleapis.com/v4/users/me/identity Authorization: Bearer access-token Accept: application/json
Odpowiedź
{
"name": "users/me/identity",
"legacyUserId": "A1B2C3",
"healthUserId": "111111256096816351"
}Pobieranie danych śródsezonowych lub szczegółowych zebranych w ciągu dnia
Aby uzyskać dane śródsezonowe lub szczegółowe zebrane w ciągu dnia w
obsługiwanych przedziałach czasu dla danego typu danych, użyj list
punktu końcowego dla określonego
typu danych.
Na przykład:
Żądanie
GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints Authorization: Bearer access-token Accept: application/json
Odpowiedź
{
"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"
}Filtrowanie danych według czasu rozpoczęcia przedziału czasu
Aby filtrować dane według czasu lub przedziału czasu, użyj punktu końcowego list z parametrem filter.
Na przykład:
Żądanie
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
Odpowiedź
{
"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"
}Filtrowanie danych według czasu fizycznego obserwacji próbki
Aby filtrować dane według czasu fizycznego obserwacji próbki, użyj punktu końcowego list z parametrem filter.
Na przykład:
Żądanie
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
Odpowiedź
{
"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": ""
}Filtrowanie danych według źródeł danych, takich jak urządzenia do noszenia
Aby uzyskać dane z określonej "rodziny źródeł danych", użyj reconcile
punktu końcowego. Aby to zrobić, określ parametr dataSourceFamily jako parametr zapytania.
W tabeli poniżej opisano obsługiwane opcje dataSourceFamily:
| Opcja | Opis |
|---|---|
users/me/dataSourceFamilies/all-sources |
Wartość domyślna. Zawiera dane ze wszystkich dostępnych źródeł danych. |
users/me/dataSourceFamilies/google-wearables |
Zawiera dane z urządzeń do noszenia Google i Fitbit (takich jak trackery Fitbit i Pixel Watch). Wyklucza dane logowane ręcznie. |
users/me/dataSourceFamilies/google-sources |
Zawiera dane własne Google, takie jak dane z urządzeń do noszenia i dane logowane ręcznie. |
Oto przykład filtrowania tylko snu zarejestrowanego przez urządzenie do noszenia w dniu 2026-03-03:
Żądanie
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
Odpowiedź
{
"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": ""
}Agregowanie punktów danych w przedziale czasu
Aby zwrócić agregację punktów danych na podstawie okna w sekundach w zakresie datetime na podstawie czasu fizycznego użytkowników (w UTC), użyj rollUp
punktu końcowego.
Wywołując punkt końcowy rollUp, musisz podać treść żądania reprezentującą wymagany zakres dat w czasie użytkownika. Na przykład:
Żądanie
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"
}Odpowiedź
{
"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"
}
},
...
]
}Agregowanie danych z jednego lub kilku dni
Punkt końcowy dailyRollUp
powinien być
używany, gdy chcesz agregować dane z
jednego lub kilku dni, znanych jako windowSize. W treści żądania podaj zamknięty zakres czasu dla wymaganego przedziału czasu. W zależności od typu danych otrzymasz sumę lub średnią z przedziału.
Na przykład:
Żądanie
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
}Odpowiedź
{
"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"
}
}
]
}Wstawianie lub aktualizowanie danych dotyczących zdrowia użytkownika
Aby wstawić lub zaktualizować dane użytkownika w aplikacji Fitbit, użyj patch
punktu końcowego.
Oto przykład, w którym użytkownik zarejestrował poziom tkanki tłuszczowej na wadze „HumanScale” firmy „Scales R Us”. Nowy odczyt tkanki tłuszczowej użytkownika to 20% w dniu 2026-03-10.
Żądanie
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
}
}Odpowiedź
{
"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
}
}
}Rejestrowanie produktu spożywczego
Aby zarejestrować produkt spożywczy, wyślij żądanie POST do punktu końcowego danych nutrition-log. Treść żądania zawiera DataPoint z obiektem nutritionLog.
Więcej informacji znajdziesz w przewodniku po odżywianiu.
Na przykład:
Żądanie
POST https://health.googleapis.com/v4/users/me/dataTypes/nutrition-log/dataPoints
Authorization: Bearer access-token
Content-Type: application/json
{
"nutritionLog": {
"interval": {
"startTime": "2026-06-16T12:00:00Z",
"endTime": "2026-06-16T12:30:00Z"
},
"foodDisplayName": "Banana",
"mealType": "LUNCH",
"energy": {
"kcal": 105
},
"totalCarbohydrate": {
"grams": 27
},
"totalFat": {
"grams": 0.3
}
}
}Odpowiedź
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.devicesandservices.health.v4.DataPoint",
"name": "users/2515055256096816351/dataTypes/nutrition-log/dataPoints/567890",
"dataSource": {
"recordingMethod": "ACTIVELY_MEASURED",
"platform": "GOOGLE_WEB_API"
},
"nutritionLog": {
"interval": {
"startTime": "2026-06-16T12:00:00Z",
"startUtcOffset": "0s",
"endTime": "2026-06-16T12:30:00Z",
"endUtcOffset": "0s"
},
"energy": {
"kcal": 105
},
"totalCarbohydrate": {
"grams": 27
},
"totalFat": {
"grams": 0.3
},
"mealType": "LUNCH",
"foodDisplayName": "Banana"
}
}
}Usuwanie danych dotyczących zdrowia użytkownika
Aby usunąć tablicę danych użytkownika w aplikacji Fitbit, użyj batchDelete
punktu końcowego.
Oto przykład, w którym użytkownik wcześniej zarejestrował poziom tkanki tłuszczowej na wadze, ale chce usunąć ten rekord. Używanie user-id i data-point-id z pierwotnej operacji wstawiania:
Żądanie
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"
]
}Odpowiedź
{
"done": true,
"response": {
"@type": "type.googleapis.com/google.devicesandservices.health.v4main.BatchDeleteDataPointsResponse"
}
}Znajdowanie informacji o urządzeniu
Aby pobrać listę urządzeń sparowanych z kontem użytkownika, użyj punktu końcowego list do. Obejmuje to informacje o modelu urządzenia (deviceVersion) i czas ostatniej synchronizacji z aplikacją mobilną Google Health (lastSyncTime).
Informacje o konfiguracji listy i synchronizacji są przydatne do rozwiązywania problemów z synchronizacją lub pobierania danych historycznych od czasu ostatniej synchronizacji.
Na przykład:
Żądanie
GET https://health.googleapis.com/v4/users/me/pairedDevices Authorization: Bearer access-token Accept: application/json
Odpowiedź
{
"pairedDevices": [
{
"name": "users/me/pairedDevices/123456",
"deviceType": "TRACKER",
"batteryStatus": "High",
"batteryLevel": 88,
"lastSyncTime": "2026-03-04T07:05:00Z",
"deviceVersion": "Charge 6",
"macAddress": "00:11:22:33:44:55",
"features": [
"STEPS",
"HEART_RATE"
]
}
]
}Wykonywanie zapytań o dane historyczne
Jedną z głównych zalet interfejsu Google Health API jest możliwość śledzenia wyników użytkownika i monitorowania jego parametrów zdrowia przez długi czas. Możesz wysyłać zapytania o dane użytkownika tak długo, jak są one rejestrowane. Interfejs API nie nakłada żadnych ograniczeń na ilość danych historycznych, które może wykorzystywać Twoja aplikacja.
Wysyłanie zapytań o dane historyczne podlega jednak standardowym limitom liczby żądań. Aby zmniejszyć liczbę wywołań interfejsu API w stosunku do tych limitów, interfejs Google Health API obsługuje wysyłanie zapytań o dane w zakresie dat. Pamiętaj o tych ograniczeniach dotyczących stronicowania i żądań:
- Każdy punkt końcowy zwraca maksymalny rozmiar strony wynoszący 10 000 punktów danych na stronę.
- Zakresy dat zapytań są ograniczone do 14–90 dni na żądanie.
W zależności od ilości danych historycznych, których potrzebuje Twoja aplikacja, pobranie całego zbioru danych może wymagać kilku kolejnych żądań i dodatkowego czasu. Pamiętaj o tym podczas projektowania procesu synchronizacji danych aplikacji.
Aby zapewnić optymalną wydajność i uniknąć błędów interfejsu API, podczas wysyłania zapytań o dane historyczne postępuj zgodnie z tymi wskazówkami:
Synchronizacja danych etapami (wczytywanie na gorąco i wczytywanie „na zimno”)
- Początkowe wczytywanie „na gorąco”: podczas głównej sekwencji wczytywania pobieraj i renderuj tylko dane z ostatnich 7–14 dni. Dzięki temu użytkownicy od razu widzą dane bez czekania na długotrwałe zapytania.
- Wczytywanie „na zimno” w tle: po renderowaniu głównego interfejsu użytkownika deleguj pobieranie starszych danych historycznych do asynchronicznej kolejki o niższym priorytecie lub procesu w tle.
Dzielenie zapytań na podstawie czasu
- Nie wysyłaj w jednym wywołaniu interfejsu API żądań obejmujących okresy wieloletnie lub wielomiesięczne. Dziel duże zapytania historyczne na mniejsze, kolejne przedziały (np. 1 tydzień na żądanie).
- Bezpiecznie grupuj lub sekwencjonuj te podzapytania, aby zachować limity współbieżności i utrzymywać stałe wskaźniki postępu interfejsu użytkownika.
Wykorzystanie wstępnie zagregowanych danych zbiorczych
Zmień strukturę paneli przeglądowych i wykresów trendów, aby używać wstępnie zagregowanych punktów końcowych podsumowania (takich jak DailyRollUpDataPoints). Znacznie zmniejszy to obciążenie obliczeniowe na backendzie i czas przesyłania danych do klienta.
Odporna obsługa błędów (inteligentne ponawianie prób)
- W przypadku napotkania limitów liczby żądań (
429 Too Many Requests) i przekroczenia limitu czasu bramy serwera (504 Gateway Timeout) wdróż ścisłą obsługę wzrastającego czasu do ponowienia. Nigdy nie ponawiaj od razu prób wysyłania dużych, nieudanych ładunków. Natychmiastowe ponawianie prób zwiększa przeciążenie backendu i pogarsza działanie systemu. - Jeśli zapytanie wielokrotnie przekracza limit czasu, automatycznie przejdź na mniejszy przedział czasu (np. zmniejsz 1-tygodniowy fragment do 3 dni).