Memfilter data

Google Health API mengandalkan ekspresi filter untuk membatasi titik data yang ditampilkan saat memanggil metode pengambilan standar. Secara khusus, filter digunakan dengan:

  • Endpoint list: mengkueri titik data mentah.
  • Endpoint reconcile: membuat kueri titik data streaming yang direkonsiliasi.

Panduan ini menjelaskan cara penerapan pemfilteran, sintaksis dan konvensi, serta memiliki contoh untuk setiap jenis rekaman.

Konvensi filter

Google Health API menerapkan filter yang mengikuti standar Google API Improvement Proposals (AIP-160).

Parameter kueri

Filter diteruskan menggunakan string kueri URL dalam parameter filter. Karena filter berisi karakter khusus (seperti <, >=, dan tanda petik), filter tersebut harus dienkode URL saat dikirim dalam permintaan HTTP.

Misalnya, permintaan dengan filter steps.interval.civil_start_time >= "2026-03-04T00:00:00" harus dienkode sebagai:

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

Format penamaan

Jika jenis data memiliki lebih dari satu kata, format ID berbeda antara jalur resource dan filter:

  • Jalur endpoint: gunakan tanda hubung (misalnya, /dataTypes/body-fat).
  • String filter: gunakan garis bawah (misalnya, body_fat).

Jika Anda menggunakan tanda hubung dalam ID filter, API akan menampilkan 400 Bad Request dengan alasan error INVALID_DATA_POINT_FILTER.

Jenis dan kolom filter

Kolom yang Anda gunakan dalam filter bergantung pada jenis rekaman jenis data yang Anda kueri. Tabel berikut menjelaskan kolom yang didukung untuk setiap jenis catatan:

Jenis data Deskripsi Kolom filter yang didukung
Interval Titik data yang dicatat selama jangka waktu tertentu (misalnya, steps, distance, calories). {dataType}.interval.start_time
{dataType}.interval.civil_start_time

Contoh:
steps.interval.civil_start_time
Sampel Pengamatan instan atau pengukuran singkat (misalnya, weight, body-fat, blood-glucose). {dataType}.sample_time.physical_time
{dataType}.sample_time.civil_time

Contoh:
body_fat.sample_time.physical_time
Setiap hari Metrik dan ringkasan harian (misalnya, daily-heart-rate-variability). {dataType}.date

Contoh:
daily_heart_rate_variability.date
Sesi Sesi pengguna yang diperpanjang dengan aturan pengaturan waktu khusus. Latihan: {dataType}.interval.civil_start_time
Tidur: sleep.interval.end_time, sleep.interval.civil_end_time
EKG: electrocardiogram.interval.start_time

Contoh:
sleep.interval.civil_end_time

Operator dan aturan format yang didukung

Ekspresi filter harus mematuhi aturan pemformatan berikut:

Operator perbandingan

Hanya dua operator perbandingan yang didukung:

Operator Deskripsi
>= Batas bawah (inklusif).
< Batas atas (eksklusif).

Menggunakan operator perbandingan lainnya (seperti >, <=, atau =) akan menampilkan 400 Bad Request dengan INVALID_DATA_POINT_FILTER_RESTRICTION_COMPARATOR.

Operator logika

Operator Dukungan
AND Operator default dan hanya didukung. Digunakan untuk menggabungkan batas awal dan akhir.
OR Tidak didukung. Penggunaan OR akan menampilkan 400 Bad Request dengan alasan error INVALID_DATA_POINT_FILTER_EXPRESSION_STRUCTURE ("Filter harus berupa gabungan atau urutan pembatasan. Ditemukan: DISJUNCTION").

Literal waktu

Literal waktu dalam ekspresi filter harus menggunakan format berikut:

Jenis waktu Persyaratan Contoh
Waktu fisik Format RFC 3339, yang diakhiri dengan Z atau offset UTC. Mewakili peristiwa dunia nyata dalam UTC. Benar: "2026-03-01T00:00:00Z", "2026-03-01T00:00:00-08:00"
Salah: "2026-03-01"
Waktu sipil Format ISO 8601: YYYY-MM-DD[THH:mm:ss]. Mewakili waktu pada jam pengguna, terlepas dari lokasi atau selisih zona waktu. Benar: "2026-03-01", "2026-03-01T08:30:00"

Aturan validasi filter

Filter mengikuti aturan berikut:

Aturan Deskripsi Contoh
Tidak ada jenis waktu campuran Jangan mencampur batas waktu fisik dan waktu sipil. Tidak valid: steps.interval.start_time >= "2026-03-01T00:00:00Z" AND steps.interval.civil_start_time < "2026-03-02"
Error: INVALID_DATA_POINT_FILTER_MIXED_TIME_RESTRICTIONS ("Filter tidak boleh berisi rentang waktu fisik dan waktu sipil")
Tidak ada jenis data campuran Gunakan kolom yang termasuk dalam jenis data di jalur permintaan. Tidak valid: Jalur /users/.../dataTypes/steps/... dengan filter distance.interval.start_time >= "..."
Error: INVALID_DATA_POINT_FILTER_COLLECTION_MISMATCH ("Jenis data dalam filter tidak cocok dengan koleksi jenis data induk")
Logika urutan waktu Batas atas harus lebih besar dari batas bawah. Tidak valid: steps.interval.start_time >= "2026-03-02T00:00:00Z" AND steps.interval.start_time < "2026-03-01T00:00:00Z"
Error: INVALID_TIME_RANGE ("Waktu berakhir kueri harus lebih besar daripada waktu mulai")
Format kasus Gunakan snake case yang cocok dengan nama jenis data. Tidak valid: body-fat.sample_time.physical_time >= "..."
Error: INVALID_DATA_POINT_FILTER ("Filter tidak valid")

API menampilkan HTTP 400 Bad Request untuk filter yang tidak valid. Periksa error.details[].metadata.detailedReasons untuk mengetahui kode alasan error.

Cakupan OAuth yang diperlukan

Untuk membuat kueri titik data menggunakan filter, pengguna yang diberi otorisasi harus memberikan cakupan OAuth yang relevan untuk jenis data tersebut. Jika cakupan yang diperlukan tidak ada, API akan menampilkan status 403 Forbidden dengan MISSING_OAUTH_SCOPE.

Tabel berikut memetakan cakupan OAuth ke jenis data yang diberikan akses baca kepadanya. Tabel menampilkan cakupan dalam format relatifnya (misalnya, .activity_and_fitness.readonly mewakili https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly):

Cakupan OAuth yang diperlukan Jenis data
.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 elektrokardiogram
.health_metrics_and_measurements.readonly glukosa darah, lemak tubuh, suhu inti tubuh, variabilitas detak jantung harian, zona detak jantung harian, saturasi oksigen harian, laju pernapasan harian, detak jantung istirahat harian, turunan suhu tidur harian, detak jantung, variabilitas detak jantung, tinggi badan, saturasi oksigen, ringkasan tidur laju pernapasan, sensor suhu kulit, berat badan
.irn.readonly notifikasi-irama-tidak-teratur
.nutrition.readonly makanan, satuan-pengukuran-makanan, catatan-hidrasi, catatan-nutrisi
.sleep.readonly sleep

Jika klien Anda hanya diberi cakupan tulis (seperti .activity_and_fitness.writeonly) untuk jenis data yang diminta, Anda tetap dapat mengirimkan kueri titik data yang ditulis oleh klien Anda sendiri. Dalam hal ini, permintaan secara implisit dibatasi untuk family sumber data self-sources. Untuk mengetahui detail dan batasan jenis data, lihat Memfilter menurut famili sumber data.

Kasus penggunaan dan contoh

Contoh berikut menunjukkan cara membuat filter untuk skenario umum:

Mengkueri langkah-langkah menurut rentang waktu fisik

Langkah kueri yang direkam antara 2026-03-01T00:00:00Z (inklusif) dan 2026-03-02T00:00:00Z (eksklusif):

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"

Mengkueri langkah-langkah menurut rentang waktu sipil

Langkah-langkah kueri untuk sepanjang hari pada 4 Maret 2026, relatif terhadap waktu lokal pengguna:

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"

Mengueri lemak tubuh berdasarkan waktu pengambilan sampel fisik

Kueri pengukuran lemak tubuh yang direkam mulai Maret 2026 (dalam 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"

Bobot kueri menurut waktu sampel sipil

Log bobot kueri dicatat setelah waktu setempat tertentu:

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

Kueri ringkasan harian variabilitas detak jantung

Kueri ringkasan harian variabilitas detak jantung (HRV) yang direkam sebelum tanggal tertentu:

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

Mengueri sesi latihan menurut waktu mulai sipil

Kueri sesi latihan yang terjadi selama minggu tertentu di zona waktu lokal pengguna:

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"

Mengkueri sesi tidur menurut waktu berakhir kalender

Kueri catatan tidur berdasarkan waktu berakhir sesi:

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"

Membuat kueri elektrokardiogram menurut waktu mulai

Membuat kueri rekaman EKG yang dimulai dari titik waktu UTC fisik. Perhatikan bahwa kueri EKG hanya mendukung perbandingan >= pada start_time:

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

Memfilter menurut grup sumber data

Grup sumber data adalah pengelompokan logis sumber data (seperti smartwatch, aplikasi seluler, atau entri manual). Hal ini memungkinkan Anda mengisolasi atau menggabungkan data dari jenis sumber tertentu (misalnya, perangkat wearable fisik, entri manual, atau data yang ditulis oleh klien Anda sendiri).

Semua endpoint list, reconcile, rollUp, dan dailyRollUp mendukung parameter dataSourceFamily. Mekanisme penerusan bergantung pada endpoint:

Endpoint (metode HTTP) Mekanisme
list (GET) Teruskan dataSourceFamily sebagai parameter kueri URL.
reconcile (GET) Teruskan dataSourceFamily sebagai parameter kueri URL.
rollUp (POST) Teruskan dataSourceFamily sebagai kolom di isi permintaan JSON.
dailyRollUp (POST) Teruskan dataSourceFamily sebagai kolom di isi permintaan JSON.

Grup sumber data yang didukung

Tabel berikut menjelaskan nilai dataSourceFamily yang didukung:

Opsi Deskripsi
users/me/dataSourceFamilies/all-sources Nilai default (saat diberi cakupan baca). Mencakup titik data dari semua sumber data pihak pertama (1P) dan pihak ketiga (3P) yang tersedia. Data aplikasi pihak ketiga ditampilkan dengan opsi ini (seperti langkah smartwatch + langkah aplikasi pihak ketiga + langkah ponsel + langkah manual).
users/me/dataSourceFamilies/google-wearables Mencakup data yang direkam oleh perangkat pelacak Google dan Fitbit (seperti pelacak wearable Fitbit dan Pixel Watch). Mengecualikan data yang dicatat secara manual dan data yang diperkirakan oleh ponsel. Gunakan opsi ini saat integrasi Anda memerlukan telemetri sensor mentah yang direkam langsung oleh hardware perangkat wearable.
users/me/dataSourceFamilies/google-sources Mencakup sumber pihak pertama Google dan Fitbit. Data ini mencakup catatan perangkat pelacak fisik, data dari Health Connect, dan entri manual yang dicatat melalui aplikasi pihak pertama (seperti aplikasi Fitbit atau Google Fit).
users/me/dataSourceFamilies/self-sources Hanya menyertakan data yang ditulis oleh klien panggilan melalui Google Health API (titik data yang sumber datanya didaftarkan melalui API dengan ID klien OAuth yang sama dengan pemanggil).

Jika tidak ada titik data yang cocok dengan family sumber data yang diminta, responsnya adalah daftar kosong, bukan error.

Cakupan hanya tulis dan sumber mandiri

Pemanggil yang hanya diberi cakupan tulis (seperti .activity_and_fitness.writeonly) untuk jenis data yang diminta dapat membaca data yang mereka tulis sendiri, dan hanya data tersebut.

  • Permintaan tanpa parameter dataSourceFamily eksplisit, atau dengan dataSourceFamily yang ditetapkan ke users/me/dataSourceFamilies/self-sources, akan dibatasi secara implisit ke self-sources.
  • Meminta kelompok sumber data lainnya (seperti all-sources, google-wearables, atau google-sources) hanya dengan cakupan tulis akan gagal dengan error 403 Forbidden (PERMISSION_DENIED).

Batasan jenis data pada endpoint daftar

Di endpoint list (users.dataTypes.dataPoints.list), pemfilteran menurut dataSourceFamily tidak didukung untuk jenis data sleep, food, dan food-measurement-unit:

  • Menetapkan dataSourceFamily secara eksplisit pada list untuk sleep, food, atau food-measurement-unit akan gagal dengan error 400 Bad Request (INVALID_ARGUMENT).
  • Memanggil list untuk jenis data ini saat hanya diberi cakupan tulis (dengan pembatasan ke self-sources tersirat oleh cakupan pemanggil) akan gagal dengan error 403 Forbidden (PERMISSION_DENIED).
  • Untuk memfilter titik data sleep menurut dataSourceFamily, gunakan endpoint reconcile.

Contoh grup sumber data

Untuk mencantumkan titik data mentah yang ditulis klien Anda sendiri untuk pengguna, panggil endpoint list dengan parameter kueri dataSourceFamily yang ditetapkan ke users/me/dataSourceFamilies/self-sources.

Misalnya, permintaan GET berikut mencantumkan pengukuran body-fat mentah yang ditulis oleh klien yang memanggil, dimulai pada 01-03-2026:

Permintaan

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

Respons

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

Untuk mendapatkan aliran data yang disesuaikan dari family sumber data tertentu, panggil endpoint reconcile dengan parameter kueri dataSourceFamily.

Misalnya, permintaan GET berikut mengambil data tidur yang direkam oleh pelacak untuk hari setelah 03-03-2026:

Permintaan

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

Respons

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

Untuk menggabungkan titik data selama ukuran periode tertentu yang dibatasi untuk keluarga sumber data tertentu, panggil endpoint rollUp dan teruskan kolom dataSourceFamily dalam isi permintaan JSON.

Permintaan POST berikut mengkueri jumlah langkah kaki intrahari dalam interval per jam (3600s), yang dikumpulkan secara eksklusif dari perangkat wearable:

Permintaan

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

Respons

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

Untuk menggabungkan titik data harian untuk keluarga sumber tertentu, panggil endpoint dailyRollUp dan teruskan kolom dataSourceFamily di isi permintaan.

Misalnya, permintaan berikut menghitung ringkasan harian untuk langkah-langkah pengguna, termasuk semua sumber Google dan Fitbit pihak pertama (perangkat wearable + entri manual):

Permintaan

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

Tanggapan

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