Endpoint

Questa pagina fornisce una panoramica delle convenzioni dell'API REST, insieme a un indice delle attività comuni dell'API Google Health ed esempi di ciascuna.

Convenzioni delle API REST

L'API Google Health segue gli standard delle proposte di miglioramento delle API Google (AIP), in particolare AIP-127 (transcodifica HTTP e gRPC) e AIP-131-AIP-135 (metodi standard). Questi standard definiscono il modo in cui i dati vengono mappati da un messaggio proto a una richiesta HTTP.

Parametri di query

I parametri di query vengono utilizzati quando i dati fanno parte dell'URL. Questo valore è principalmente per le richieste GET (recupero di una risorsa) o LIST (filtraggio/impaginazione), ma viene utilizzato anche per le operazioni DELETE.

  • Posizionamento: aggiunto all'URL dopo un ?.
  • Sintassi: coppie chiave-valore separate da &.
  • Mappatura: ogni campo del messaggio di richiesta che non fa parte del modello di percorso URL viene mappato a un parametro di query.
  • Ideale per: tipi semplici (stringhe, numeri interi, enumerazioni) e campi ripetuti.

Sintassi di esempio:

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"

Corpo della richiesta

Il corpo della richiesta viene utilizzato quando i dati modificano lo stato di una risorsa o sono troppo grandi per un URL. Il corpo è in genere una rappresentazione JSON della risorsa stessa. In genere utilizzato per le operazioni POST, PATCH e PUT.

  • Posizionamento: all'interno del payload HTTP (non visibile nell'URL).
  • Sintassi: formattato come oggetto JSON.
  • Mappatura: definita nell'annotazione google.api.http.
    • body: "*" significa che l'intero messaggio è il corpo.
    • body: "resource_name" significa che solo un campo specifico del proto è il corpo.
  • Ideale per: oggetti complessi, messaggi nidificati e dati sensibili.

Sintassi di esempio:

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

Lo scenario ibrido

In un metodo Update conforme ad AIP-134 o in un'operazione PATCH, vengono utilizzati entrambi. L'URL contiene il nome della risorsa, il corpo contiene i dati della risorsa aggiornati e un parametro di query (di solito update_mask) specifica i campi da modificare.

PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
Content-Type: application/json

{
  "endpointUri": "https://myapp.com/new-webhooks/health"
}

Differenze principali in sintesi

Funzionalità Parametri di query Corpo della richiesta
Indicazioni AIP Utilizzato per le operazioni di ricerca, filtro e lettura. Utilizzato per le operazioni di scrittura.
Visibilità Visibile nella cronologia del browser e nei log del server. Nascosto nell'URL.
complessità Limitato a strutture piatte o ripetute. Supporta oggetti JSON nidificati in profondità.
Codifica Deve essere codificato nell'URL (ad esempio, gli spazi diventano %20). Codifica JSON standard.

Date

Tutte le date nell'API Google Health vengono visualizzate nel formato YYYY-MM-DD. L'API Nutrition supporta lo standard ISO-8601 per i valori di data con le seguenti condizioni:

  • Un anno a 4 cifre YYYY
  • Valori dell'anno compresi nell'intervallo 0000-9999
  • Nessuna applicazione delle limitazioni della data di inizio implicite nello standard ISO-8601 o in altre epoche

Intestazioni

L'esecuzione degli endpoint dell'API Google Health richiede l'utilizzo delle intestazioni e del token di accesso appropriati. La seguente intestazione è consigliata sia per le richieste GET che POST:

Authorization: Bearer access-token
Accept: application/json

Indice delle attività API

Questa sezione fornisce un indice delle attività comuni dell'API Google Health ed esempi di ciascuna.

Ottenere l'ID utente Fitbit o Google

Dopo che un utente ha dato il consenso tramite Google OAuth 2.0, la risposta del token non contiene l'ID utente Fitbit o Google. Per ottenere l'ID utente, chiama l'endpoint getIdentity. getIdentity restituisce sia l'ID utente Fitbit legacy sia l'ID utente Google.

Ti consigliamo di chiamare l'endpoint getIdentity e memorizzare entrambi gli ID utente non appena un nuovo utente fornisce il consenso tramite OAuth. Ciò garantisce la compatibilità con le versioni precedenti e future dell'integrazione.

Ad esempio:

Richiesta

GET https://health.googleapis.com/v4/users/me/identity
Authorization: Bearer access-token
Accept: application/json

Risposta

{
  "name": "users/me/identity",
  "legacyUserId": "A1B2C3",
  "healthUserId": "111111256096816351"
}

Visualizzare dati intragiornalieri o dettagliati raccolti durante una giornata

Utilizza l'endpoint list per un tipo di dati specifico per ottenere dati intraday o dettagliati raccolti durante il giorno negli intervalli supportati per quel tipo di dati.

Ad esempio:

Richiesta

GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints
Authorization: Bearer access-token
Accept: application/json

Risposta

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

Visualizzare una visione riconciliata dei dati sugli intervalli

Per recuperare i dati sugli intervalli senza record sovrapposti o conflitti tra più dispositivi, chiama l'endpoint reconcile. L'endpoint di riconciliazione deduplica automaticamente gli intervalli sovrapposti in più batch di sincronizzazione e più dispositivi di registrazione, restituendo un flusso autorevole e continuo adatto per il rendering delle cronologie delle attività e il calcolo delle durate.

Per informazioni di base sul motivo per cui i dispositivi connessi producono intervalli sovrapposti e un confronto operativo tra list e reconcile, consulta la Guida alla gestione dei dati.

L'esempio seguente confronta la risposta di list (che restituisce entrambi i record sovrapposti) rispetto a reconcile (che risolve il conflitto restituendo il record autorevole) per un utente con due sessioni di allenamento sovrapposte:

Elenco non elaborato

GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints
Authorization: Bearer access-token
Accept: application/json
{
  "dataPoints": [
    {
      "name": "users/111111256096816351/dataTypes/exercise/dataPoints/7797422996486764704",
      "exercise": {
        "interval": {
          "startTime": "2026-09-03T11:20:00Z",
          "endTime": "2026-09-03T11:50:00Z"
        },
        "exerciseType": "RUNNING"
      }
    },
    {
      "name": "users/111111256096816351/dataTypes/exercise/dataPoints/4389052750481144696",
      "exercise": {
        "interval": {
          "startTime": "2026-09-03T11:00:00Z",
          "endTime": "2026-09-03T11:30:00Z"
        },
        "exerciseType": "RUNNING"
      }
    }
  ]
}

Riconciliato

GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints:reconcile
Authorization: Bearer access-token
Accept: application/json
{
  "dataPoints": [
    {
      "dataPointName": "users/111111256096816351/dataTypes/exercise/dataPoints/7797422996486764704",
      "exercise": {
        "interval": {
          "startTime": "2026-09-03T11:20:00Z",
          "endTime": "2026-09-03T11:50:00Z"
        },
        "exerciseType": "RUNNING"
      }
    }
  ]
}

La riconciliazione risolve le sessioni in conflitto deduplicando e selezionando il record autorevole anziché sintetizzare un'unione temporale artificiale (ad esempio da 11:00:00Z a 11:50:00Z). La risposta riconciliata restituisce il punto dati vincente (7797422996486764704) con l'intervallo registrato originale (da 11:20:00Z a 11:50:00Z), preservando l'integrità della telemetria e delle metriche misurate della sessione.

Filtra dati

Per recuperare sottoinsiemi specifici di record di punti dati che corrispondono a criteri come un intervallo di tempo, una data o un'ora di osservazione, utilizza l'endpoint list o reconcile con un parametro filter.

Per linee guida dettagliate, regole di formattazione, errori di convalida ed esempi di query, consulta la Guida al filtro dei dati.

Filtrare per famiglia di origini dati

Per isolare o aggregare i dati di tipi specifici di origini (ad esempio, dispositivi indossabili fisici rispetto alle voci manuali), utilizza il parametro dataSourceFamily.

Per linee guida dettagliate, famiglie supportate ed esempi di richieste e risposte per reconcile, rollUp e dailyRollUp, consulta Filtrare per famiglia di origini dati nella guida Filtrare i dati.

Filtra i dati in base all'ora di inizio civile di un intervallo

Utilizza l'endpoint list con un parametro filter per filtrare i dati in base all'ora civile o a un intervallo.

Ad esempio:

Richiesta

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

Risposta

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

Filtrare i dati in base all'ora fisica di un'osservazione di esempio

Utilizza l'endpoint list con un parametro filter per filtrare i dati in base all'ora fisica di osservazione del campione.

Ad esempio:

Richiesta

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

Risposta

{
  "dataPoints": [
    {
      "name": "users/123456789/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": ""
}

Filtrare e aggregare per famiglia di origini dati

Una famiglia di origini dati è un raggruppamento logico di origini dati (come smartwatch, app mobile o voci manuali). Consente di isolare o aggregare i dati di tipi specifici di fonti (ad esempio, dispositivi indossabili fisici rispetto alle voci manuali).

Gli endpoint reconcile, rollUp e dailyRollUp supportano tutti il parametro dataSourceFamily. Il meccanismo di trasmissione dipende dall'endpoint:

Endpoint (metodo HTTP) Meccanismo
reconcile (GET) Trasmetti dataSourceFamily come parametro di query dell'URL.
rollUp (POST) Passa dataSourceFamily come campo nel corpo della richiesta JSON.
dailyRollUp (POST) Passa dataSourceFamily come campo nel corpo della richiesta JSON.

Famiglie di origini dati supportate

La tabella seguente descrive i valori dataSourceFamily supportati:

Opzione Descrizione
users/me/dataSourceFamilies/all-sources Valore predefinito. Restituisce i punti dati riconciliati in tutte le origini dati proprietari (1P) e di terze parti (3P) registrate. Con questa opzione verranno restituiti i dati delle app di terze parti (ad esempio passi dello smartwatch + passi dell'app di terze parti + passi del cellulare + passi manuali).
users/me/dataSourceFamilies/google-wearables Include i dati registrati dai dispositivi di monitoraggio Google e Fitbit (come i tracker indossabili Fitbit e Pixel Watch). Esclude i dati registrati manualmente e i dati stimati dallo smartphone. Utilizza questa opzione quando l'integrazione richiede la telemetria dei sensori non elaborata registrata direttamente dall'hardware indossabile.
users/me/dataSourceFamilies/google-sources Include origini Google e Fitbit proprietarie. Sono inclusi i record dei dispositivi di monitoraggio dell'attività fisica, i dati di Health Connect e le voci manuali registrate tramite app proprietarie (come l'app Fitbit o Google Fit).

Per ottenere uno stream di dati riconciliati da una famiglia di origini dati specifica, chiama l'endpoint reconcile con il parametro di query dataSourceFamily.

Ad esempio, la seguente richiesta GET recupera il sonno registrato dal tracker per il giorno successivo al 3 marzo 2026:

Richiesta

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

Risposta

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

Per aggregare i punti dati in base a una dimensione della finestra specifica limitata a una particolare famiglia di origini dati, chiama l'endpoint rollUp e passa il campo dataSourceFamily nel corpo della richiesta JSON.

La seguente richiesta POST esegue query sul conteggio dei passi a piedi infragiornalieri a intervalli orari (3600s), aggregati esclusivamente da dispositivi indossabili:

Richiesta

POST https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints:rollUp
Authorization: Bearer access-token
Accept: application/json

{
  "range": {
    "startTime": "2026-07-29T00:00:00Z",
    "endTime": "2026-07-29T23:59:59Z"
  },
  "windowSize": "3600s",
  "dataSourceFamily": "users/me/dataSourceFamilies/google-wearables"
}

Risposta

{
  "rollupDataPoints": [
    {
      "startTime": "2026-07-29T08:00:00Z",
      "endTime": "2026-07-29T09:00:00Z",
      "steps": {
        "countSum": "1200"
      }
    },
    {
      "startTime": "2026-07-29T09:00:00Z",
      "endTime": "2026-07-29T10:00:00Z",
      "steps": {
        "countSum": "3450"
      }
    }
  ]
}

Per aggregare i punti dati giornalieri per una famiglia di origini specifica, chiama l'endpoint dailyRollUp e passa il campo dataSourceFamily nel corpo della richiesta.

Ad esempio, la seguente richiesta calcola i rollup giornalieri per i passi dell'utente, incluse tutte le fonti Google e Fitbit proprietarie (wearable + inserimenti manuali):

Richiesta

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": 7,
        "day": 28
      },
      "time": {
        "hours": 0,
        "minutes": 0,
        "seconds": 0,
        "nanos": 0
      }
    },
    "end": {
      "date": {
        "year": 2026,
        "month": 7,
        "day": 30
      },
      "time": {
        "hours": 0,
        "minutes": 0,
        "seconds": 0,
        "nanos": 0
      }
    }
  },
  "windowSizeDays": 1,
  "dataSourceFamily": "users/me/dataSourceFamilies/google-sources"
}

Risposta

{
  "rollupDataPoints": [
    {
      "civilStartTime": {
        "date": {
          "year": 2026,
          "month": 7,
          "day": 28
        },
        "time": {}
      },
      "civilEndTime": {
        "date": {
          "year": 2026,
          "month": 7,
          "day": 28
        },
        "time": {
          "hours": 23,
          "minutes": 59,
          "seconds": 59
        }
      },
      "steps": {
        "countSum": "8430"
      }
    },
    {
      "civilStartTime": {
        "date": {
          "year": 2026,
          "month": 7,
          "day": 29
        },
        "time": {}
      },
      "civilEndTime": {
        "date": {
          "year": 2026,
          "month": 7,
          "day": 29
        },
        "time": {
          "hours": 23,
          "minutes": 59,
          "seconds": 59
        }
      },
      "steps": {
        "countSum": "11245"
      }
    }
  ]
}

Aggrega i punti dati in un intervallo di tempo

Utilizza l'endpoint rollUpper restituire l'aggregazione dei punti dati in base a una finestra in secondi, nell'intervallo datetime in base all'ora fisica degli utenti (in UTC).

Quando chiami l'endpoint rollUp, fornisci il corpo della richiesta che rappresenta l'intervallo di tempo richiesto e windowSize. Tieni presente i seguenti requisiti per windowSize:

  • Dimensione minima della finestra: la durata di windowSize deve essere di almeno 1 secondo ("1s"). Le durate inferiori a un secondo, pari a zero o negative verranno rifiutate con un 400 Bad Request (INVALID_ROLLUP_WINDOW).
  • Allineamento della risoluzione di archiviazione: per evitare una distribuzione non uniforme dei dati aggregati nei sottosegmenti, scegli un windowSize uguale o superiore alla risoluzione di archiviazione sottostante del tipo di dati (ad esempio "60s" per intervalli di un minuto). Per maggiori dettagli, vedi Dimensioni della finestra di rollup e risoluzione dello spazio di archiviazione sottostante.

Ad esempio, per raggruppare i conteggi dei passi a intervalli di 1 minuto (60s):

Richiesta

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": "60s"
}

Risposta

{
  "rollupDataPoints": [
    {
      "startTime": "2026-02-17T17:55:00Z",
      "endTime": "2026-02-17T17:56:00Z",
      "steps": {
        "countSum": "72"
      }
    },
    {
      "startTime": "2026-02-17T17:54:00Z",
      "endTime": "2026-02-17T17:55:00Z",
      "steps": {
        "countSum": "85"
      }
    },
...
  ]
}

Aggrega i dati per un singolo giorno o più giorni

L'endpoint dailyRollUp deve essere utilizzato quando vuoi aggregare i dati in un singolo giorno o in più giorni, noto come windowSize. Fornisci l'intervallo di tempo civile chiuso-aperto per l'intervallo richiesto nel corpo della richiesta. A seconda del tipo di dati, riceverai la somma o la media nell'intervallo.

Ad esempio:

Richiesta

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
}

Risposta

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

Bucket quando l'intervallo non è un multiplo della dimensione della finestra

Se l'intervallo richiesto non è un multiplo esatto di windowSize (o windowSizeDays), l'ultimo bucket in ordine cronologico verrà troncato all'endpoint superiore dell'intervallo e coprirà una durata inferiore alla dimensione della finestra. L'API accetta la tua richiesta senza modifiche e non esegue arrotondamenti, spostamenti temporali o interpolazioni dei dati.

Per coprire l'intero intervallo richiesto, l'API utilizza la divisione per eccesso per calcolare il numero totale di finestre di aggregazione:

Number of windows = ceiling(Range duration / Window size)

Ogni bucket inizia in sequenza dall'inizio dell'intervallo. Se l'aggiunta di un'altra finestra a grandezza naturale si estende oltre l'ora di fine richiesta, l'ultima finestra viene troncata (bloccata) all'ora di fine dell'intervallo.

Come funziona la suddivisione in bucket

Quando richiedi i rollup con intervalli non divisibili, l'API applica le seguenti regole:

  • Il raggruppamento inizia all'inizio dell'intervallo richiesto (range.startTime o range.start) e procede in avanti in base alla dimensione della finestra (windowSize o windowSizeDays).
  • L'ultimo bucket cronologico viene bloccato alla fine dell'intervallo richiesto (range.endTime o range.end), il che significa che copre una durata inferiore rispetto alla dimensione della finestra richiesta.
  • Gli oggetti RollupDataPoint o DailyRollupDataPoint restituiti specificano in modo esplicito i propri timestamp di inizio e fine, che puoi utilizzare per esaminare la durata effettiva del bucket troncato.
  • Poiché l'API restituisce i dati di rollup in ordine cronologico inverso (i più recenti per primi), l'ultimo bucket cronologico (quello troncato) viene visualizzato come primo elemento (index 0) nell'elenco restituito.

Scenario: autonomia di 12 minuti con una finestra di 5 minuti

Supponiamo che un client richieda un rollup in un intervallo di 12 minuti con un valore di 5 minuti windowSize:

  • range.startTime: 10:00:00
  • range.endTime: 10:12:00 (durata totale: 12 minuti)
  • windowSize: 5 minutes

Poiché 12 minuti non è un multiplo di 5 minuti (12 = 5 * 2 + 2), l'API accetta la richiesta e calcola il numero di finestre come ceiling(12 / 5) = 3.

In questo modo vengono creati i seguenti tre bucket cronologici:

  1. Bucket 1: [10:00:00, 10:05:00) - Durata: 5 minuti (intera finestra)
  2. Bucket 2: [10:05:00, 10:10:00). Durata: 5 minuti (intera finestra)
  3. Bucket 3 (troncato): [10:10:00, 10:12:00). Durata: 2 minuti (troncato a range.endTime)

Impatto sui valori aggregati

Poiché la finestra finale ha una durata inferiore, le metriche additive (come la somma o il conteggio dei passi) saranno inferiori nel bucket troncato solo a causa della durata più breve del monitoraggio.

Se un utente cammina a un ritmo costante di 100 passi al minuto durante l'intero intervallo di 12 minuti:

  • Bucket 1 (10:00-10:05): 500 passi (5 minuti × 100 passi/minuto)
  • Bucket 2 (10:05-10:10): 500 passi (5 minuti × 100 passi/minuto)
  • Bucket 3 (10:10-10:12): 200 passi (2 minuti × 100 passi/minuto)

Esempio di risposta dell'API che mostra l'ordinamento

Poiché l'API restituisce i risultati in ordine cronologico inverso, il bucket troncato viene visualizzato come primo elemento nell'elenco restituito:

{
  "rollupDataPoints": [
    {
      "startTime": "2026-08-20T10:10:00Z",
      "endTime": "2026-08-20T10:12:00Z",
      "steps": {
        "countSum": "200"
      }
    },
    {
      "startTime": "2026-08-20T10:05:00Z",
      "endTime": "2026-08-20T10:10:00Z",
      "steps": {
        "countSum": "500"
      }
    },
    {
      "startTime": "2026-08-20T10:00:00Z",
      "endTime": "2026-08-20T10:05:00Z",
      "steps": {
        "countSum": "500"
      }
    }
  ]
}

Dimensioni della finestra di rollup e risoluzione dello spazio di archiviazione sottostante

Anche se l'endpoint rollUp accetta qualsiasi windowSize di 1 secondo o più, i diversi tipi di dati registrano e mantengono le misurazioni a diverse frequenze di campionamento o durate dell'intervallo nell'archiviazione sottostante. Ad esempio, le metriche di attività fisica indossabili come steps, distance, active-minutes e active-energy-burned vengono in genere registrate a intervalli di 1 minuto (60s).

Quando aggrega i tipi di dati di intervallo, l'endpoint rollUp inserisce ogni punto dati registrato nel bucket contenente il startTime del punto dati. L'API non suddivide, interpola o distribuisce i dati degli intervalli nei bucket dei sottointervalli.

Se specifichi un windowSize inferiore all'intervallo di archiviazione dei dati sottostanti (ad esempio, se richiedi una finestra di 10 secondi per steps archiviati a intervalli di 1 minuto):

  1. Il primo sotto-bucket corrispondente all'startTime dell'intervallo (ad esempio, da 10:00:00 a 10:00:10) riceve l'intero conteggio accumulato del minuto (ad esempio, tutti i 100 passi registrati per quel minuto).
  2. I bucket secondari rimanenti all'interno dello stesso minuto (da 10:00:10 a 10:00:20, da 10:00:20 a 10:00:30 e così via) non ricevono punti dati, poiché nessun intervallo inizia all'interno di queste finestre.

Ciò comporta dati "a picchi", in cui il valore dell'intero intervallo è concentrato nella prima finestra secondaria.

Per ottenere aggregazioni distribuite in modo uniforme e significative, imposta sempre windowSize su una durata uguale o superiore alla risoluzione di archiviazione sottostante del tipo di dati di destinazione (ad esempio, 60s o superiore per steps). Per la risoluzione di archiviazione e la finestra di rollup minima consigliata per ogni tipo di dati, consulta il riferimento Tipi di dati dell'API Google Health.

Aggiornare i dati sulla salute di un utente

Utilizza l'endpoint patch per aggiornare i dati sulla salute di un utente.

L'endpoint patch aggiorna un record esistente in base all'identificatore specificato nell'URL della richiesta. Fornisci l'identificatore di un punto dati inserito in precedenza. L'API sovrascrive il record esistente.

I timestamp dell'intervallo di un punto dati (startTime e endTime) possono anche essere aggiornati dal proprietario del record o propagati da piattaforme upstream come Health Connect. Per maggiori dettagli sulla modificabilità dei timestamp, consulta la guida alla gestione dei dati. Per un esempio di aggiornamento dei timestamp degli intervalli, vedi Aggiornare i timestamp degli intervalli per i dati esistenti.

Quando utilizzare l'identificatore del punto dati

L'identificatore del punto dati è essenziale nei seguenti scenari:

  • Aggiornamenti mirati:per aggiornare una metrica specifica, fornisci il relativo identificatore nella richiesta patch.
  • Eliminazioni: la conservazione dell'identificatore consente alla tua applicazione di eliminare il record in un secondo momento utilizzando l'endpoint batchDelete.

Ecco un esempio in cui un utente aggiorna la lettura del grasso corporeo su una bilancia chiamata "HumanScale" della società "Scales R Us". La nuova lettura della percentuale di grasso corporeo dell'utente è del 20% per la data 10/03/2026:

Richiesta

PATCH https://health.googleapis.com/v4/users/me/dataTypes/body-fat/dataPoints/1234567890
Authorization: Bearer access-token
Content-Type: application/json

{
  "name": "users/me/dataTypes/body-fat/dataPoints/1234567890",
  "dataSource": {
    "recordingMethod": "ACTIVELY_MEASURED",
    "device": {
      "formFactor": "SCALE",
      "manufacturer": "Scales R Us",
      "displayName": "HumanScale"
    }
  },
  "bodyFat": {
    "sampleTime": {
      "physicalTime": "2026-03-10T10:00:00Z"
    },
    "percentage": 20
  }
}

Risposta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4main.DataPoint",
    "name": "users/123456789/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
    }
  }
}

Aggiornare i timestamp dell'intervallo per i dati esistenti

Per aggiornare startTime o endTime di un punto dati dell'intervallo esistente, invia una richiesta PATCH all'URI della risorsa del punto dati. Solo il creatore o il proprietario originale di un record può modificarne i campi. Le applicazioni non possono modificare i punti dati che non hanno creato.

Per informazioni di base sulla modificabilità dei timestamp, sugli aggiornamenti upstream di Health Connect e sulle implicazioni della memorizzazione nella cache, consulta la Guida alla gestione dei dati.

L'esempio seguente mostra un'applicazione proprietaria che aggiorna i timestamp dell'intervallo di un log di idratazione esistente utilizzando l'endpoint patch:

Richiesta

PATCH https://health.googleapis.com/v4/users/me/dataTypes/hydration-log/dataPoints/4093039283164890826
Authorization: Bearer access-token
Content-Type: application/json

{
  "hydrationLog": {
    "interval": {
      "startTime": "2026-09-03T10:05:00Z",
      "endTime": "2026-09-03T10:19:59Z"
    },
    "amountConsumed": {
      "milliliters": 350
    }
  }
}

Risposta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4.DataPoint",
    "name": "users/111111256096816351/dataTypes/hydration-log/dataPoints/4093039283164890826",
    "hydrationLog": {
      "interval": {
        "startTime": "2026-09-03T10:05:00Z",
        "endTime": "2026-09-03T10:19:59Z",
        "civilStartTime": {
          "date": {
            "year": 2026,
            "month": 9,
            "day": 3
          },
          "time": {
            "hours": 10,
            "minutes": 5
          }
        },
        "civilEndTime": {
          "date": {
            "year": 2026,
            "month": 9,
            "day": 3
          },
          "time": {
            "hours": 10,
            "minutes": 19,
            "seconds": 59
          }
        }
      },
      "amountConsumed": {
        "milliliters": 350
      }
    }
  }
}

Registrare un alimento

Per registrare un alimento, invia una richiesta POST all'endpoint nutrition-log dataPoints. Il corpo della richiesta contiene un DataPoint con un oggetto nutritionLog. Per saperne di più, consulta la guida all'alimentazione.

Ad esempio:

Richiesta

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

Risposta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4.DataPoint",
    "name": "users/123456789/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"
    }
  }
}

Eliminare i dati sanitari dell'utente

Utilizza il metodo batchDelete per eliminare un array di dati dell'app Fitbit di un utente.

Ecco un esempio in cui un utente ha registrato in precedenza la propria percentuale di grasso corporeo su una bilancia, ma vuole eliminare il record. Utilizzando user-id e data-point-id dell'azione di inserimento originale:

Richiesta

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/123456789/dataTypes/body-fat/dataPoints/1234567890"
  ]
}

Risposta

{
  "done": true,
  "response": {
    "@type": "type.googleapis.com/google.devicesandservices.health.v4main.BatchDeleteDataPointsResponse"
  }
}

Trovare le informazioni sul dispositivo

Utilizza l'endpoint list per recuperare l'elenco dei dispositivi accoppiati all'account di un utente. Sono incluse le informazioni sul modello del dispositivo (deviceVersion) e l'ultima sincronizzazione con l'app mobile Google Health (lastSyncTime).

La configurazione dell'elenco e le informazioni di sincronizzazione sono utili per risolvere i problemi di sincronizzazione o recuperare i dati storici dall'ultima sincronizzazione.

Ad esempio:

Richiesta

GET https://health.googleapis.com/v4/users/me/pairedDevices
Authorization: Bearer access-token
Accept: application/json

Risposta

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

Eseguire query sui dati storici

Uno dei vantaggi principali dell'API Google Health è la possibilità di monitorare le prestazioni di un utente e i suoi parametri vitali per lunghi periodi di tempo. Puoi eseguire query sui dati di un utente a partire dal momento in cui sono stati registrati. L'API non impone limitazioni o restrizioni alla quantità di dati storici che la tua applicazione può utilizzare.

Tuttavia, l'esecuzione di query sui dati storici è ancora regolata dai limiti di frequenza standard. Per gestire la stabilità del sistema e prevenire payload eccessivi, l'API Google Health utilizza la paginazione automatica con dimensioni di pagina specifiche per endpoint. Tieni presente i seguenti limiti e comportamenti:

  • Impaginazione automatica:se esegui una query su un intervallo di dati lungo, l'API restituirà solo la prima pagina di risultati fino al limite di dimensioni della pagina per l'endpoint, insieme a un nextPageToken. Devi utilizzare nextPageToken per richiedere le pagine successive.
  • Dimensioni delle pagine variabili:i limiti di capping dipendono dall'endpoint e dal tipo di dati. Per la maggior parte dei tipi di dati, le dimensioni delle pagine sono limitate a un massimo di 10.000. Tuttavia, per alcuni tipi di dati come exercise e sleep, la dimensione predefinita e massima della pagina è limitata a 25. Ad esempio, se un client richiede tutti i dati relativi al sonno degli ultimi 10 anni, l'API restituirà comunque solo 25 sessioni di sonno nella prima pagina.
  • Limitazioni dell'intervallo di date di rollup: per gli endpoint di rollup e aggregazione dei dati (come rollUp e dailyRollUp), gli intervalli di date delle query sono limitati in base al tipo di dati:
    • Un intervallo massimo di 14 giorni per calories-in-heart-rate-zone, heart-rate, active-minutes e total-calories.
    • Un intervallo massimo di 90 giorni per tutti gli altri tipi di dati di rollup.

A seconda del volume di dati storici di cui ha bisogno la tua applicazione, il recupero dell'intero set di dati richiederà la paginazione sequenziale delle pagine. Tienilo presente quando progetti la procedura di sincronizzazione dei dati della tua applicazione.

Per garantire un rendimento ottimale ed evitare errori dell'API, segui queste linee guida quando interroghi i dati storici:

Sincronizzazione dei dati in fasi (caricamento hot e caricamento completo)

  • Caricamento "rapido" iniziale:recupera e visualizza solo i dati più recenti (7-14 giorni) durante la sequenza di caricamento principale. In questo modo, gli utenti vedono immediatamente i dati senza dover attendere query di lunga durata.
  • Caricamento "a freddo" in background:delega il recupero dei dati storici meno recenti a una coda asincrona a priorità inferiore o a un processo in background dopo il rendering della UI principale.

Chunking delle query per l'aggregazione

  • Poiché gli endpoint di rollup e rollup giornaliero impongono un limite massimo all'intervallo di date (14 o 90 giorni a seconda del tipo di dati), devi suddividere le query di aggregazione cronologica di grandi dimensioni in intervalli sequenziali più piccoli entro questi limiti.
  • Raggruppa o sequenzia queste sottoquery in modo sicuro per rispettare i limiti di concorrenza e mantenere indicatori di avanzamento dell'interfaccia utente costanti.

Sfruttare i roll-up pre-aggregati

Ristruttura le dashboard di panoramica e i grafici delle tendenze in modo che utilizzino endpoint di riepilogo preaggregati (ad esempio DailyRollUpDataPoints). In questo modo, si ridurranno drasticamente il sovraccarico di calcolo sul backend e il tempo di trasferimento di rete al client.

Gestione degli errori resiliente (nuovi tentativi intelligenti)

  • Implementa una gestione rigorosa del backoff esponenziale quando si verificano limiti di frequenza (429 Too Many Requests) e timeout del gateway del server (504 Gateway Timeout). Non riprovare immediatamente a inviare payload di grandi dimensioni non riusciti. I tentativi immediati moltiplicano la congestione del backend e peggiorano il sistema.