Введите фильтр

Google Health API использует выражения фильтрации, чтобы ограничивать количество возвращаемых точек данных при вызове стандартных методов получения. В частности, фильтры используются:

В этом руководстве рассказывается, как реализована фильтрация, какой у нее синтаксис и какие соглашения используются, а также приведены примеры для каждого типа записи.

Правила фильтрации

В Google Health API фильтры реализованы в соответствии со стандартом Google API Improvement Proposals (AIP-160).

Параметры запроса

Фильтры передаются с помощью строки запроса URL в параметре filter. Поскольку фильтры содержат специальные символы (например, <, >= и кавычки), при передаче в HTTP-запросе их необходимо кодировать в URL.

Например, запрос с фильтром steps.interval.civil_start_time >= "2026-03-04T00:00:00" должен быть закодирован следующим образом:

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

Формат названия

Если тип данных состоит из нескольких слов, формат идентификатора будет различаться в пути к ресурсу и фильтре:

  • Путь к конечной точке – используйте дефисы (например, /dataTypes/body-fat).
  • Строка фильтра: используйте символы подчеркивания (например, body_fat).

Если в идентификаторе фильтра используются дефисы, API возвращает ошибку 400 Bad Request с причиной INVALID_DATA_POINT_FILTER.

Типы фильтров и поля

Поля, которые вы используете в фильтре, зависят от типа записи типа данных, по которому вы выполняете запрос. В таблице ниже описаны поля, поддерживаемые для каждого типа записи:

Тип записи Описание Поддерживаемые поля фильтров
Интервал Точки данных, записанные за определенный период времени (например, steps, distance, calories). {dataType}.interval.start_time
{dataType}.interval.civil_start_time

Пример:
steps.interval.civil_start_time
Пример Мгновенные наблюдения или короткие измерения (например, weight, body-fat, blood-glucose). {dataType}.sample_time.physical_time
{dataType}.sample_time.civil_time

Пример:
body_fat.sample_time.physical_time
Каждый день Ежедневные показатели и сводки (например, daily-heart-rate-variability). {dataType}.date

Пример:
daily_heart_rate_variability.date
Сеанс Расширенные сеансы пользователей со специальными правилами времени. Тренировка: {dataType}.interval.civil_start_time
Сон: sleep.interval.end_time, sleep.interval.civil_end_time
ЭКГ: electrocardiogram.interval.start_time

Пример:
sleep.interval.civil_end_time

Поддерживаемые операторы и правила форматирования

Выражения фильтра должны соответствовать следующим правилам форматирования:

Операторы сравнения

Поддерживаются только два оператора сравнения:

Оператор Описание
>= Нижняя граница (включительно).
< Верхняя граница (не включена).

При использовании других операторов сравнения (например, >, <= или =) возвращается значение 400 Bad Request с INVALID_DATA_POINT_FILTER_RESTRICTION_COMPARATOR.

Логические операторы

Оператор Поддержка
AND Оператор по умолчанию и единственный поддерживаемый оператор. Используется для объединения границ начала и конца.
OR Не поддерживается. При использовании OR возвращается 400 Bad Request с причиной ошибки INVALID_DATA_POINT_FILTER_EXPRESSION_STRUCTURE ("Фильтр должен представлять собой конъюнкцию или последовательность ограничений. Найдено: DISJUNCTION").

Литералы времени

В выражениях фильтров временные литералы должны быть представлены в следующих форматах:

Тип времени Требования Примеры
Физическое время Формат RFC 3339, заканчивающийся на Z или смещение UTC. Представляет реальные события в формате UTC. Правильно: "2026-03-01T00:00:00Z", "2026-03-01T00:00:00-08:00"
Неправильно: "2026-03-01"
Гражданское время Формат ISO 8601: YYYY-MM-DD[THH:mm:ss]. Время на часах пользователя без учета местоположения и смещения часового пояса. Правильно: "2026-03-01", "2026-03-01T08:30:00"

Правила проверки фильтров

Фильтры работают по следующим правилам:

Правило Описание Примеры
Нельзя использовать разные типы времени Не смешивайте физические и гражданские временные границы. Недопустимое значение: steps.interval.start_time >= "2026-03-01T00:00:00Z" AND steps.interval.civil_start_time < "2026-03-02"
Ошибка: INVALID_DATA_POINT_FILTER_MIXED_TIME_RESTRICTIONS ("Фильтр не может содержать диапазоны физического и гражданского времени")
Нельзя использовать смешанные типы данных Используйте поля, относящиеся к типу данных в пути запроса. Недействительный: путь /users/.../dataTypes/steps/... с фильтром distance.interval.start_time >= "..."
Ошибка: INVALID_DATA_POINT_FILTER_COLLECTION_MISMATCH ("Тип данных в фильтре не соответствует коллекции родительских типов данных")
Логика временного порядка Верхняя граница должна быть больше нижней. Недопустимое значение: steps.interval.start_time >= "2026-03-02T00:00:00Z" AND steps.interval.start_time < "2026-03-01T00:00:00Z"
Ошибка: INVALID_TIME_RANGE ("Время окончания запроса должно быть строго больше времени начала")
Формат запроса Используйте змеиный регистр, соответствующий названию типа данных. Недопустимое значение: body-fat.sample_time.physical_time >= "..."
Ошибка: INVALID_DATA_POINT_FILTER ("Недопустимый фильтр")

Если фильтры недопустимы, API возвращает код статуса HTTP 400 Bad Request. Проверьте код причины ошибки в error.details[].metadata.detailedReasons.

Необходимые области действия OAuth

Чтобы запрашивать точки данных с помощью фильтров, авторизованный пользователь должен предоставить соответствующую область действия OAuth для этого типа данных. Если обязательная область действия отсутствует, API возвращает статус 403 Forbidden с сообщением MISSING_OAUTH_SCOPE.

В таблице ниже сопоставлены области действия OAuth и типы данных, к которым они предоставляют доступ с правами чтения. В таблице области действия представлены в относительном формате (например, .activity_and_fitness.readonly представляет https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly):

Требуемая область действия OAuth Типы данных
.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 электрокардиограмма;
.health_metrics_and_measurements.readonly blood-glucose, body-fat, core-body-temperature, daily-heart-rate-variability, daily-heart-rate-zones, daily-oxygen-saturation, daily-respiratory-rate, daily-resting-heart-rate, daily-sleep-temperature-derivations, heart-rate, heart-rate-variability, height, oxygen-saturation, respiratory-rate-sleep-summary, skin-temperature-sensors, weight
.irn.readonly irregular-rhythm-notification
.nutrition.readonly food, food-measurement-unit, hydration-log, nutrition-log
.sleep.readonly сон

Если вашему клиенту предоставлена только область записи (например, .activity_and_fitness.writeonly) для запрошенного типа данных, вы все равно можете запрашивать точки данных, записанные вашим клиентом. В этом случае запросы неявно ограничены семейством источников данных self-sources. Подробнее о фильтрации по семейству источников данных и ограничениях на типы данных…

Примеры использования

В примерах ниже показано, как создавать фильтры для распространенных сценариев.

Как запросить данные о шагах за определенный период времени

Шаги, зарегистрированные в период с 2026-03-01T00:00:00Z (включительно) по 2026-03-02T00:00:00Z (не включительно):

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"

Как запросить данные о шагах за определенный период времени

Запрос шагов за весь день 4 марта 2026 г. относительно местного времени пользователя:

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"

Как запросить данные о проценте жировой ткани по времени взятия образца

Запрос данных о количестве жировой ткани, зарегистрированных начиная с марта 2026 г. (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"

Вес запроса по времени выборки

Журналы веса запросов, записанные после определенного местного времени:

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

Запрос ежедневных сводок о вариабельности сердечного ритма

Как запросить ежедневные сводки о вариабельности сердечного ритма (ВСР), записанные до определенной даты:

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

Как запросить данные о тренировках по времени начала

Запрос сеансов тренировок, которые произошли в определенную неделю по местному часовому поясу пользователя:

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"

Как запросить сеансы сна по гражданскому времени окончания

Чтобы запросить записи о сне по времени окончания сеанса, выполните следующие действия:

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"

Как запросить электрокардиограммы по времени начала

Запрашивать записи ЭКГ, начиная с определенного момента времени в UTC. Обратите внимание, что запросы ЭКГ поддерживают сравнение >= только по параметру start_time:

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

Как фильтровать по семейству источников данных

Семейство источников данных – это логическая группа источников данных, например умных часов, мобильных приложений или записей, внесенных вручную. Она позволяет изолировать или агрегировать данные из определенных источников, например физических носимых устройств, записей, сделанных вручную, или данных, записанных вашим клиентом.

Параметр dataSourceFamily поддерживается всеми конечными точками: list, reconcile, rollUp и dailyRollUp. Механизм передачи зависит от конечной точки:

Конечная точка (метод HTTP) Механизм
list (GET) Передайте dataSourceFamily в качестве параметра запроса URL.
reconcile (GET) Передайте dataSourceFamily в качестве параметра запроса URL.
rollUp (POST) Передайте dataSourceFamily в качестве поля в теле запроса JSON.
dailyRollUp (POST) Передайте dataSourceFamily в качестве поля в теле запроса JSON.

Поддерживаемые семейства источников данных

В таблице ниже описаны поддерживаемые значения dataSourceFamily.

Option Описание
users/me/dataSourceFamilies/all-sources Значение по умолчанию (при предоставлении области действия для чтения) Включает точки данных из всех доступных собственных и сторонних источников. При выборе этого варианта возвращаются данные сторонних приложений (например, шаги, зарегистрированные умными часами, сторонним приложением, мобильным телефоном и вручную).
users/me/dataSourceFamilies/google-wearables Включает данные, записанные трекерами Google и Fitbit (например, носимыми трекерами Fitbit и Pixel Watch). Исключает данные, зарегистрированные вручную, и расчетные данные телефона. Используйте этот вариант, если для интеграции требуются необработанные данные телеметрии датчиков, записанные непосредственно носимым устройством.
users/me/dataSourceFamilies/google-sources Включает собственные источники Google и Fitbit. Сюда относятся записи с физических трекеров, данные из сервиса "Здоровье и спорт" и любые записи, добавленные вручную через собственные приложения (например, приложение Fitbit или Google Fit).
users/me/dataSourceFamilies/self-sources Включает только данные, записанные вызывающим клиентом через Google Health API (показатели, источник данных которых был зарегистрирован через API с тем же идентификатором клиента OAuth, что и у вызывающего клиента).

Если ни одна точка данных не соответствует запрошенному семейству источников данных, в ответе будет пустой список, а не ошибка.

Области действия с правом на запись и собственные источники

Вызывающие функции, которым предоставлены только области записи (например, .activity_and_fitness.writeonly) для запрошенных типов данных, могут читать только те данные, которые они сами записали.

  • Запросы без явного параметра dataSourceFamily или с параметром dataSourceFamily, заданным как users/me/dataSourceFamilies/self-sources, неявно ограничены значением self-sources.
  • Если запросить любое другое семейство источников данных (например, all-sources, google-wearables или google-sources) только с областью действия для записи, произойдет сбой с ошибкой 403 Forbidden (PERMISSION_DENIED).

Ограничения на типы данных для конечной точки списка

В конечной точке list (users.dataTypes.dataPoints.list) фильтрация по dataSourceFamily не поддерживается для типов данных sleep, food и food-measurement-unit:

  • Если явно задать значение dataSourceFamily для list для sleep, food или food-measurement-unit, произойдет сбой с ошибкой 400 Bad Request (INVALID_ARGUMENT).
  • Если для этих типов данных вызывается функция list, когда предоставлена только область записи (где ограничение на self-sources подразумевается областями вызывающего объекта), возникает ошибка 403 Forbidden (PERMISSION_DENIED).
  • Чтобы отфильтровать точки данных sleep по параметру dataSourceFamily, используйте конечную точку reconcile.

Примеры семейств источников данных

Чтобы получить список точек необработанных данных, которые ваш клиент записал для пользователя, вызовите конечную точку list с параметром запроса dataSourceFamily, для которого задано значение users/me/dataSourceFamilies/self-sources.

Например, следующий GET-запрос содержит список необработанных данных body-fat, записанных вызывающим клиентом начиная с 01.03.2026:

Запрос

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

Ответ

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

Чтобы получить согласованный поток данных из определенного семейства источников данных, вызовите конечную точку reconcile с параметром запроса dataSourceFamily.

Например, следующий GET-запрос позволяет получить данные о сне, зарегистрированные трекером, за день после 03.03.2026:

Запрос

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

Ответ

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

Чтобы агрегировать точки данных за определенный период, ограниченный определенным семейством источников данных, вызовите конечную точку rollUp и передайте поле dataSourceFamily в теле запроса JSON.

Следующий запрос POST позволяет получить данные о количестве шагов, пройденных в течение дня, с разбивкой по часам (3600s), агрегированные исключительно с носимых устройств:

Запрос

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

Ответ

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

Чтобы агрегировать ежедневные точки данных для определенного семейства источников, вызовите конечную точку dailyRollUp и передайте поле dataSourceFamily в теле запроса.

Например, следующий запрос рассчитывает ежедневные сводки для шагов пользователя, включая все собственные источники Google и Fitbit (носимые устройства и записи, добавленные вручную):

Запрос

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

Ответ

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