Skip to content

API Reference

Health sleep module for managing user sleep data.

This module provides CRUD operations and data models for user sleep tracking including sleep duration, stages, quality metrics, heart rate, SpO2, and sleep scoring.

Exports
  • CRUD: get_health_sleep_number, get_all_health_sleep_by_user_id, get_health_sleep_by_id_and_user_id, get_health_sleep_with_pagination, get_health_sleep_by_date, create_health_sleep, edit_health_sleep, delete_health_sleep
  • Schemas: HealthSleepBase, HealthSleepCreate, HealthSleepUpdate, HealthSleepRead, HealthSleepListResponse, HealthSleepStage
  • Enums: Source, SleepStageType, HRVStatus, SleepScore
  • Models: HealthSleep (ORM model)

HRVStatus

Bases: Enum

Enum representing the Heart Rate Variability (HRV) status classification.

Attributes:

Name Type Description
BALANCED

Indicates healthy HRV levels with good cardiovascular autonomic balance.

UNBALANCED

Indicates HRV levels showing some autonomic imbalance or stress.

LOW

Indicates HRV levels that are lower than optimal, suggesting fatigue or overtraining.

POOR

Indicates critically low HRV levels, suggesting significant stress, illness, or recovery issues.

Source code in backend/app/health/health_sleep/schema.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class HRVStatus(Enum):
    """
    Enum representing the Heart Rate Variability (HRV) status classification.

    Attributes:
        BALANCED: Indicates healthy HRV levels with good cardiovascular autonomic balance.
        UNBALANCED: Indicates HRV levels showing some autonomic imbalance or stress.
        LOW: Indicates HRV levels that are lower than optimal, suggesting fatigue or overtraining.
        POOR: Indicates critically low HRV levels, suggesting significant stress, illness, or recovery issues.
    """

    BALANCED = "BALANCED"
    UNBALANCED = "UNBALANCED"
    LOW = "LOW"
    POOR = "POOR"

HealthSleepBase

Bases: BaseModel

Pydantic model representing the base schema for health sleep data.

This model defines the structure and validation rules for sleep-related health metrics, including sleep duration, quality scores, heart rate variability, oxygen saturation, respiration rates, and sleep stages.

Attributes:

Name Type Description
date date | None

Calendar date of the sleep session.

sleep_start_time_gmt datetime | None

Start time of sleep in GMT.

sleep_end_time_gmt datetime | None

End time of sleep in GMT.

sleep_start_time_local datetime | None

Start time of sleep in local time.

sleep_end_time_local datetime | None

End time of sleep in local time.

total_sleep_seconds StrictInt | None

Total duration of sleep in seconds (>= 0).

nap_time_seconds StrictInt | None

Duration of naps in seconds (>= 0).

unmeasurable_sleep_seconds StrictInt | None

Unmeasurable sleep duration in seconds (>= 0).

deep_sleep_seconds StrictInt | None

Duration of deep sleep in seconds (>= 0).

light_sleep_seconds StrictInt | None

Duration of light sleep in seconds (>= 0).

rem_sleep_seconds StrictInt | None

Duration of REM sleep in seconds (>= 0).

awake_sleep_seconds StrictInt | None

Duration of awake time in seconds (>= 0).

avg_heart_rate StrictInt | None

Average heart rate during sleep (20-220 bpm).

min_heart_rate StrictInt | None

Minimum heart rate during sleep (20-220 bpm).

max_heart_rate StrictInt | None

Maximum heart rate during sleep (20-220 bpm).

avg_spo2 StrictInt | None

Average SpO2 oxygen saturation percentage (70-100%).

lowest_spo2 StrictInt | None

Lowest SpO2 reading during sleep (70-100%).

highest_spo2 StrictInt | None

Highest SpO2 reading during sleep (70-100%).

avg_respiration StrictInt | None

Average respiration rate (>= 0).

lowest_respiration StrictInt | None

Lowest respiration rate (>= 0).

highest_respiration StrictInt | None

Highest respiration rate (>= 0).

avg_stress_level StrictInt | None

Average stress level (0-100).

awake_count StrictInt | None

Number of times awake during sleep (>= 0).

restless_moments_count StrictInt | None

Number of restless moments during sleep (>= 0).

sleep_score_overall StrictInt | None

Overall sleep score (0-100).

sleep_score_duration SleepScore | None

Sleep duration score.

sleep_score_quality SleepScore | None

Sleep quality score.

garminconnect_sleep_id StrictStr | None

Garmin Connect sleep record ID.

sleep_stages list[SleepStage] | None

List of sleep stages.

source Source | None

Source of the sleep data.

hrv_status HRVStatus | None

Heart rate variability status.

resting_heart_rate StrictInt | None

Resting heart rate (20-220 bpm).

avg_skin_temp_deviation StrictFloat | None

Average skin temperature deviation.

awake_count_score SleepScore | None

Awake count score.

rem_percentage_score SleepScore | None

REM percentage score.

deep_percentage_score SleepScore | None

Deep sleep percentage score.

light_percentage_score SleepScore | None

Light sleep percentage score.

avg_sleep_stress StrictInt | None

Average sleep stress (0-100).

sleep_stress_score SleepScore | None

Sleep stress score.

Model Configuration
  • Allows population from ORM attributes
  • Forbids extra fields
  • Validates on assignment
  • Uses enum values in serialization
Validators

validate_sleep_times: Ensures sleep start time is before sleep end time for both GMT and local time zones.

Source code in backend/app/health/health_sleep/schema.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
class HealthSleepBase(BaseModel):
    """
    Pydantic model representing the base schema for health sleep data.

    This model defines the structure and validation rules for sleep-related health metrics,
    including sleep duration, quality scores, heart rate variability, oxygen saturation,
    respiration rates, and sleep stages.

    Attributes:
        date (datetime_date | None): Calendar date of the sleep session.
        sleep_start_time_gmt (datetime | None): Start time of sleep in GMT.
        sleep_end_time_gmt (datetime | None): End time of sleep in GMT.
        sleep_start_time_local (datetime | None): Start time of sleep in local time.
        sleep_end_time_local (datetime | None): End time of sleep in local time.
        total_sleep_seconds (StrictInt | None): Total duration of sleep in seconds (>= 0).
        nap_time_seconds (StrictInt | None): Duration of naps in seconds (>= 0).
        unmeasurable_sleep_seconds (StrictInt | None): Unmeasurable sleep duration in seconds (>= 0).
        deep_sleep_seconds (StrictInt | None): Duration of deep sleep in seconds (>= 0).
        light_sleep_seconds (StrictInt | None): Duration of light sleep in seconds (>= 0).
        rem_sleep_seconds (StrictInt | None): Duration of REM sleep in seconds (>= 0).
        awake_sleep_seconds (StrictInt | None): Duration of awake time in seconds (>= 0).
        avg_heart_rate (StrictInt | None): Average heart rate during sleep (20-220 bpm).
        min_heart_rate (StrictInt | None): Minimum heart rate during sleep (20-220 bpm).
        max_heart_rate (StrictInt | None): Maximum heart rate during sleep (20-220 bpm).
        avg_spo2 (StrictInt | None): Average SpO2 oxygen saturation percentage (70-100%).
        lowest_spo2 (StrictInt | None): Lowest SpO2 reading during sleep (70-100%).
        highest_spo2 (StrictInt | None): Highest SpO2 reading during sleep (70-100%).
        avg_respiration (StrictInt | None): Average respiration rate (>= 0).
        lowest_respiration (StrictInt | None): Lowest respiration rate (>= 0).
        highest_respiration (StrictInt | None): Highest respiration rate (>= 0).
        avg_stress_level (StrictInt | None): Average stress level (0-100).
        awake_count (StrictInt | None): Number of times awake during sleep (>= 0).
        restless_moments_count (StrictInt | None): Number of restless moments during sleep (>= 0).
        sleep_score_overall (StrictInt | None): Overall sleep score (0-100).
        sleep_score_duration (SleepScore | None): Sleep duration score.
        sleep_score_quality (SleepScore | None): Sleep quality score.
        garminconnect_sleep_id (StrictStr | None): Garmin Connect sleep record ID.
        sleep_stages (list[SleepStage] | None): List of sleep stages.
        source (Source | None): Source of the sleep data.
        hrv_status (HRVStatus | None): Heart rate variability status.
        resting_heart_rate (StrictInt | None): Resting heart rate (20-220 bpm).
        avg_skin_temp_deviation (StrictFloat | None): Average skin temperature deviation.
        awake_count_score (SleepScore | None): Awake count score.
        rem_percentage_score (SleepScore | None): REM percentage score.
        deep_percentage_score (SleepScore | None): Deep sleep percentage score.
        light_percentage_score (SleepScore | None): Light sleep percentage score.
        avg_sleep_stress (StrictInt | None): Average sleep stress (0-100).
        sleep_stress_score (SleepScore | None): Sleep stress score.

    Model Configuration:
        - Allows population from ORM attributes
        - Forbids extra fields
        - Validates on assignment
        - Uses enum values in serialization

    Validators:
        validate_sleep_times: Ensures sleep start time is before sleep end time
                             for both GMT and local time zones.
    """

    date: datetime_date | None = Field(
        default=None, description="Calendar date of the sleep session"
    )
    sleep_start_time_gmt: datetime | None = Field(
        default=None, description="Start time of sleep in GMT"
    )
    sleep_end_time_gmt: datetime | None = Field(
        default=None, description="End time of sleep in GMT"
    )
    sleep_start_time_local: datetime | None = Field(
        default=None, description="Start time of sleep in local time"
    )
    sleep_end_time_local: datetime | None = Field(
        default=None, description="End time of sleep in local time"
    )
    total_sleep_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Total duration of sleep in seconds"
    )
    nap_time_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Duration of naps in seconds"
    )
    unmeasurable_sleep_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Unmeasurable sleep duration in seconds"
    )
    deep_sleep_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Duration of deep sleep in seconds"
    )
    light_sleep_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Duration of light sleep in seconds"
    )
    rem_sleep_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Duration of REM sleep in seconds"
    )
    awake_sleep_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Duration of awake time in seconds"
    )
    avg_heart_rate: StrictInt | None = Field(
        default=None, ge=20, le=220, description="Average heart rate during sleep"
    )
    min_heart_rate: StrictInt | None = Field(
        default=None, ge=20, le=220, description="Minimum heart rate during sleep"
    )
    max_heart_rate: StrictInt | None = Field(
        default=None, ge=20, le=220, description="Maximum heart rate during sleep"
    )
    avg_spo2: StrictInt | None = Field(
        default=None,
        ge=70,
        le=100,
        description="Average SpO2 oxygen saturation percentage",
    )
    lowest_spo2: StrictInt | None = Field(
        default=None, ge=70, le=100, description="Lowest SpO2 reading during sleep"
    )
    highest_spo2: StrictInt | None = Field(
        default=None, ge=70, le=100, description="Highest SpO2 reading during sleep"
    )
    avg_respiration: StrictInt | None = Field(
        default=None, ge=0, description="Average respiration rate"
    )
    lowest_respiration: StrictInt | None = Field(
        default=None, ge=0, description="Lowest respiration rate"
    )
    highest_respiration: StrictInt | None = Field(
        default=None, ge=0, description="Highest respiration rate"
    )
    avg_stress_level: StrictInt | None = Field(
        default=None, ge=0, le=100, description="Average stress level"
    )
    awake_count: StrictInt | None = Field(
        default=None, ge=0, description="Number of times awake during sleep"
    )
    restless_moments_count: StrictInt | None = Field(
        default=None, ge=0, description="Number of restless moments during sleep"
    )
    sleep_score_overall: StrictInt | None = Field(
        default=None, ge=0, le=100, description="Overall sleep score (0-100)"
    )
    sleep_score_duration: SleepScore | None = Field(
        default=None, description="Sleep duration score"
    )
    sleep_score_quality: SleepScore | None = Field(
        default=None, description="Sleep quality score"
    )
    garminconnect_sleep_id: StrictStr | None = Field(
        default=None, min_length=1, description="Garmin Connect sleep record ID"
    )
    sleep_stages: list[HealthSleepStage] | None = Field(
        default=None, description="List of sleep stages"
    )
    source: Source | None = Field(default=None, description="Source of the sleep data")
    hrv_status: HRVStatus | None = Field(
        default=None, description="Heart rate variability status"
    )
    resting_heart_rate: StrictInt | None = Field(
        default=None, ge=20, le=220, description="Resting heart rate"
    )
    avg_skin_temp_deviation: StrictFloat | None = Field(
        default=None, description="Average skin temperature deviation"
    )
    awake_count_score: SleepScore | None = Field(
        default=None, description="Awake count score"
    )
    rem_percentage_score: SleepScore | None = Field(
        default=None, description="REM percentage score"
    )
    deep_percentage_score: SleepScore | None = Field(
        default=None, description="Deep sleep percentage score"
    )
    light_percentage_score: SleepScore | None = Field(
        default=None, description="Light sleep percentage score"
    )
    avg_sleep_stress: StrictInt | None = Field(
        default=None, ge=0, le=100, description="Average sleep stress"
    )
    sleep_stress_score: SleepScore | None = Field(
        default=None, description="Sleep stress score"
    )

    model_config = ConfigDict(
        from_attributes=True,
        extra="forbid",
        validate_assignment=True,
        use_enum_values=True,
    )

    @model_validator(mode="after")
    def validate_sleep_times(self) -> "HealthSleepBase":
        """Validate sleep start < end."""
        # Validate sleep start < sleep end (GMT)
        if (
            self.sleep_start_time_gmt is not None
            and self.sleep_end_time_gmt is not None
        ):
            if self.sleep_start_time_gmt >= self.sleep_end_time_gmt:
                raise ValueError("Sleep start time must be before sleep end time")

        # Validate sleep start < sleep end (Local)
        if (
            self.sleep_start_time_local is not None
            and self.sleep_end_time_local is not None
        ):
            if self.sleep_start_time_local >= self.sleep_end_time_local:
                raise ValueError(
                    "Sleep start time (local) must be before sleep end time (local)"
                )

        return self

validate_sleep_times

validate_sleep_times()

Validate sleep start < end.

Source code in backend/app/health/health_sleep/schema.py
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
@model_validator(mode="after")
def validate_sleep_times(self) -> "HealthSleepBase":
    """Validate sleep start < end."""
    # Validate sleep start < sleep end (GMT)
    if (
        self.sleep_start_time_gmt is not None
        and self.sleep_end_time_gmt is not None
    ):
        if self.sleep_start_time_gmt >= self.sleep_end_time_gmt:
            raise ValueError("Sleep start time must be before sleep end time")

    # Validate sleep start < sleep end (Local)
    if (
        self.sleep_start_time_local is not None
        and self.sleep_end_time_local is not None
    ):
        if self.sleep_start_time_local >= self.sleep_end_time_local:
            raise ValueError(
                "Sleep start time (local) must be before sleep end time (local)"
            )

    return self

HealthSleepCreate

Bases: HealthSleepBase

Validator for HealthSleepCreate model that automatically sets the date field.

This validator runs after model initialization to ensure that if no date is provided, it defaults to today's date.

Source code in backend/app/health/health_sleep/schema.py
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
class HealthSleepCreate(HealthSleepBase):
    """
    Validator for HealthSleepCreate model that automatically sets the date field.

    This validator runs after model initialization to ensure that if no date
    is provided, it defaults to today's date.
    """

    @model_validator(mode="after")
    def set_default_date(self) -> "HealthSleepCreate":
        """
        Set date to today if not provided.

        Returns:
            The validated model instance with date set.
        """
        if self.date is None:
            self.date = datetime_date.today()
        return self

set_default_date

set_default_date()

Set date to today if not provided.

Returns:

Type Description
HealthSleepCreate

The validated model instance with date set.

Source code in backend/app/health/health_sleep/schema.py
329
330
331
332
333
334
335
336
337
338
339
@model_validator(mode="after")
def set_default_date(self) -> "HealthSleepCreate":
    """
    Set date to today if not provided.

    Returns:
        The validated model instance with date set.
    """
    if self.date is None:
        self.date = datetime_date.today()
    return self

HealthSleepListResponse

Bases: BaseModel

Response model for paginated health sleep records.

This model represents the paginated response structure for retrieving a user's sleep records. It includes pagination metadata and a list of individual sleep record details.

Attributes:

Name Type Description
total StrictInt

Total number of sleep records available for the user.

num_records StrictInt | None

Number of records included in this response page.

page_number StrictInt | None

Current page number of the paginated results.

records list[HealthSleepRead]

List of health sleep record objects for the current page.

Source code in backend/app/health/health_sleep/schema.py
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
class HealthSleepListResponse(BaseModel):
    """
    Response model for paginated health sleep records.

    This model represents the paginated response structure for retrieving a user's sleep records.
    It includes pagination metadata and a list of individual sleep record details.

    Attributes:
        total (StrictInt): Total number of sleep records available for the user.
        num_records (StrictInt | None): Number of records included in this response page.
        page_number (StrictInt | None): Current page number of the paginated results.
        records (list[HealthSleepRead]): List of health sleep record objects for the current page.
    """

    total: StrictInt = Field(
        ..., description="Total number of sleep records for the user"
    )
    num_records: StrictInt | None = Field(
        default=None, description="Number of records in this response"
    )
    page_number: StrictInt | None = Field(
        default=None, description="Current page number"
    )
    records: list[HealthSleepRead] = Field(
        ..., description="List of health sleep records"
    )

    model_config = ConfigDict(
        from_attributes=True,
        extra="forbid",
        validate_assignment=True,
    )

HealthSleepModel

Bases: Base

User sleep tracking data with metrics and quality scores.

Attributes:

Name Type Description
id Mapped[int]

Primary key.

user_id Mapped[int]

Foreign key to users table.

date Mapped[date]

Calendar date of sleep session.

sleep_start_time_gmt Mapped[datetime | None]

Sleep start in GMT.

sleep_end_time_gmt Mapped[datetime | None]

Sleep end in GMT.

sleep_start_time_local Mapped[datetime | None]

Sleep start in local time.

sleep_end_time_local Mapped[datetime | None]

Sleep end in local time.

total_sleep_seconds Mapped[int | None]

Total sleep duration.

nap_time_seconds Mapped[int | None]

Nap duration.

unmeasurable_sleep_seconds Mapped[int | None]

Unmeasurable sleep.

deep_sleep_seconds Mapped[int | None]

Deep sleep duration.

light_sleep_seconds Mapped[int | None]

Light sleep duration.

rem_sleep_seconds Mapped[int | None]

REM sleep duration.

awake_sleep_seconds Mapped[int | None]

Awake time during sleep.

avg_heart_rate Mapped[int | None]

Average heart rate.

min_heart_rate Mapped[int | None]

Minimum heart rate.

max_heart_rate Mapped[int | None]

Maximum heart rate.

avg_spo2 Mapped[int | None]

Average SpO2 percentage.

lowest_spo2 Mapped[int | None]

Lowest SpO2 reading.

highest_spo2 Mapped[int | None]

Highest SpO2 reading.

avg_respiration Mapped[int | None]

Average respiration rate.

lowest_respiration Mapped[int | None]

Lowest respiration.

highest_respiration Mapped[int | None]

Highest respiration.

avg_stress_level Mapped[int | None]

Average stress level.

awake_count Mapped[int | None]

Times awakened.

restless_moments_count Mapped[int | None]

Restless moments.

sleep_score_overall Mapped[int | None]

Overall score (0-100).

sleep_score_duration Mapped[str | None]

Duration score label.

sleep_score_quality Mapped[str | None]

Quality score label.

garminconnect_sleep_id Mapped[str | None]

Garmin Connect ID.

sleep_stages Mapped[dict | None]

Sleep stage intervals (JSON).

source Mapped[str | None]

Data source.

hrv_status Mapped[str | None]

HRV status.

resting_heart_rate Mapped[int | None]

Resting heart rate.

avg_skin_temp_deviation Mapped[Decimal | None]

Skin temp deviation.

awake_count_score Mapped[str | None]

Awake count score.

rem_percentage_score Mapped[str | None]

REM percentage score.

deep_percentage_score Mapped[str | None]

Deep percentage score.

light_percentage_score Mapped[str | None]

Light percentage score.

avg_sleep_stress Mapped[int | None]

Average sleep stress.

sleep_stress_score Mapped[str | None]

Sleep stress score.

user Mapped[str | None]

Relationship to Users model.

Source code in backend/app/health/health_sleep/models.py
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
class HealthSleep(Base):
    """
    User sleep tracking data with metrics and quality scores.

    Attributes:
        id: Primary key.
        user_id: Foreign key to users table.
        date: Calendar date of sleep session.
        sleep_start_time_gmt: Sleep start in GMT.
        sleep_end_time_gmt: Sleep end in GMT.
        sleep_start_time_local: Sleep start in local time.
        sleep_end_time_local: Sleep end in local time.
        total_sleep_seconds: Total sleep duration.
        nap_time_seconds: Nap duration.
        unmeasurable_sleep_seconds: Unmeasurable sleep.
        deep_sleep_seconds: Deep sleep duration.
        light_sleep_seconds: Light sleep duration.
        rem_sleep_seconds: REM sleep duration.
        awake_sleep_seconds: Awake time during sleep.
        avg_heart_rate: Average heart rate.
        min_heart_rate: Minimum heart rate.
        max_heart_rate: Maximum heart rate.
        avg_spo2: Average SpO2 percentage.
        lowest_spo2: Lowest SpO2 reading.
        highest_spo2: Highest SpO2 reading.
        avg_respiration: Average respiration rate.
        lowest_respiration: Lowest respiration.
        highest_respiration: Highest respiration.
        avg_stress_level: Average stress level.
        awake_count: Times awakened.
        restless_moments_count: Restless moments.
        sleep_score_overall: Overall score (0-100).
        sleep_score_duration: Duration score label.
        sleep_score_quality: Quality score label.
        garminconnect_sleep_id: Garmin Connect ID.
        sleep_stages: Sleep stage intervals (JSON).
        source: Data source.
        hrv_status: HRV status.
        resting_heart_rate: Resting heart rate.
        avg_skin_temp_deviation: Skin temp deviation.
        awake_count_score: Awake count score.
        rem_percentage_score: REM percentage score.
        deep_percentage_score: Deep percentage score.
        light_percentage_score: Light percentage score.
        avg_sleep_stress: Average sleep stress.
        sleep_stress_score: Sleep stress score.
        user: Relationship to Users model.
    """

    __tablename__ = "health_sleep"

    id: Mapped[int] = mapped_column(
        primary_key=True,
        autoincrement=True,
    )
    user_id: Mapped[int] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        comment="User ID that the health_sleep belongs",
    )
    date: Mapped[date_type] = mapped_column(
        nullable=False,
        index=True,
        comment="Calendar date of the sleep session",
    )
    sleep_start_time_gmt: Mapped[datetime | None] = mapped_column(
        nullable=True,
        comment="Start time of sleep in GMT",
    )
    sleep_end_time_gmt: Mapped[datetime | None] = mapped_column(
        nullable=True,
        comment="End time of sleep in GMT",
    )
    sleep_start_time_local: Mapped[datetime | None] = mapped_column(
        nullable=True,
        comment="Start time of sleep in local time",
    )
    sleep_end_time_local: Mapped[datetime | None] = mapped_column(
        nullable=True,
        comment="End time of sleep in local time",
    )
    total_sleep_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Total duration of sleep in seconds",
    )
    nap_time_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Duration of naps in seconds",
    )
    unmeasurable_sleep_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Unmeasurable sleep duration in seconds",
    )
    deep_sleep_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Duration of deep sleep in seconds",
    )
    light_sleep_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Duration of light sleep in seconds",
    )
    rem_sleep_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Duration of REM sleep in seconds",
    )
    awake_sleep_seconds: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Duration of awake time in seconds",
    )
    avg_heart_rate: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Average heart rate during sleep",
    )
    min_heart_rate: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Minimum heart rate during sleep",
    )
    max_heart_rate: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Maximum heart rate during sleep",
    )
    avg_spo2: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Average SpO2 oxygen saturation percentage",
    )
    lowest_spo2: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Lowest SpO2 reading during sleep",
    )
    highest_spo2: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Highest SpO2 reading during sleep",
    )
    avg_respiration: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Average respiration rate",
    )
    lowest_respiration: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Lowest respiration rate",
    )
    highest_respiration: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Highest respiration rate",
    )
    avg_stress_level: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Average stress level during sleep",
    )
    awake_count: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Number of times awakened during sleep",
    )
    restless_moments_count: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Count of restless moments",
    )
    sleep_score_overall: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Overall sleep score (0-100)",
    )
    sleep_score_duration: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Sleep duration score (e.g., GOOD, EXCELLENT, POOR)",
    )
    sleep_score_quality: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Sleep quality score",
    )
    garminconnect_sleep_id: Mapped[str | None] = mapped_column(
        String(250),
        nullable=True,
        comment="External Garmin Connect sleep ID",
    )
    sleep_stages: Mapped[dict | None] = mapped_column(
        JSON,
        nullable=True,
        comment="List of sleep stage intervals as JSON",
    )
    source: Mapped[str | None] = mapped_column(
        String(250),
        nullable=True,
        comment="Source of the health sleep data",
    )
    hrv_status: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Heart rate variability status",
    )
    resting_heart_rate: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Resting heart rate during sleep",
    )
    avg_skin_temp_deviation: Mapped[Decimal | None] = mapped_column(
        Numeric(precision=10, scale=2),
        nullable=True,
        comment="Average skin temperature deviation during sleep in Celsius",
    )
    awake_count_score: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Awake count score",
    )
    rem_percentage_score: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="REM sleep percentage score",
    )
    deep_percentage_score: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Deep sleep percentage score",
    )
    light_percentage_score: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Light sleep percentage score",
    )
    avg_sleep_stress: Mapped[int | None] = mapped_column(
        nullable=True,
        comment="Average sleep stress level",
    )
    sleep_stress_score: Mapped[str | None] = mapped_column(
        String(50),
        nullable=True,
        comment="Sleep stress score",
    )

    # Define a relationship to the Users model
    # TODO: Change to Mapped["User"] when all modules use mapped
    users = relationship("Users", back_populates="health_sleep")

HealthSleepRead

Bases: HealthSleepBase

Read schema for health sleep records.

Extends the base health sleep schema with an identifier field for retrieving or referencing existing sleep records in the database.

Attributes:

Name Type Description
user_id StrictInt

Foreign key reference to the user.

id StrictInt

Unique identifier for the sleep record to update or retrieve.

Source code in backend/app/health/health_sleep/schema.py
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
class HealthSleepRead(HealthSleepBase):
    """
    Read schema for health sleep records.

    Extends the base health sleep schema with an identifier field for retrieving
    or referencing existing sleep records in the database.

    Attributes:
        user_id (StrictInt): Foreign key reference to the user.
        id (StrictInt): Unique identifier for the sleep record to update or retrieve.
    """

    id: StrictInt = Field(
        ..., description="Unique identifier for the sleep record to update"
    )
    user_id: StrictInt = Field(..., description="Foreign key reference to the user")

HealthSleepStage

Bases: BaseModel

Represents a sleep stage with timing and duration information.

This model captures details about individual sleep stages within a sleep session, including the type of stage, when it occurred, and how long it lasted.

Attributes:

Name Type Description
stage_type SleepStageType | None

The classification of the sleep stage (e.g., light, deep, REM).

start_time_gmt datetime | None

The beginning timestamp of the sleep stage in GMT timezone.

end_time_gmt datetime | None

The ending timestamp of the sleep stage in GMT timezone.

duration_seconds StrictInt | None

The length of the sleep stage in seconds. Must be non-negative.

Source code in backend/app/health/health_sleep/schema.py
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
class HealthSleepStage(BaseModel):
    """
    Represents a sleep stage with timing and duration information.

    This model captures details about individual sleep stages within a sleep session,
    including the type of stage, when it occurred, and how long it lasted.

    Attributes:
        stage_type: The classification of the sleep stage (e.g., light, deep, REM).
        start_time_gmt: The beginning timestamp of the sleep stage in GMT timezone.
        end_time_gmt: The ending timestamp of the sleep stage in GMT timezone.
        duration_seconds: The length of the sleep stage in seconds. Must be non-negative.
    """

    stage_type: SleepStageType | None = Field(
        default=None, description="Type of sleep stage"
    )
    start_time_gmt: datetime | None = Field(
        default=None, description="Start time of the stage in GMT"
    )
    end_time_gmt: datetime | None = Field(
        default=None, description="End time of the stage in GMT"
    )
    duration_seconds: StrictInt | None = Field(
        default=None, ge=0, description="Duration of the stage in seconds"
    )

    model_config = ConfigDict(
        from_attributes=True,
        extra="forbid",
        validate_assignment=True,
        use_enum_values=True,
    )

HealthSleepUpdate

Bases: HealthSleepRead

Schema for updating health sleep records.

Inherits all fields from HealthSleepRead, allowing clients to update existing sleep data while maintaining consistency with the read schema.

Used in PUT/PATCH requests to modify sleep tracking information such as sleep duration, quality, and related health metrics.

Source code in backend/app/health/health_sleep/schema.py
360
361
362
363
364
365
366
367
368
369
class HealthSleepUpdate(HealthSleepRead):
    """
    Schema for updating health sleep records.

    Inherits all fields from HealthSleepRead, allowing clients to update
    existing sleep data while maintaining consistency with the read schema.

    Used in PUT/PATCH requests to modify sleep tracking information such as
    sleep duration, quality, and related health metrics.
    """

SleepScore

Bases: Enum

Enumeration of sleep quality score levels.

Attributes:

Name Type Description
EXCELLENT str

Represents excellent sleep quality.

GOOD str

Represents good sleep quality.

FAIR str

Represents fair sleep quality.

POOR str

Represents poor sleep quality.

Source code in backend/app/health/health_sleep/schema.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class SleepScore(Enum):
    """
    Enumeration of sleep quality score levels.

    Attributes:
        EXCELLENT (str): Represents excellent sleep quality.
        GOOD (str): Represents good sleep quality.
        FAIR (str): Represents fair sleep quality.
        POOR (str): Represents poor sleep quality.
    """

    EXCELLENT = "EXCELLENT"
    GOOD = "GOOD"
    FAIR = "FAIR"
    POOR = "POOR"

SleepStageType

Bases: Enum

Enum representing different stages of sleep.

Attributes:

Name Type Description
DEEP int

Deep sleep stage, value 0. Characterized by slow brain waves and muscle relaxation.

LIGHT int

Light sleep stage, value 1. Transitional sleep between wakefulness and deep sleep.

REM int

Rapid Eye Movement sleep stage, value 2. Associated with vivid dreams and mental activity.

AWAKE int

Awake state, value 3. The stage when the person is conscious and not sleeping.

Source code in backend/app/health/health_sleep/schema.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class SleepStageType(Enum):
    """
    Enum representing different stages of sleep.

    Attributes:
        DEEP (int): Deep sleep stage, value 0. Characterized by slow brain waves and muscle relaxation.
        LIGHT (int): Light sleep stage, value 1. Transitional sleep between wakefulness and deep sleep.
        REM (int): Rapid Eye Movement sleep stage, value 2. Associated with vivid dreams and mental activity.
        AWAKE (int): Awake state, value 3. The stage when the person is conscious and not sleeping.
    """

    DEEP = 0
    LIGHT = 1
    REM = 2
    AWAKE = 3

Source

Bases: Enum

Enum representing the source of sleep health data.

Attributes:

Name Type Description
GARMIN

Sleep data sourced from Garmin devices or services.

Source code in backend/app/health/health_sleep/schema.py
14
15
16
17
18
19
20
21
22
class Source(Enum):
    """
    Enum representing the source of sleep health data.

    Attributes:
        GARMIN: Sleep data sourced from Garmin devices or services.
    """

    GARMIN = "garmin"

create_health_sleep

create_health_sleep(user_id, health_sleep, db)

Create a new health sleep record for a user.

Parameters:

Name Type Description Default
user_id int

User ID for the sleep record.

required
health_sleep HealthSleepCreate

Health sleep data to create.

required
db Session

Database session.

required

Returns:

Type Description
HealthSleep

Created health sleep record with assigned ID.

Raises:

Type Description
HTTPException

409 if duplicate entry, 500 if database error.

Source code in backend/app/health/health_sleep/crud.py
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
@core_decorators.handle_db_errors
def create_health_sleep(
    user_id: int,
    health_sleep: health_sleep_schema.HealthSleepCreate,
    db: Session,
) -> health_sleep_models.HealthSleep:
    """
    Create a new health sleep record for a user.

    Args:
        user_id: User ID for the sleep record.
        health_sleep: Health sleep data to create.
        db: Database session.

    Returns:
        Created health sleep record with assigned ID.

    Raises:
        HTTPException: 409 if duplicate entry, 500 if database
            error.
    """
    try:
        # Create a new health_sleep
        db_health_sleep = health_sleep_models.HealthSleep(
            **health_sleep.model_dump(
                exclude_none=False,
                mode="json",
            ),
            user_id=user_id,
        )

        # Add the health_sleep to the database
        db.add(db_health_sleep)
        db.commit()
        db.refresh(db_health_sleep)

        # Return the created health_sleep model
        return db_health_sleep
    except IntegrityError as integrity_error:
        # Rollback the transaction
        db.rollback()

        # Raise an HTTPException with a 409 Conflict status code
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=(
                f"Duplicate entry error. Check if there is "
                f"already an entry created for {health_sleep.date}"
            ),
        ) from integrity_error

delete_health_sleep

delete_health_sleep(user_id, health_sleep_id, db)

Delete a health sleep record for a specific user.

Parameters:

Name Type Description Default
user_id int

User ID who owns the sleep record.

required
health_sleep_id int

Sleep record ID to delete.

required
db Session

Database session.

required

Returns:

Type Description
None

None

Raises:

Type Description
HTTPException

404 if not found, 500 if database error.

Source code in backend/app/health/health_sleep/crud.py
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
@core_decorators.handle_db_errors
def delete_health_sleep(user_id: int, health_sleep_id: int, db: Session) -> None:
    """
    Delete a health sleep record for a specific user.

    Args:
        user_id: User ID who owns the sleep record.
        health_sleep_id: Sleep record ID to delete.
        db: Database session.

    Returns:
        None

    Raises:
        HTTPException: 404 if not found, 500 if database error.
    """
    # Get the record to delete
    db_health_sleep = get_health_sleep_by_id_and_user_id(health_sleep_id, user_id, db)

    # Check if the health_sleep was found
    if db_health_sleep is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=(
                f"Health sleep with id {health_sleep_id} "
                f"for user {user_id} not found"
            ),
        )

    # Delete the record
    db.delete(db_health_sleep)
    db.commit()

edit_health_sleep

edit_health_sleep(user_id, health_sleep, db)

Edit an existing health sleep record for a user.

Parameters:

Name Type Description Default
user_id int

User ID whose sleep record is being edited.

required
health_sleep HealthSleepUpdate

Updated health sleep data.

required
db Session

Database session.

required

Returns:

Type Description
HealthSleep

Updated HealthSleep model.

Raises:

Type Description
HTTPException

403 if trying to edit other user record, 404 if not found, 500 if database error.

Source code in backend/app/health/health_sleep/crud.py
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
@core_decorators.handle_db_errors
def edit_health_sleep(
    user_id: int,
    health_sleep: health_sleep_schema.HealthSleepUpdate,
    db: Session,
) -> health_sleep_models.HealthSleep:
    """
    Edit an existing health sleep record for a user.

    Args:
        user_id: User ID whose sleep record is being edited.
        health_sleep: Updated health sleep data.
        db: Database session.

    Returns:
        Updated HealthSleep model.

    Raises:
        HTTPException: 403 if trying to edit other user record, 404 if not
            found, 500 if database error.
    """
    # Ensure the health_sleep belongs to the user
    if health_sleep.user_id != user_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Cannot edit health sleep for another user.",
        )

    # Get the health_sleep from the database
    db_health_sleep = get_health_sleep_by_id_and_user_id(health_sleep.id, user_id, db)

    if db_health_sleep is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Health sleep not found",
        )

    # Dictionary of the fields to update if they are not None
    health_sleep_data = health_sleep.model_dump(exclude_unset=True, mode="json")
    # Iterate over fields and update dynamically
    for key, value in health_sleep_data.items():
        setattr(db_health_sleep, key, value)

    # Commit the transaction
    db.commit()
    db.refresh(db_health_sleep)

    return db_health_sleep

get_all_health_sleep_by_user_id

get_all_health_sleep_by_user_id(user_id, db)

Retrieve all sleep health records for a user.

Parameters:

Name Type Description Default
user_id int

User ID to fetch records for.

required
db Session

Database session.

required

Returns:

Type Description
list[HealthSleep]

List of HealthSleep models ordered by date descending.

Raises:

Type Description
HTTPException

If database error occurs.

Source code in backend/app/health/health_sleep/crud.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@core_decorators.handle_db_errors
def get_all_health_sleep_by_user_id(
    user_id: int, db: Session
) -> list[health_sleep_models.HealthSleep]:
    """
    Retrieve all sleep health records for a user.

    Args:
        user_id: User ID to fetch records for.
        db: Database session.

    Returns:
        List of HealthSleep models ordered by date descending.

    Raises:
        HTTPException: If database error occurs.
    """
    # Get the health_sleep from the database
    stmt = (
        select(health_sleep_models.HealthSleep)
        .where(health_sleep_models.HealthSleep.user_id == user_id)
        .order_by(desc(health_sleep_models.HealthSleep.date))
    )
    return db.execute(stmt).scalars().all()

get_health_sleep_by_date

get_health_sleep_by_date(user_id, date, db)

Retrieve health sleep record for a user on a specific date.

Parameters:

Name Type Description Default
user_id int

User ID.

required
date str

Date string for the sleep record.

required
db Session

Database session.

required

Returns:

Type Description
HealthSleep | None

HealthSleep model if found, None otherwise.

Raises:

Type Description
HTTPException

If database error occurs.

Source code in backend/app/health/health_sleep/crud.py
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
@core_decorators.handle_db_errors
def get_health_sleep_by_date(
    user_id: int, date: str, db: Session
) -> health_sleep_models.HealthSleep | None:
    """
    Retrieve health sleep record for a user on a specific date.

    Args:
        user_id: User ID.
        date: Date string for the sleep record.
        db: Database session.

    Returns:
        HealthSleep model if found, None otherwise.

    Raises:
        HTTPException: If database error occurs.
    """
    # Get the health_sleep from the database
    stmt = select(health_sleep_models.HealthSleep).where(
        health_sleep_models.HealthSleep.date == func.date(date),
        health_sleep_models.HealthSleep.user_id == user_id,
    )
    return db.execute(stmt).scalar_one_or_none()

get_health_sleep_by_id_and_user_id

get_health_sleep_by_id_and_user_id(health_sleep_id, user_id, db)

Retrieve health sleep record by ID and user ID.

Parameters:

Name Type Description Default
health_sleep_id int

Health sleep record ID to fetch.

required
user_id int

User ID to fetch record for.

required
db Session

Database session.

required

Returns:

Type Description
HealthSleep | None

HealthSleep model if found, None otherwise.

Raises:

Type Description
HTTPException

If database error occurs.

Source code in backend/app/health/health_sleep/crud.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@core_decorators.handle_db_errors
def get_health_sleep_by_id_and_user_id(
    health_sleep_id: int, user_id: int, db: Session
) -> health_sleep_models.HealthSleep | None:
    """
    Retrieve health sleep record by ID and user ID.

    Args:
        health_sleep_id: Health sleep record ID to fetch.
        user_id: User ID to fetch record for.
        db: Database session.

    Returns:
        HealthSleep model if found, None otherwise.

    Raises:
        HTTPException: If database error occurs.
    """
    # Get the health_sleep from the database
    stmt = select(health_sleep_models.HealthSleep).where(
        health_sleep_models.HealthSleep.id == health_sleep_id,
        health_sleep_models.HealthSleep.user_id == user_id,
    )
    return db.execute(stmt).scalar_one_or_none()

get_health_sleep_number

get_health_sleep_number(user_id, db)

Retrieve total count of health sleep records for a user.

Parameters:

Name Type Description Default
user_id int

User ID to count records for.

required
db Session

Database session.

required

Returns:

Type Description
int

Total number of health sleep records.

Raises:

Type Description
HTTPException

If database error occurs.

Source code in backend/app/health/health_sleep/crud.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@core_decorators.handle_db_errors
def get_health_sleep_number(user_id: int, db: Session) -> int:
    """
    Retrieve total count of health sleep records for a user.

    Args:
        user_id: User ID to count records for.
        db: Database session.

    Returns:
        Total number of health sleep records.

    Raises:
        HTTPException: If database error occurs.
    """
    # Get the number of health_sleep from the database
    stmt = (
        select(func.count())
        .select_from(health_sleep_models.HealthSleep)
        .where(health_sleep_models.HealthSleep.user_id == user_id)
    )
    return db.execute(stmt).scalar_one()

get_health_sleep_with_pagination

get_health_sleep_with_pagination(user_id, db, page_number=1, num_records=5)

Retrieve paginated health sleep records for a user.

Parameters:

Name Type Description Default
user_id int

User ID to fetch records for.

required
db Session

Database session.

required
page_number int

Page number to retrieve (1-indexed).

1
num_records int

Number of records per page.

5

Returns:

Type Description
list[HealthSleep]

List of HealthSleep models for the requested page.

Raises:

Type Description
HTTPException

If database error occurs.

Source code in backend/app/health/health_sleep/crud.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
@core_decorators.handle_db_errors
def get_health_sleep_with_pagination(
    user_id: int,
    db: Session,
    page_number: int = 1,
    num_records: int = 5,
) -> list[health_sleep_models.HealthSleep]:
    """
    Retrieve paginated health sleep records for a user.

    Args:
        user_id: User ID to fetch records for.
        db: Database session.
        page_number: Page number to retrieve (1-indexed).
        num_records: Number of records per page.

    Returns:
        List of HealthSleep models for the requested page.

    Raises:
        HTTPException: If database error occurs.
    """
    # Get the health_sleep from the database
    stmt = (
        select(health_sleep_models.HealthSleep)
        .where(health_sleep_models.HealthSleep.user_id == user_id)
        .order_by(desc(health_sleep_models.HealthSleep.date))
        .offset((page_number - 1) * num_records)
        .limit(num_records)
    )
    return db.execute(stmt).scalars().all()