Filtra dati

L'API Google Health si basa su espressioni di filtro per limitare i punti dati restituiti quando si chiamano metodi di recupero standard. In particolare, i filtri vengono utilizzati con:

Questa guida spiega come viene implementato il filtro, la sintassi e le convenzioni e contiene esempi per ogni tipo di record.

Convenzioni di filtro

L'API Google Health implementa i filtri in conformità allo standard Google API Improvement Proposals (AIP-160).

Parametri di query

I filtri vengono passati utilizzando la stringa di query dell'URL nel parametro filter. Poiché i filtri contengono caratteri speciali (come <, >= e virgolette), devono essere codificati nell'URL quando vengono trasmessi nella richiesta HTTP.

Ad esempio, una richiesta con il filtro steps.interval.civil_start_time >= "2026-03-04T00:00:00" deve essere codificata come:

GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints
  ?filter=steps.interval.civil_start_time%20%3E%3D%20%222026-03-04T00%3A00%3A00%22

Formato di denominazione

Se un tipo di dati è composto da più di una parola, il formato dell'identificatore varia tra il percorso della risorsa e il filtro:

  • Percorso dell'endpoint: utilizza i trattini (ad esempio, /dataTypes/body-fat).
  • Stringa di filtro: utilizza i trattini bassi (ad esempio, body_fat).

Se utilizzi i trattini nell'identificatore del filtro, l'API restituisce un 400 Bad Request con il motivo dell'errore INVALID_DATA_POINT_FILTER.

Tipi e campi di filtro

I campi che utilizzi in un filtro dipendono dal tipo di record del tipo di dati su cui esegui la query. La tabella seguente descrive i campi supportati per ogni tipo di record:

Tipo di record Descrizione Campi filtro supportati
Intervallo Punti dati registrati in un determinato periodo di tempo (ad esempio, steps, distance, calories). {dataType}.interval.start_time
{dataType}.interval.civil_start_time

Esempio:
steps.interval.civil_start_time
Esempio Osservazioni istantanee o misurazioni brevi (ad esempio, weight, body-fat, blood-glucose). {dataType}.sample_time.physical_time
{dataType}.sample_time.civil_time

Esempio:
body_fat.sample_time.physical_time
Ogni giorno Metriche e riepiloghi giornalieri (ad esempio, daily-heart-rate-variability). {dataType}.date

Esempio:
daily_heart_rate_variability.date
Sessione Sessioni utente estese con regole di temporizzazione specializzate. Allenamento:{dataType}.interval.civil_start_time
Sonno:sleep.interval.end_time, sleep.interval.civil_end_time
ECG:electrocardiogram.interval.start_time

Esempio:
sleep.interval.civil_end_time

Operatori e regole di formattazione supportati

Le espressioni di filtro devono rispettare le seguenti regole di formattazione:

Operatori di confronto

Sono supportati solo due operatori di confronto:

Operatore Descrizione
>= Limite inferiore (incluso).
< Limite superiore (esclusivo).

L'utilizzo di altri operatori di confronto (ad esempio >, <= o =) restituisce un 400 Bad Request con INVALID_DATA_POINT_FILTER_RESTRICTION_COMPARATOR.

Operatori logici

Operatore Assistenza
AND Operatore predefinito e unico supportato. Utilizzato per combinare i limiti di inizio e fine.
OR Non supportati. L'utilizzo di OR restituisce un 400 Bad Request con il motivo dell'errore INVALID_DATA_POINT_FILTER_EXPRESSION_STRUCTURE ("The filter must be a conjunction or sequence of restrictions. Trovato: DISJUNCTION").

Valori letterali ora

I valori letterali di tempo nelle espressioni di filtro devono utilizzare questi formati:

Tipo di ora Requisiti Esempi
Tempo fisico Formato RFC 3339, che termina con Z o un offset UTC. Rappresenta eventi reali in formato UTC. Corretto: "2026-03-01T00:00:00Z", "2026-03-01T00:00:00-08:00"
Errato: "2026-03-01"
Ora civile Formato ISO 8601: YYYY-MM-DD[THH:mm:ss]. Rappresenta l'ora sull'orologio di un utente, indipendentemente dalla posizione o dagli offset del fuso orario. Corretto: "2026-03-01", "2026-03-01T08:30:00"

Filtra regole di convalida

I filtri seguono queste regole:

Regola Descrizione Esempi
Nessun tipo di ora mista Non combinare i limiti di tempo fisici e civili. Non valido: steps.interval.start_time >= "2026-03-01T00:00:00Z" AND steps.interval.civil_start_time < "2026-03-02"
Errore: INVALID_DATA_POINT_FILTER_MIXED_TIME_RESTRICTIONS ("Il filtro non può contenere intervalli di tempo fisici e civili")
Nessun tipo di dati misto Utilizza i campi appartenenti al tipo di dati nel percorso della richiesta. Non valido: percorso /users/.../dataTypes/steps/... con filtro distance.interval.start_time >= "..."
Errore: INVALID_DATA_POINT_FILTER_COLLECTION_MISMATCH ("Il tipo di dati nel filtro non corrisponde alla raccolta di tipi di dati padre")
Logica dell'ordine cronologico Il limite superiore deve essere maggiore del limite inferiore. Non valido: steps.interval.start_time >= "2026-03-02T00:00:00Z" AND steps.interval.start_time < "2026-03-01T00:00:00Z"
Errore: INVALID_TIME_RANGE ("L'ora di fine della query deve essere strettamente maggiore dell'ora di inizio")
Formato della cassa Utilizza la notazione snake case corrispondente al nome del tipo di dati. Non valido: body-fat.sample_time.physical_time >= "..."
Errore: INVALID_DATA_POINT_FILTER ("Filtro non valido")

L'API restituisce HTTP 400 Bad Request per i filtri non validi. Controlla error.details[].metadata.detailedReasons per il codice del motivo dell'errore.

Ambiti OAuth obbligatori

Per eseguire query sui punti dati utilizzando i filtri, l'utente autorizzato deve concedere l'ambito OAuth pertinente per quel tipo di dati. Se l'ambito richiesto non è presente, l'API restituisce lo stato 403 Forbidden con MISSING_OAUTH_SCOPE.

La tabella seguente mappa gli ambiti OAuth ai tipi di dati a cui concedono l'accesso in lettura. La tabella mostra gli ambiti nel formato relativo (ad esempio, .activity_and_fitness.readonly rappresenta https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly):

Ambito OAuth richiesto Tipi di dati
.activity_and_fitness.readonly active-energy-burned, active-minutes, active-zone-minutes, activity-level, altitude, calories-in-heart-rate-zone, daily-vo2-max, distance, exercise, floors, run-vo2-max, sedentary-period, steps, swim-lengths-data, time-in-heart-rate-zone, total-calories, vo2-max
.ecg.readonly elettrocardiogramma
.health_metrics_and_measurements.readonly glicemia, grasso corporeo, temperatura corporea interna, variabilità del battito cardiaco giornaliera, zone del battito cardiaco giornaliere, saturazione di ossigeno giornaliera, frequenza respiratoria giornaliera, battito cardiaco a riposo giornaliero, derivazioni della temperatura del sonno giornaliera, battito cardiaco, variabilità del battito cardiaco, altezza, saturazione di ossigeno, riepilogo della frequenza respiratoria nel sonno, sensori di temperatura cutanea, peso
.irn.readonly notifica-di-ritmo-irregolare
.nutrition.readonly alimenti, unità-di-misura-alimenti, diario-idratazione, diario-alimentare
.sleep.readonly sonno

Se al tuo client viene concesso solo un ambito di scrittura (ad esempio .activity_and_fitness.writeonly) per un tipo di dati richiesto, puoi comunque interrogare i punti dati scritti dal tuo client. In questo caso, le richieste sono implicitamente limitate alla famiglia di origini dati self-sources. Per dettagli e limitazioni sui tipi di dati, vedi Filtrare per famiglia di origini dati.

Casi d'uso ed esempi

I seguenti esempi mostrano come creare filtri per scenari comuni:

Passaggi della query per intervallo di tempo fisico

Passi della query registrati tra 2026-03-01T00:00:00Z (incluso) e 2026-03-02T00:00:00Z (escluso):

GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints
  ?filter=steps.interval.start_time >= "2026-03-01T00:00:00Z"
  AND steps.interval.start_time < "2026-03-02T00:00:00Z"

Esegui query sui passaggi in base all'intervallo di tempo civile

Passaggi della query per un'intera giornata del 4 marzo 2026, rispetto all'orologio locale dell'utente:

GET https://health.googleapis.com/v4/users/me/dataTypes/steps/dataPoints
  ?filter=steps.interval.civil_start_time >= "2026-03-04"
  AND steps.interval.civil_start_time < "2026-03-05"

Eseguire query sul grasso corporeo in base all'ora del campione fisico

Esegui una query sulle misurazioni del grasso corporeo registrate a partire da marzo 2026 (in UTC):

GET https://health.googleapis.com/v4/users/me/dataTypes/body-fat/dataPoints
  ?filter=body_fat.sample_time.physical_time >= "2026-03-01T00:00:00Z"

Peso della query in base all'ora di campionamento civile

Log del peso delle query registrati dopo un'ora locale specifica:

GET https://health.googleapis.com/v4/users/me/dataTypes/weight/dataPoints
  ?filter=weight.sample_time.civil_time >= "2026-03-01T08:00:00"

Query sui riepiloghi giornalieri della variabilità del battito cardiaco

Esegui una query sui riepiloghi giornalieri della variabilità del battito cardiaco (HRV) registrati prima di una data specifica:

GET https://health.googleapis.com/v4/users/me/dataTypes/daily-heart-rate-variability/dataPoints
  ?filter=daily_heart_rate_variability.date < "2026-08-15"

Eseguire query sulle sessioni di allenamento in base all'ora di inizio civile

Esegui query sulle sessioni di allenamento che si sono svolte durante una settimana specifica nel fuso orario locale dell'utente:

GET https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints
  ?filter=exercise.interval.civil_start_time >= "2026-03-01"
  AND exercise.interval.civil_start_time < "2026-03-08"

Esegui query sulle sessioni di sonno in base all'ora di fine civile

Esegui query sui record del sonno in base all'ora di fine della sessione:

GET https://health.googleapis.com/v4/users/me/dataTypes/sleep/dataPoints
  ?filter=sleep.interval.civil_end_time >= "2026-03-04T05:00:00"
  AND sleep.interval.civil_end_time < "2026-03-04T12:00:00"

Eseguire query sugli elettrocardiogrammi in base all'ora di inizio

Esegui query sulle registrazioni ECG a partire da un punto nel tempo UTC fisico. Tieni presente che le query ECG supportano solo un confronto >= su start_time:

GET https://health.googleapis.com/v4/users/me/dataTypes/electrocardiogram/dataPoints
  ?filter=electrocardiogram.interval.start_time >= "2026-03-10T12:00:00Z"

Filtrare per famiglia di origini dati

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

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

Endpoint (metodo HTTP) Meccanismo
list (GET) Trasmetti dataSourceFamily come parametro di query dell'URL.
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 (quando viene concesso un ambito di lettura). Include punti dati di tutte le origini dati proprietarie (1P) e di terze parti (3P) disponibili. Con questa opzione vengono 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). Sono esclusi 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 fonti proprietarie di Google e Fitbit. Sono inclusi i record dei dispositivi tracker fisici, i dati di Health Connect e le voci manuali registrate tramite app proprietarie (come l'app Fitbit o Google Fit).
users/me/dataSourceFamilies/self-sources Include solo i dati scritti dal client chiamante tramite l'API Google Health (punti dati la cui origine dati è stata registrata tramite l'API con lo stesso ID client OAuth del chiamante).

Se nessun punto dati corrisponde alla famiglia di origini dati richiesta, la risposta è un elenco vuoto anziché un errore.

Ambiti di sola scrittura e origini proprie

I chiamanti a cui vengono concessi solo ambiti di scrittura (ad esempio .activity_and_fitness.writeonly) per i tipi di dati richiesti possono leggere i dati che hanno scritto personalmente e solo questi.

  • Le richieste senza un parametro dataSourceFamily esplicito o con dataSourceFamily impostato su users/me/dataSourceFamilies/self-sources sono implicitamente limitate a self-sources.
  • La richiesta di qualsiasi altra famiglia di origini dati (ad esempio all-sources, google-wearables o google-sources) con solo un ambito di scrittura non va a buon fine e restituisce un errore 403 Forbidden (PERMISSION_DENIED).

Limitazioni del tipo di dati sull'endpoint di elenco

Nell'endpoint list (users.dataTypes.dataPoints.list), il filtro per dataSourceFamily non è supportato per i tipi di dati sleep, food e food-measurement-unit:

  • L'impostazione esplicita di dataSourceFamily su list per sleep, food o food-measurement-unit non riesce e viene visualizzato un errore 400 Bad Request (INVALID_ARGUMENT).
  • La chiamata di list per questi tipi di dati quando viene concesso solo un ambito di scrittura (in cui la limitazione a self-sources è implicita negli ambiti del chiamante) non va a buon fine e viene visualizzato un errore 403 Forbidden (PERMISSION_DENIED).
  • Per filtrare i punti dati sleep in base a dataSourceFamily, utilizza l'endpoint reconcile.

Esempi di famiglie di origini dati

Per elencare i punti dati non elaborati che il tuo client ha scritto per un utente, chiama l'endpoint list con il parametro di query dataSourceFamily impostato su users/me/dataSourceFamilies/self-sources.

Ad esempio, la seguente richiesta GET elenca le misurazioni body-fat non elaborate scritte dal client chiamante a partire dal 1° marzo 2026:

Richiesta

GET https://health.googleapis.com/v4/users/me/dataTypes/body-fat/dataPoints
  ?dataSourceFamily=users/me/dataSourceFamilies/self-sources
  &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": ""
}

Per ottenere uno stream di dati riconciliato 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 trasmetti il campo dataSourceFamily nel corpo della richiesta JSON.

La seguente richiesta POST esegue query sui conteggi 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 (dispositivi indossabili + 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"
      }
    }
  ]
}