Women's health
Menstrual-cycle tracking and pregnancy. The write methods here are irreversible health-data writes with no delete endpoint — read the warning at the top of src/services/womensHealth.ts before calling one.
Every method below hangs off a Garmin instance. See Installation & setup for how to construct one:
import { GarminClient, Garmin, FileTokenStore } from "garminconnect-js";
const client = new GarminClient({ tokenStore: new FileTokenStore("./tokens") });
if (!(await client.loadTokens())) throw new Error("not connected to Garmin");
const garmin = new Garmin(client);
11 methods. The verification column says what has been
confirmed against a live Garmin account, not merely unit-tested —
AGENTS.md carries the full evidence per method.
| Method | Verified |
|---|---|
confirmMenstrualPeriodStart | live-verified |
getMenstrualCalendarData | live-verified |
getMenstrualCycleSummary | live-verified |
getMenstrualDataForDate | live-verified |
getMenstrualLastConfirmed | live-verified |
getMenstrualReports | live-verified |
getPregnancySummary | live-verified |
initMenstrualCycleSetup | live-verified |
updateMenstrualCalendar | live-verified |
updateMenstrualDailyLog | live-verified |
updateMenstrualSettings | live-verified |
confirmMenstrualPeriodStart
garmin.confirmMenstrualPeriodStart(periodStartDate: string | Date, periodLength: number, cycleLength: number, options?: {predictedCycle?: boolean}): Promise<unknown>
const result = await garmin.confirmMenstrualPeriodStart("2026-09-24", 1, 1);
Returns
unknown — Garmin's response is passed through unparsed. Cast it to whatever you need; this library does not model it.
POSTs /periodichealth-service/menstrualcycle/{periodStartDate} directly, NOT the dayview/calendar/lastconfirmed/summary sub-paths
Verification: live-verified
getMenstrualCalendarData
garmin.getMenstrualCalendarData(startdate: string | Date, enddate: string | Date): Promise<MenstrualCalendarData | null>
const result = await garmin.getMenstrualCalendarData("2026-09-24", "2026-09-24");
Returns
MenstrualCalendarData — an object whose fields this library does not model. Garmin's response is passed through unparsed, so read one to see what you get, or use a Record<string, unknown> and narrow it yourself.
passes through unchecked; Garmin rejects windows of 92+ inclusive days; not enforced here (caller's responsibility)
Verification: live-verified
getMenstrualCycleSummary
garmin.getMenstrualCycleSummary(fordate: string | Date): Promise<MenstrualCycleSummary | null>
const result = await garmin.getMenstrualCycleSummary("2026-09-24");
Returns
MenstrualCycleSummary — an object whose fields this library does not model. Garmin's response is passed through unparsed, so read one to see what you get, or use a Record<string, unknown> and narrow it yourself.
passes through unchecked
Verification: live-verified
getMenstrualDataForDate
garmin.getMenstrualDataForDate(fordate: string | Date): Promise<MenstrualDayView | null>
const result = await garmin.getMenstrualDataForDate("2026-09-24");
Returns
MenstrualDayView — an object whose fields this library does not model. Garmin's response is passed through unparsed, so read one to see what you get, or use a Record<string, unknown> and narrow it yourself.
passes through unchecked
Verification: live-verified
getMenstrualLastConfirmed
garmin.getMenstrualLastConfirmed(fordate: string | Date): Promise<MenstrualLastConfirmed | null>
const result = await garmin.getMenstrualLastConfirmed("2026-09-24");
Returns
MenstrualLastConfirmed — an object whose fields this library does not model. Garmin's response is passed through unparsed, so read one to see what you get, or use a Record<string, unknown> and narrow it yourself.
passes through unchecked
Verification: live-verified
getMenstrualReports
garmin.getMenstrualReports(fordate: string | Date, numberOfCycles?: number, options?: {nextReport?: boolean, reportType?: string, todayCalendarDate?: string | Date}): Promise<MenstrualReports | null>
const result = await garmin.getMenstrualReports("2026-09-24");
Returns
MenstrualReports — an object whose fields this library does not model. Garmin's response is passed through unparsed, so read one to see what you get, or use a Record<string, unknown> and narrow it yourself.
defaults numberOfCycles=6, nextReport=false, reportType="CYCLE", todayCalendarDate defaults to today; numberOfCycles restricted to {1,6,12} or throws GarminError; passes through unchecked
Verification: live-verified
getPregnancySummary
garmin.getPregnancySummary(): Promise<PregnancySummary | null>
const result = await garmin.getPregnancySummary();
Returns
PregnancySummary — an object whose fields this library does not model. Garmin's response is passed through unparsed, so read one to see what you get, or use a Record<string, unknown> and narrow it yourself.
passes through unchecked
Verification: live-verified
initMenstrualCycleSetup
garmin.initMenstrualCycleSetup(periodStartDate: string | Date, periodLength: number, cycleLength: number): Promise<unknown>
const result = await garmin.initMenstrualCycleSetup("2026-09-24", 1, 1);
Returns
unknown — Garmin's response is passed through unparsed. Cast it to whatever you need; this library does not model it.
does NOT also update tracking-preference settings (call updateMenstrualSettings separately for that); not intended for an already-configured account
Verification: live-verified
updateMenstrualCalendar
garmin.updateMenstrualCalendar(startdate: string | Date, enddate: string | Date, cycleDatesLists: (string | Date)[][], options?: {todayCalendarDate?: string | Date}): Promise<unknown>
const result = await garmin.updateMenstrualCalendar("2026-09-24", "2026-09-24", "2026-09-24");
Returns
unknown — Garmin's response is passed through unparsed. Cast it to whatever you need; this library does not model it.
full replace, not a merge; each cycleDatesLists group must be non-empty, consecutive calendar dates, and fall within [startdate, enddate], else throws GarminError
Verification: live-verified
updateMenstrualDailyLog
garmin.updateMenstrualDailyLog(calendarDate: string | Date, options?: {symptoms?: string[], moods?: string[], flow?: string, discharge?: string[], sexDrive?: string, sexualActivity?: string, notes?: string, ovulationDay?: boolean}): Promise<unknown>
const result = await garmin.updateMenstrualDailyLog("2026-09-24");
Returns
unknown — Garmin's response is passed through unparsed. Cast it to whatever you need; this library does not model it.
full-day replace, not a merge; at least one optional field required or throws GarminError; notes: undefined preserves the existing note, notes: "" clears it (distinct, load-bearing); discharge rejects combining "NO_DISCHARGE" with any other value
Verification: live-verified
updateMenstrualSettings
garmin.updateMenstrualSettings(settings: Record<string, unknown>, options?: {userSettingsId?: number}): Promise<unknown>
const result = await garmin.updateMenstrualSettings("settings");
Returns
unknown — Garmin's response is passed through unparsed. Cast it to whatever you need; this library does not model it.
settings must be non-empty or throws GarminError; multi-step: GETs /userprofile-service/userprofile/user-settings, overlays settings onto the current userMenstrualCycleSettings, then PUTs the same endpoint, including id if resolvable
Verification: live-verified