// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.devicesandservices.health.v4;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/devicesandservices/health/v4/data_coordinates.proto";
import "google/devicesandservices/health/v4/data_model.proto";
import "google/devicesandservices/health/v4/data_source.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";
import "google/type/interval.proto";

option csharp_namespace = "Google.DevicesAndServices.Health.V4";
option go_package = "google.golang.org/genproto/googleapis/devicesandservices/health/apiv4main;healthpb";
option java_multiple_files = true;
option java_outer_classname = "DataPointsProto";
option java_package = "com.google.devicesandservices.health.v4";
option php_namespace = "Google\\DevicesAndServices\\Health\\V4";
option ruby_package = "Google::DevicesAndServices::Health::V4";

// Data Points Service exposing the user's health and fitness measured and
// derived data.
service DataPointsService {
  option (google.api.default_host) = "health.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly,"
      "https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly,"
      "https://www.googleapis.com/auth/googlehealth.location.readonly,"
      "https://www.googleapis.com/auth/googlehealth.sleep.readonly";

  // Get a single identifyable data point.
  rpc GetDataPoint(GetDataPointRequest) returns (DataPoint) {
    option (google.api.http) = {
      get: "/v4/{name=users/*/dataTypes/*/dataPoints/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Query user health and fitness data points.
  rpc ListDataPoints(ListDataPointsRequest) returns (ListDataPointsResponse) {
    option (google.api.http) = {
      get: "/v4/{parent=users/*/dataTypes/*}/dataPoints"
    };
    option (google.api.method_signature) = "parent";
  }

  // Creates a single identifiable data point.
  rpc CreateDataPoint(CreateDataPointRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v4/{parent=users/*/dataTypes/*}/dataPoints"
      body: "data_point"
    };
    option (google.api.method_signature) = "parent,data_point";
    option (google.longrunning.operation_info) = {
      response_type: "DataPoint"
      metadata_type: "CreateDataPointOperationMetadata"
    };
  }

  // Updates a single identifiable data point. If a data point with the
  // specified `name` is not found, the request will fail.
  rpc UpdateDataPoint(UpdateDataPointRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      patch: "/v4/{data_point.name=users/*/dataTypes/*/dataPoints/*}"
      body: "data_point"
    };
    option (google.api.method_signature) = "data_point";
    option (google.longrunning.operation_info) = {
      response_type: "DataPoint"
      metadata_type: "UpdateDataPointOperationMetadata"
    };
  }

  // Delete a batch of identifyable data points.
  rpc BatchDeleteDataPoints(BatchDeleteDataPointsRequest)
      returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v4/{parent=users/*/dataTypes/*}/dataPoints:batchDelete"
      body: "*"
    };
    option (google.longrunning.operation_info) = {
      response_type: "BatchDeleteDataPointsResponse"
      metadata_type: "BatchDeleteDataPointsOperationMetadata"
    };
  }

  // Reconcile data points from multiple data sources into a single data stream.
  rpc ReconcileDataPoints(ReconcileDataPointsRequest)
      returns (ReconcileDataPointsResponse) {
    option (google.api.http) = {
      get: "/v4/{parent=users/*/dataTypes/*}/dataPoints:reconcile"
    };
  }

  // Roll up data points over physical time intervals for supported data types.
  rpc RollUpDataPoints(RollUpDataPointsRequest)
      returns (RollUpDataPointsResponse) {
    option (google.api.http) = {
      post: "/v4/{parent=users/*/dataTypes/*}/dataPoints:rollUp"
      body: "*"
    };
  }

  // Roll up data points over civil time intervals for supported data types.
  rpc DailyRollUpDataPoints(DailyRollUpDataPointsRequest)
      returns (DailyRollUpDataPointsResponse) {
    option (google.api.http) = {
      post: "/v4/{parent=users/*/dataTypes/*}/dataPoints:dailyRollUp"
      body: "*"
    };
  }

  // Exports exercise data in TCX format.
  //
  // **IMPORTANT:** HTTP clients must append `?alt=media` to the
  // request URL to download the raw TCX file.
  //
  // Example:
  // `https://health.googleapis.com/v4/users/me/dataTypes/exercise/dataPoints/EXERCISE_ID:exportExerciseTcx?alt=media`
  //
  // Without `alt=media`, the server returns a JSON response
  // (`ExportExerciseTcxResponse`)
  // which is intended primarily for gRPC clients.
  //
  // **Note:** While the Authorization section below states that any one of the
  // listed scopes is accepted, this specific method requires the user to
  // provide both one of the `activity_and_fitness` scopes (`normal` or
  // `readonly`) AND one of the `location` scopes (`normal` or `readonly`) in
  // their access token to succeed.
  rpc ExportExerciseTcx(ExportExerciseTcxRequest)
      returns (ExportExerciseTcxResponse) {
    option (google.api.http) = {
      get: "/v4/{name=users/*/dataTypes/*/dataPoints/*}:exportExerciseTcx"
    };
    option (google.api.method_signature) = "name";
  }
}

// A computed or recorded metric.
message DataPoint {
  option (google.api.resource) = {
    type: "health.googleapis.com/DataPoint"
    pattern: "users/{user}/dataTypes/{data_type}/dataPoints/{data_point}"
    plural: "dataPoints"
    singular: "dataPoint"
  };

  // Data type component in the name field will always correspond to the data
  // field set.
  // These messages represent the data payload for each data type and are
  // embedded within the `DataPoint` resource. They are not standalone resources
  // themselves.
  // Unless otherwise noted, data types will exclude data points that are
  // identified as recorded by wearables in intervals when they were not
  // actually worn.
  oneof data {
    // Optional. Data for points in the `steps` interval data type collection.
    Steps steps = 4 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `floors` interval data type collection.
    Floors floors = 5 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `heart-rate` sample data type
    // collection.
    HeartRate heart_rate = 6 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `sleep` session data type collection.
    Sleep sleep = 8 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-resting-heart-rate` daily data
    // type collection.
    DailyRestingHeartRate daily_resting_heart_rate = 9
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-heart-rate-variability` daily
    // data type collection.
    DailyHeartRateVariability daily_heart_rate_variability = 10
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `exercise` session data type collection.
    Exercise exercise = 11 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `weight` sample data type collection.
    Weight weight = 12 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `altitude` interval data type
    // collection.
    Altitude altitude = 13 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `distance` interval data type
    // collection.
    Distance distance = 14 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `body-fat` sample data type collection.
    BodyFat body_fat = 15 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `active-zone-minutes` interval data type
    // collection, measured in minutes.
    ActiveZoneMinutes active_zone_minutes = 17
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `heart-rate-variability` sample data
    // type collection.
    HeartRateVariability heart_rate_variability = 19
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-sleep-temperature-derivations`
    // daily data type collection.
    DailySleepTemperatureDerivations daily_sleep_temperature_derivations = 20
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `sedentary-period` interval data type
    // collection.
    SedentaryPeriod sedentary_period = 21
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `run-vo2-max` sample data type
    // collection.
    RunVO2Max run_vo2_max = 22 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `oxygen-saturation` sample data type
    // collection.
    OxygenSaturation oxygen_saturation = 24
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-oxygen-saturation` daily data
    // type collection.
    DailyOxygenSaturation daily_oxygen_saturation = 25
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `activity-level` daily data type
    // collection.
    ActivityLevel activity_level = 26 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `vo2-max` sample data type collection.
    VO2Max vo2_max = 27 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-vo2-max` daily data type
    // collection.
    DailyVO2Max daily_vo2_max = 28 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `nutrition-log` session data type
    // collection.
    NutritionLog nutrition_log = 29 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `irregular-rhythm-notification` session
    // data type collection.
    IrregularRhythmNotification irregular_rhythm_notification = 30
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `electrocardiogram` session data type
    // collection.
    Electrocardiogram electrocardiogram = 31
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-heart-rate-zones` daily data type
    // collection.
    DailyHeartRateZones daily_heart_rate_zones = 32
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `hydration-log` session data type
    // collection.
    HydrationLog hydration_log = 33 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The food details.
    Food food = 34 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `time-in-heart-rate-zone` interval data
    // type collection.
    TimeInHeartRateZone time_in_heart_rate_zone = 35
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `active-minutes` interval data type
    // collection.
    ActiveMinutes active_minutes = 36 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `respiratory-rate-sleep-summary` sample
    // data type collection.
    RespiratoryRateSleepSummary respiratory_rate_sleep_summary = 37
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `daily-respiratory-rate` daily data type
    // collection.
    DailyRespiratoryRate daily_respiratory_rate = 38
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `swim-lengths-data` interval data type
    // collection.
    SwimLengthsData swim_lengths_data = 39
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `height` sample data type collection.
    Height height = 40 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `basal-energy-burned` interval data type
    // collection.
    BasalEnergyBurned basal_energy_burned = 41
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `core-body-temperature` sample data type
    // collection.
    CoreBodyTemperature core_body_temperature = 42
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `active-energy-burned` interval data
    // type collection.
    ActiveEnergyBurned active_energy_burned = 44
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. The food measurement unit details.
    FoodMeasurementUnit food_measurement_unit = 45
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Data for points in the `blood-glucose` sample data type
    // collection.
    BloodGlucose blood_glucose = 46 [(google.api.field_behavior) = OPTIONAL];
  }

  // Identifier. Data point name, only supported for the subset of identifiable
  // data types. For the majority of the data types, individual data points do
  // not need to be identified and this field would be empty.
  //
  // Format: `users/{user}/dataTypes/{data_type}/dataPoints/{data_point}`
  //
  // Example:
  // `users/abcd1234/dataTypes/sleep/dataPoints/a1b2c3d4-e5f6-7890-1234-567890abcdef`
  //
  // The `{user}` ID is a system-generated identifier, as described in
  // [Identity.health_user_id][google.devicesandservices.health.v4.Identity.health_user_id].
  //
  // The `{data_type}` ID corresponds to the kebab-case version of the field
  // names in the [DataPoint
  // data][google.devicesandservices.health.v4.DataPoint] union
  // field, e.g. `total-calories` for the `total_calories` field.
  //
  // The `{data_point}` ID can be client-provided or system-generated.
  // If client-provided, it must be a string of 4-63 characters,
  // containing only lowercase letters, numbers, and hyphens.
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Optional. Data source information for the metric
  DataSource data_source = 3 [(google.api.field_behavior) = OPTIONAL];
}

// A reconciled computed or recorded metric.
message ReconciledDataPoint {
  // Data type component in the name field will always correspond to the data
  // field set.
  // These messages represent the data payload for each data type and are
  // embedded within the `DataPoint` resource. They are not standalone resources
  // themselves.
  // Unless otherwise noted, data types reconciliation algorithm will exclude
  // data points that are identified as recorded by wearables in intervals
  // when they were not actually worn.
  oneof data {
    // Data for points in the `steps` interval data type collection.
    Steps steps = 4;

    // Data for points in the `floors` interval data type collection.
    Floors floors = 5;

    // Data for points in the `heart-rate` sample data type collection.
    HeartRate heart_rate = 6;

    // Data for points in the `sleep` session data type collection.
    Sleep sleep = 8;

    // Data for points in the `daily-resting-heart-rate` daily data type
    // collection.
    DailyRestingHeartRate daily_resting_heart_rate = 9;

    // Data for points in the `daily-heart-rate-variability` daily data type
    // collection.
    DailyHeartRateVariability daily_heart_rate_variability = 10;

    // Data for points in the `exercise` session data type collection.
    Exercise exercise = 11;

    // Data for points in the `weight` sample data type collection.
    Weight weight = 12;

    // Data for points in the `altitude` interval data type collection.
    Altitude altitude = 13;

    // Data for points in the `distance` interval data type collection.
    Distance distance = 14;

    // Data for points in the `body-fat` sample data type collection.
    BodyFat body_fat = 15;

    // Data for points in the `active-zone-minutes` interval data type
    // collection, measured in minutes.
    ActiveZoneMinutes active_zone_minutes = 17;

    // Data for points in the `heart-rate-variability` sample data type
    // collection.
    HeartRateVariability heart_rate_variability = 19;

    // Data for points in the `daily-sleep-temperature-derivations` daily data
    // type collection.
    DailySleepTemperatureDerivations daily_sleep_temperature_derivations = 20;

    // Data for points in the `sedentary-period` interval data type collection.
    SedentaryPeriod sedentary_period = 21;

    // Data for points in the `run-vo2-max` sample data type collection.
    RunVO2Max run_vo2_max = 22;

    // Data for points in the `oxygen-saturation` sample data type collection.
    OxygenSaturation oxygen_saturation = 24;

    // Data for points in the `daily-oxygen-saturation` daily data type
    // collection.
    DailyOxygenSaturation daily_oxygen_saturation = 25;

    // Data for points in the `activity-level` daily data type collection.
    ActivityLevel activity_level = 26;

    // Data for points in the `vo2-max` sample data type collection.
    VO2Max vo2_max = 27;

    // Data for points in the `daily-vo2-max` daily data type collection.
    DailyVO2Max daily_vo2_max = 28;

    // Data for points in the `nutrition-log` session data type collection.
    NutritionLog nutrition_log = 29;

    // Data for points in the `daily-heart-rate-zones` daily data type
    // collection.
    DailyHeartRateZones daily_heart_rate_zones = 32;

    // Data for points in the `hydration-log` session data type collection.
    HydrationLog hydration_log = 33;

    // Data for points in the `time-in-heart-rate-zone` interval data type
    // collection.
    TimeInHeartRateZone time_in_heart_rate_zone = 35;

    // Data for points in the `active-minutes` interval data type collection.
    ActiveMinutes active_minutes = 36;

    // Data for points in the `respiratory-rate-sleep-summary` sample data type
    // collection.
    RespiratoryRateSleepSummary respiratory_rate_sleep_summary = 37;

    // Data for points in the `daily-respiratory-rate` daily data type
    // collection.
    DailyRespiratoryRate daily_respiratory_rate = 38;

    // Data for points in the `swim-lengths-data` interval data type collection.
    SwimLengthsData swim_lengths_data = 39;

    // Data for points in the `height` sample data type collection.
    Height height = 40;

    // Data for points in the `basal-energy-burned` interval data type
    // collection.
    BasalEnergyBurned basal_energy_burned = 41;

    // Data for points in the `core-body-temperature` sample data type
    // collection.
    CoreBodyTemperature core_body_temperature = 42;

    // Data for points in the `active-energy-burned` interval data type
    // collection.
    ActiveEnergyBurned active_energy_burned = 44;

    // Data for points in the `blood-glucose` sample data type collection.
    BloodGlucose blood_glucose = 46;
  }

  // Identifier. Data point name, only supported for the subset of identifiable
  // data types. For the majority of the data types, individual data points do
  // not need to be identified and this field would be empty.
  //
  // Format: `users/{user}/dataTypes/{data_type}/dataPoints/{data_point}`
  //
  // Example:
  // `users/abcd1234/dataTypes/sleep/dataPoints/a1b2c3d4-e5f6-7890-1234-567890abcdef`
  //
  // The `{user}` ID is a system-generated identifier, as described in
  // [Identity.health_user_id][google.devicesandservices.health.v4.Identity.health_user_id].
  //
  // The `{data_type}` ID corresponds to the kebab-case version of the field
  // names in the [DataPoint
  // data][google.devicesandservices.health.v4.DataPoint] union
  // field, e.g. `total-calories` for the `total_calories` field.
  //
  // The `{data_point}` ID can be client-provided or system-generated.
  // If client-provided, it must be a string of 4-63 characters,
  // containing only lowercase letters, numbers, and hyphens.
  string data_point_name = 1 [(google.api.field_behavior) = IDENTIFIER];
}

// Value of a rollup for a single physical time interval (aggregation window) of
// reconciled data points from all data sources, excluding those data points
// that are identified as recorded by wearables in intervals when they were not
// actually worn.
message RollupDataPoint {
  // Outcome of a rollup of the requested data type.
  //
  // `{DataType}RollupValue` messages for each data type contain aggregated
  // values for all supported fields.
  //
  //  The field names usually follow the format
  // `{original_field_name}_{aggregation_function}`. For example:
  // `confidence_min`, `confidence_sum`.
  //
  // If there were no manual, on-wrist data points in this interval,
  // the value will not be set. When the value is set, but the data shows zero,
  // e.g. `steps.count_sum = 0`, it means that a device was worn but it did not
  // record any data points for this data type.
  //
  // These messages represent the aggregated data payload for each data type
  // and are embedded within the `RollupDataPoint`. They are not standalone
  // resources themselves.
  oneof value {
    // Returned by default when rolling up data points from the `steps` data
    // type, or when requested explicitly using the `steps` rollup type
    // identifier.
    StepsRollupValue steps = 5;

    // Returned by default when rolling up data points from the `floors` data
    // type, or when requested explicitly using the `floors` rollup type
    // identifier.
    FloorsRollupValue floors = 6;

    // Returned by default when rolling up data points from the `heart-rate`
    // data type, or when requested explicitly using the `heart-rate` rollup
    // type identifier.
    HeartRateRollupValue heart_rate = 7;

    // Returned by default when rolling up data points from the `weight` data
    // type, or when requested explicitly using the `weight` rollup type
    // identifier.
    WeightRollupValue weight = 8;

    // Returned by default when rolling up data points from the `altitude` data
    // type, or when requested explicitly using the `altitude` rollup type
    // identifier.
    AltitudeRollupValue altitude = 9;

    // Returned by default when rolling up data points from the `distance` data
    // type, or when requested explicitly using the `distance` rollup type
    // identifier.
    DistanceRollupValue distance = 10;

    // Returned by default when rolling up data points from the `body-fat` data
    // type, or when requested explicitly using the `body-fat` rollup type
    // identifier.
    BodyFatRollupValue body_fat = 11;

    // Returned by default when rolling up data points from the `total-calories`
    // data type, or when requested explicitly using the `total-calories`
    // rollup type identifier.
    TotalCaloriesRollupValue total_calories = 12;

    // Returned by default when rolling up data points from the
    // `active-zone-minutes` data type, or when requested explicitly using the
    // `active-zone-minutes` rollup type identifier.
    ActiveZoneMinutesRollupValue active_zone_minutes = 13;

    // Returned by default when rolling up data points from the
    // `sedentary-period` data type, or when requested explicitly using the
    // `sedentary-period` rollup type identifier.
    SedentaryPeriodRollupValue sedentary_period = 15;

    // Returned by default when rolling up data points from the
    // `run-vo2-max` data type, or when requested explicitly using the
    // `run-vo2-max` rollup type identifier.
    RunVO2MaxRollupValue run_vo2_max = 16;

    // Returned by default when rolling up data points from the
    // `calories-in-heart-rate-zone` data type, or when requested explicitly
    // using the `calories-in-heart-rate-zone` rollup type identifier.
    CaloriesInHeartRateZoneRollupValue calories_in_heart_rate_zone = 17;

    // Returned by default when rolling up data points from the
    // `activity-level` data type, or when requested explicitly using the
    // `activity-level` rollup type identifier.
    ActivityLevelRollupValue activity_level = 18;

    // Returned by default when rolling up data points from the
    // `nutrition-log` data type, or when requested explicitly using the
    // `nutrition-log` rollup type identifier.
    NutritionLogRollupValue nutrition_log = 19;

    // Returned by default when rolling up data points from the
    // `hydration-log` data type, or when requested explicitly using the
    // `hydration-log` rollup type identifier.
    HydrationLogRollupValue hydration_log = 20;

    // Returned by default when rolling up data points from the
    // `time-in-heart-rate-zone` data type, or when requested explicitly using
    // the `time-in-heart-rate-zone` rollup type identifier.
    TimeInHeartRateZoneRollupValue time_in_heart_rate_zone = 21;

    // Returned by default when rolling up data points from the
    // `active-minutes` data type, or when requested explicitly using the
    // `active-minutes` rollup type identifier.
    ActiveMinutesRollupValue active_minutes = 22;

    // Returned by default when rolling up data points from the
    // `swim-lengths-data` data type, or when requested explicitly using the
    // `swim-lengths-data` rollup type identifier.
    SwimLengthsDataRollupValue swim_lengths_data = 23;

    // Returned by default when rolling up data points from the
    // `core-body-temperature` data type, or when requested explicitly using
    // the `core-body-temperature` rollup type identifier.
    CoreBodyTemperatureRollupValue core_body_temperature = 24;

    // Returned by default when rolling up data points from the
    // `active-energy-burned` data type.
    ActiveEnergyBurnedRollupValue active_energy_burned = 25;

    // Returned by default when rolling up data points from the
    // `blood-glucose` data type.
    BloodGlucoseRollupValue blood_glucose = 26;
  }

  // Start time of the window this value aggregates over
  google.protobuf.Timestamp start_time = 1;

  // End time of the window this value aggregates over
  google.protobuf.Timestamp end_time = 2;
}

// Value of a daily rollup for a single civil time interval (aggregation window)
// of reconciled data points from all data sources, excluding those data points
// that are identified as recorded by wearables in intervals when they were not
// actually worn.
message DailyRollupDataPoint {
  // Outcome of a rollup of the requested roll-up type.
  //
  // `{RollUpType}RollupValue` messages for each data type contain aggregated
  // values for all supported fields.
  //
  //  The field names usually follow the format
  // `{original_field_name}_{aggregation_function}`. For example:
  // `confidence_min`, `confidence_sum`.
  //
  // If there were no manual, on-wrist data points in this interval,
  // the value will not be set. When the value is set, but the data shows zero,
  // e.g. `steps.count_sum = 0`, it means that a device was worn but it did not
  // record any data points for this data type.
  //
  // These messages represent the aggregated data payload for each data type
  // and are embedded within the `DailyRollupDataPoint`. They are not standalone
  // resources themselves.
  oneof value {
    // Returned by default when rolling up data points from the `steps` data
    // type, or when requested explicitly using the `steps` rollup type
    // identifier.
    StepsRollupValue steps = 5;

    // Returned by default when rolling up data points from the `floors` data
    // type, or when requested explicitly using the `floors` rollup type
    // identifier.
    FloorsRollupValue floors = 6;

    // Returned by default when rolling up data points from the `heart-rate`
    // data type, or when requested explicitly using the `heart-rate` rollup
    // type identifier.
    HeartRateRollupValue heart_rate = 7;

    // Returned by default when rolling up data points from the
    // `daily-resting-heart-rate` data type, or when requested
    // explicitly using the `resting-heart-rate-personal-range` rollup type
    // identifier.
    RestingHeartRatePersonalRangeRollupValue resting_heart_rate_personal_range =
        8;

    // Returned by default when rolling up data points from the
    // `daily-heart-rate-variability` data type, or when requested explicitly
    // using the `heart-rate-variability-personal-range` rollup type
    // identifier.
    HeartRateVariabilityPersonalRangeRollupValue
        heart_rate_variability_personal_range = 9;

    // Returned by default when rolling up data points from the `weight` data
    // type, or when requested explicitly using the `weight` rollup type
    // identifier.
    WeightRollupValue weight = 10;

    // Returned by default when rolling up data points from the `altitude` data
    // type, or when requested explicitly using the `altitude` rollup type
    // identifier.
    AltitudeRollupValue altitude = 11;

    // Returned by default when rolling up data points from the `distance` data
    // type, or when requested explicitly using the `distance` rollup type
    // identifier.
    DistanceRollupValue distance = 12;

    // Returned by default when rolling up data points from the `body-fat` data
    // type, or when requested explicitly using the `body-fat` rollup type
    // identifier.
    BodyFatRollupValue body_fat = 13;

    // Returned by default when rolling up data points from the `total-calories`
    // data type, or when requested explicitly using the `total-calories`
    // rollup type identifier.
    TotalCaloriesRollupValue total_calories = 14;

    // Returned by default when rolling up data points from the
    // `active-zone-minutes` data type, or when requested explicitly using the
    // `active-zone-minutes` rollup type identifier.
    ActiveZoneMinutesRollupValue active_zone_minutes = 15;

    // Returned by default when rolling up data points from the
    // `sedentary-period` data type, or when requested explicitly using the
    // `sedentary-period` rollup type identifier.
    SedentaryPeriodRollupValue sedentary_period = 17;

    // Returned by default when rolling up data points from the
    // `run-vo2-max` data type, or when requested explicitly using the
    // `run-vo2-max` rollup type identifier.
    RunVO2MaxRollupValue run_vo2_max = 18;

    // Returned by default when rolling up data points from the
    // `calories-in-heart-rate-zone` data type, or when requested explicitly
    // using the `calories-in-heart-rate-zone` rollup type identifier.
    CaloriesInHeartRateZoneRollupValue calories_in_heart_rate_zone = 19;

    // Returned by default when rolling up data points from the
    // `activity-level` data type, or when requested explicitly using the
    // `activity-level` rollup type identifier.
    ActivityLevelRollupValue activity_level = 20;

    // Returned by default when rolling up data points from the
    // `nutrition-log` data type, or when requested explicitly using the
    // `nutrition-log` rollup type identifier.
    NutritionLogRollupValue nutrition_log = 21;

    // Returned by default when rolling up data points from the
    // `hydration-log` data type, or when requested explicitly using the
    // `hydration-log` rollup type identifier.
    HydrationLogRollupValue hydration_log = 22;

    // Returned by default when rolling up data points from the
    // `time-in-heart-rate-zone` data type, or when requested explicitly using
    // the `time-in-heart-rate-zone` rollup type identifier.
    TimeInHeartRateZoneRollupValue time_in_heart_rate_zone = 23;

    // Returned by default when rolling up data points from the
    // `active-minutes` data type, or when requested explicitly using the
    // `active-minutes` rollup type identifier.
    ActiveMinutesRollupValue active_minutes = 24;

    // Returned by default when rolling up data points from the
    // `swim-lengths-data` data type, or when requested explicitly using the
    // `swim-lengths-data` rollup type identifier.
    SwimLengthsDataRollupValue swim_lengths_data = 25;

    // Returned by default when rolling up data points from the
    // `core-body-temperature` data type, or when requested explicitly using
    // the `core-body-temperature` rollup type identifier.
    CoreBodyTemperatureRollupValue core_body_temperature = 26;

    // Returned by default when rolling up data points from the
    // `active-energy-burned` data type.
    ActiveEnergyBurnedRollupValue active_energy_burned = 27;

    // Returned by default when rolling up data points from the
    // `blood-glucose` data type.
    BloodGlucoseRollupValue blood_glucose = 28;
  }

  // Start time of the window this value aggregates over
  CivilDateTime civil_start_time = 1;

  // End time of the window this value aggregates over
  CivilDateTime civil_end_time = 2;
}

// Request for getting a single data point
message GetDataPointRequest {
  // Required. The name of the data point to retrieve.
  //
  // Format: `users/{user}/dataTypes/{data_type}/dataPoints/{data_point}`
  //
  // See
  // [DataPoint.name][google.devicesandservices.health.v4.DataPoint.name]
  // for examples and possible values.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "health.googleapis.com/DataPoint"
    }
  ];
}

// Request for listing raw data points
message ListDataPointsRequest {
  // Required. Parent data type of the Data Point collection.
  //
  // Format: `users/me/dataTypes/{data_type}`, e.g.:
  //
  // - `users/me/dataTypes/steps`
  // - `users/me/dataTypes/weight`
  //
  // For a list of the supported data types see the [DataPoint
  // data][google.devicesandservices.health.v4.DataPoint] union
  // field.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "health.googleapis.com/DataType" }
  ];

  // Optional. The maximum number of data points to return.
  // If unspecified, at most 1440 data points will be returned.
  // The maximum page size is 10000; values above that will be truncated
  // accordingly.
  // For `exercise` and `sleep` the default page size is 25.
  // The maximum page size for `exercise` and `sleep` is 25.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The `next_page_token` from a previous request, if any.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Filter expression following https://google.aip.dev/160.
  //
  // A time range (either physical or civil) can be specified.
  //
  // The supported filter fields are:
  //
  //
  // - Interval start time:
  //     - Pattern: `{interval_data_type}.interval.start_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Timestamp literal expected in RFC-3339 format
  //     - Supported logical operators: `AND`
  //     - Example:
  //         - `steps.interval.start_time >= "2023-11-24T00:00:00Z" AND
  //         steps.interval.start_time < "2023-11-25T00:00:00Z"`
  //         - `distance.interval.start_time >= "2024-08-14T12:34:56Z"`
  //
  // - Interval civil start time:
  //     - Pattern: `{interval_data_type}.interval.civil_start_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Date with optional time literal expected in ISO 8601
  //     `YYYY-MM-DD[THH:mm:ss]` format
  //     - Supported logical operators: `AND`
  //     - Example:
  //         - `steps.interval.civil_start_time >= "2023-11-24" AND
  //         steps.interval.civil_start_time < "2023-11-25"`
  //         - `distance.interval.civil_start_time >= "2024-08-14T12:34:56"`
  //
  // - Sample observation physical time:
  //     - Pattern: `{sample_data_type}.sample_time.physical_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Timestamp literal expected in RFC-3339 format
  //     - Supported logical operators: `AND`
  //     - Example:
  //         - `weight.sample_time.physical_time >= "2023-11-24T00:00:00Z"
  //         AND weight.sample_time.physical_time < "2023-11-25T00:00:00Z"`
  //         - `weight.sample_time.physical_time >=
  //         "2024-08-14T12:34:56Z"`
  //
  // - Sample observation civil time:
  //     - Pattern: `{sample_data_type}.sample_time.civil_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Date with optional time literal expected in ISO 8601
  //     `YYYY-MM-DD[THH:mm:ss]` format
  //     - Supported logical operators: `AND`
  //     - Example:
  //        - `weight.sample_time.civil_time >= "2023-11-24" AND
  //        weight.sample_time.civil_time < "2023-11-25"`
  //        - `weight.sample_time.civil_time >= "2024-08-14T12:34:56"`
  //
  // - Daily summary date:
  //     - Pattern: `{daily_summary_data_type}.date`
  //     - Supported comparison operators: `>=`, `<`
  //     - Date literal expected in ISO 8601 `YYYY-MM-DD` format
  //     - Supported logical operators: `AND`
  //     - Example:
  //        - `daily_heart_rate_variability.date < "2024-08-15"`
  //
  //
  //
  // - Session civil start time (**Excluding Sleep and ECG**):
  //     - Pattern: `{session_data_type}.interval.civil_start_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Date with optional time literal expected in ISO 8601
  //     `YYYY-MM-DD[THH:mm:ss]` format
  //     - Supported logical operators: `AND`
  //     - Example:
  //        - `exercise.interval.civil_start_time >= "2023-11-24" AND
  //        exercise.interval.civil_start_time < "2023-11-25"`
  //        - `exercise.interval.civil_start_time >= "2024-08-14T12:34:56"`
  //
  // - Session start time (**ECG specific**):
  //     - Pattern: `electrocardiogram.interval.start_time`
  //     - Supported comparison operators: `>=`
  //     - Timestamp literal expected in RFC-3339 format
  //     - Example:
  //         - `electrocardiogram.interval.start_time >= "2024-08-14T12:34:56Z"`
  //     - Note: Only filtering by start time is supported for ECG. Filtering
  //       by end time (e.g., `electrocardiogram.interval.end_time`) is not
  //       supported.
  //
  // - Session end time (**Sleep specific**):
  //     - Pattern: `sleep.interval.end_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Timestamp literal expected in RFC-3339 format
  //     - Supported logical operators: `AND`, `OR`
  //     - Example:
  //         - `sleep.interval.end_time >= "2023-11-24T00:00:00Z" AND
  //         sleep.interval.end_time < "2023-11-25T00:00:00Z"`
  //
  // - Session civil end time (**Sleep specific**):
  //     - Pattern: `sleep.interval.civil_end_time`
  //     - Supported comparison operators: `>=`, `<`
  //     - Date with optional time literal expected in ISO 8601
  //     `YYYY-MM-DD[THH:mm:ss]` format
  //     - Supported logical operators: `AND`, `OR`
  //     - Example:
  //        - `sleep.interval.civil_end_time >= "2023-11-24" AND
  //        sleep.interval.civil_end_time < "2023-11-25"`
  //
  //
  // Data points in the response will be ordered by the interval start time in
  // descending order.
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Response containing raw data points matching the query
message ListDataPointsResponse {
  // Data points matching the query
  repeated DataPoint data_points = 1;

  // Next page token, empty if the response is complete
  string next_page_token = 2;
}

// Request to create an identifiable data point.
message CreateDataPointRequest {
  // Required. The parent resource name where the data point will be created.
  // Format: `users/{user}/dataTypes/{data_type}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "health.googleapis.com/DataPoint"
    }
  ];

  // Required. The data point to create.
  DataPoint data_point = 2 [(google.api.field_behavior) = REQUIRED];
}

// Metadata for a create data point operation.
message CreateDataPointOperationMetadata {}

// Request to update an identifiable data point.
message UpdateDataPointRequest {
  // Required. The data point to update
  //
  // The data point's `name` field is used to identify the data point to update.
  //
  // Format: `users/{user}/dataTypes/{data_type}/dataPoints/{data_point}`
  DataPoint data_point = 1 [(google.api.field_behavior) = REQUIRED];
}

// Metadata for an update data point operation.
message UpdateDataPointOperationMetadata {}

// Request to delete a batch of identifiable data points.
message BatchDeleteDataPointsRequest {
  // Optional. Parent (data type) for the Data Point collection
  // Format: `users/me/dataTypes/{data_type}`, e.g.:
  //
  // - `users/me/dataTypes/steps`
  // - `users/me/dataTypes/-`
  //
  // For a list of the supported data types see the
  // [DataPoint
  // data][google.devicesandservices.health.v4.DataPoint] union
  // field.
  //
  // Deleting data points across multiple data type collections is supported
  // following https://aip.dev/159.
  //
  // If this is set, the parent of all of the data points specified in `names`
  // must match this field.
  string parent = 1 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.resource_reference) = { type: "health.googleapis.com/DataType" }
  ];

  // Required. The names of the DataPoints to delete.
  // A maximum of 10000 data points can be deleted in a single request.
  repeated string names = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "health.googleapis.com/DataPoint"
    }
  ];
}

// Response containing the list of possibly soft-deleted DataPoints.
message BatchDeleteDataPointsResponse {
  // The list of soft-deleted DataPoints, if the data type supports only soft
  // deletion.
  repeated DataPoint data_points = 1;
}

// Metadata for a batch delete data points operation.
message BatchDeleteDataPointsOperationMetadata {
  // The key in this map is the index of the request in the `requests` field in
  // the batch request.
  map<int32, google.rpc.Status> failed_requests = 1;
}

// Request to reconcile data points from multiple data sources.
message ReconcileDataPointsRequest {
  // Required. Parent data type of the Data Point collection.
  //
  // Format: `users/me/dataTypes/{data_type}`, e.g.:
  //
  // - `users/me/dataTypes/steps`
  // - `users/me/dataTypes/heart-rate`
  //
  // For a list of the supported data types see the
  // [DataPoint
  // data][google.devicesandservices.health.v4.DataPoint] union
  // field.
  string parent = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. The maximum number of data points to return.
  // If unspecified, at most 1440 data points will be returned.
  // The maximum page size is 10000; values above that will be truncated
  // accordingly.
  // For `exercise` and `sleep` the default page size is 25.
  // The maximum page size for `exercise` and `sleep` is 25.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The `next_page_token` from a previous request, if any.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Filter expression based on https://aip.dev/160.
  //
  // A time range, either physical or civil, can be specified.
  // See the
  // [ListDataPointsRequest.filter][google.devicesandservices.health.v4.ListDataPointsRequest.filter]
  // for the supported fields and syntax.
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The data source family name to reconcile.
  //
  // If empty, data points from all data sources will be reconciled.
  //
  // Format: `users/me/dataSourceFamilies/{data_source_family}`
  //
  // The supported values are:
  //
  // - `users/me/dataSourceFamilies/all-sources` - default value
  // - `users/me/dataSourceFamilies/google-wearables` - tracker devices
  // - `users/me/dataSourceFamilies/google-sources` - Google first party
  //   sources
  string data_source_family = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Response containing the list of reconciled DataPoints.
message ReconcileDataPointsResponse {
  // Data points matching the query
  repeated ReconciledDataPoint data_points = 1;

  // Next page token, empty if the response is complete
  string next_page_token = 2;
}

// Request to roll up data points by physical time intervals.
message RollUpDataPointsRequest {
  // Required. Parent data type of the Data Point collection.
  //
  // Format: `users/{user}/dataTypes/{data_type}`, e.g.:
  //
  // - `users/me/dataTypes/steps`
  // - `users/me/dataTypes/distance`
  //
  // For a list of the supported data types see the [RollupDataPoint
  // value][google.devicesandservices.health.v4.RollupDataPoint]
  // union field.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "health.googleapis.com/DataType" }
  ];

  // Required. Closed-open range of data points that will be rolled up.
  // The maximum range for `calories-in-heart-rate-zone`, `heart-rate`,
  // `active-minutes` and `total-calories` is 14 days.
  // The maximum range for all other data types is 90 days.
  google.type.Interval range = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The size of the time window to group data points into before
  // applying the aggregation functions.
  google.protobuf.Duration window_size = 3
      [(google.api.field_behavior) = REQUIRED];

  // Optional. The maximum number of data points to return.
  // If unspecified, at most 1440 data points will be returned.
  // The maximum page size is 10000; values above that will be truncated
  // accordingly.
  int32 page_size = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The next_page_token from a previous request, if any.
  // All other request fields need to be the same as in the initial request
  // when the page token is specified.
  string page_token = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The data source family name to roll up.
  //
  // If empty, data points from all available data sources will be rolled up.
  //
  // Format: `users/me/dataSourceFamilies/{data_source_family}`
  //
  // The supported values are:
  //
  // - `users/me/dataSourceFamilies/all-sources` - default value
  // - `users/me/dataSourceFamilies/google-wearables` - tracker devices
  // - `users/me/dataSourceFamilies/google-sources` - Google first party
  //   sources
  string data_source_family = 7 [(google.api.field_behavior) = OPTIONAL];
}

// Response containing the list of rolled up data points.
message RollUpDataPointsResponse {
  // Values for each aggregation time window.
  repeated RollupDataPoint rollup_data_points = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Request to roll up data points by civil time intervals.
message DailyRollUpDataPointsRequest {
  // Required. Parent data type of the Data Point collection.
  //
  // Format: `users/{user}/dataTypes/{data_type}`, e.g.:
  //
  // - `users/me/dataTypes/steps`
  // - `users/me/dataTypes/distance`
  //
  // For a list of the supported data types see the [DailyRollupDataPoint
  // value][google.devicesandservices.health.v4.DailyRollupDataPoint]
  // union field.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "health.googleapis.com/DataType" }
  ];

  // Required. Closed-open range of data points that will be rolled up.
  // The start time must be aligned with the aggregation window.
  // The maximum range for `calories-in-heart-rate-zone`, `heart-rate`,
  // `active-minutes` and `total-calories` is 14 days.
  // The maximum range for all other data types is 90 days.
  CivilTimeInterval range = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. Aggregation window size, in number of days. Defaults to 1 if not
  // specified.
  int32 window_size_days = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The maximum number of data points to return.
  // If unspecified, at most 1440 data points will be returned.
  // The maximum page size is 10000; values above that will be truncated
  // accordingly.
  int32 page_size = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The `next_page_token` from a previous request, if any.
  // All other request fields need to be the same as in the initial request
  // when the page token is specified.
  string page_token = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The data source family name to roll up.
  // If empty, data points from all available data sources will be rolled up.
  //
  // Format: `users/me/dataSourceFamilies/{data_source_family}`
  //
  // The supported values are:
  //
  // - `users/me/dataSourceFamilies/all-sources` - default value
  // - `users/me/dataSourceFamilies/google-wearables` - tracker devices
  // - `users/me/dataSourceFamilies/google-sources` - Google first party
  //   sources
  string data_source_family = 7 [(google.api.field_behavior) = OPTIONAL];
}

// Response containing the list of rolled up data points.
message DailyRollUpDataPointsResponse {
  // Values for each aggregation time window.
  repeated DailyRollupDataPoint rollup_data_points = 1;
}

// Represents a type of health data a user can have data points recorded for.
// It matches the parent resource of collection containing data points of the
// given type.
//
// Clients currently do not need to interact with this resource directly.
message DataType {
  option (google.api.resource) = {
    type: "health.googleapis.com/DataType"
    pattern: "users/{user}/dataTypes/{data_type}"
    plural: "dataTypes"
    singular: "dataType"
  };

  // Identifier. The resource name of the data type.
  //
  // Format: `users/{user}/dataTypes/{data_type}`
  //
  // See
  // [DataPoint.name][google.devicesandservices.health.v4.DataPoint.name]
  // for examples and possible values.
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
}

// Represents a request to export exercise data in TCX format.
message ExportExerciseTcxRequest {
  // Required. The resource name of the exercise data point to export.
  //
  // Format: `users/{user}/dataTypes/exercise/dataPoints/{data_point}`
  // Example: `users/me/dataTypes/exercise/dataPoints/2026443605080188808`
  //
  // The `{user}` is the alias `"me"` currently. Future versions may support
  // user IDs.
  // The `{data_point}` ID maps to the exercise ID, which is a long integer.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "health.googleapis.com/DataPoint"
    }
  ];

  // Optional. Indicates whether to include the TCX data points when the GPS
  // data is not available. If not specified, defaults to `false` and partial
  // data will not be included.
  bool partial_data = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Represents a Response for exporting exercise data in TCX format.
message ExportExerciseTcxResponse {
  // Contains the exported TCX data.
  //
  // This field is intended for gRPC clients, as media download integration
  // is not supported for gRPC. HTTP clients should instead use the `alt=media`
  // query parameter to download the raw binary TCX file.
  string tcx_data = 2;
}
