---
url: /docs/api/core/functions/extractWorkout.md
---
[**@kaiord/core**](../README.md)

***

[@kaiord/core](../README.md) / extractWorkout

# Function: extractWorkout()

> **extractWorkout**(`krd`): `object`

Defined in: [packages/core/src/domain/validation/extract-workout.ts:17](https://github.com/pablo-albaladejo/kaiord/blob/3eacbe62ef72342d970523967cc5155b5935bb85/packages/core/src/domain/validation/extract-workout.ts#L17)

Extracts and validates the structured workout from a KRD object.

Checks that the KRD type is "structured_workout" and validates
the workout in extensions.structured_workout against workoutSchema.

## Parameters

### krd

KRD object to extract workout from

#### events?

`object`\[] = `...`

#### extensions?

{\[`key`: `string`]: `unknown`; `course?`: `unknown`; `course_points?`: `unknown`; `fit?`: `unknown`; `health?`: {\[`key`: `string`]: `unknown`; `bodyComposition?`: { `basalMetabolicRateKcal?`: `number`; `bmi?`: `number`; `bodyFatPercent?`: `number`; `bodyWaterPercent?`: `number`; `boneMassKilograms?`: `number`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"bodyComposition"`; `leanMassKilograms?`: `number`; `measuredAt`: `string`; `sourceBridgeId?`: `string`; `version`: `string`; `visceralFatRating?`: `number`; }; `daily?`: { `activeCalories`: `number`; `date`: `string`; `externalId?`: `string`; `floorsClimbed?`: `number`; `intensityMinutes`: { `moderate`: `number`; `vigorous`: `number`; }; `kaiordRecordId?`: `string`; `kind`: `"daily"`; `restingCalories`: `number`; `sourceBridgeId?`: `string`; `steps`: `number`; `version`: `string`; }; `hrv?`: { `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"hrv"`; `measuredAt`: `string`; `measurementWindow`: `"overnight"` | `"spot"`; `rMSSD`: `number`; `score?`: `number`; `sourceBridgeId?`: `string`; `version`: `string`; }; `sleep?`: { `endTime`: `string`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"sleep"`; `restingHeartRate?`: `number`; `score?`: `number`; `sourceBridgeId?`: `string`; `stages`: `object`\[]; `startTime`: `string`; `totalDurationSeconds?`: `number`; `version`: `string`; }; `stress?`: { `averageLevel`: `number`; `endTime`: `string`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"stress"`; `peakLevel`: `number`; `sourceBridgeId?`: `string`; `startTime`: `string`; `version`: `string`; }; `weight?`: { `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"weight"`; `measuredAt`: `string`; `sourceBridgeId?`: `string`; `version`: `string`; `weightKilograms`: `number`; }; }; `structured_workout?`: `unknown`; } = `...`

#### extensions.course?

`unknown` = `...`

#### extensions.course_points?

`unknown` = `...`

#### extensions.fit?

`unknown` = `...`

#### extensions.health?

{\[`key`: `string`]: `unknown`; `bodyComposition?`: { `basalMetabolicRateKcal?`: `number`; `bmi?`: `number`; `bodyFatPercent?`: `number`; `bodyWaterPercent?`: `number`; `boneMassKilograms?`: `number`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"bodyComposition"`; `leanMassKilograms?`: `number`; `measuredAt`: `string`; `sourceBridgeId?`: `string`; `version`: `string`; `visceralFatRating?`: `number`; }; `daily?`: { `activeCalories`: `number`; `date`: `string`; `externalId?`: `string`; `floorsClimbed?`: `number`; `intensityMinutes`: { `moderate`: `number`; `vigorous`: `number`; }; `kaiordRecordId?`: `string`; `kind`: `"daily"`; `restingCalories`: `number`; `sourceBridgeId?`: `string`; `steps`: `number`; `version`: `string`; }; `hrv?`: { `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"hrv"`; `measuredAt`: `string`; `measurementWindow`: `"overnight"` | `"spot"`; `rMSSD`: `number`; `score?`: `number`; `sourceBridgeId?`: `string`; `version`: `string`; }; `sleep?`: { `endTime`: `string`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"sleep"`; `restingHeartRate?`: `number`; `score?`: `number`; `sourceBridgeId?`: `string`; `stages`: `object`\[]; `startTime`: `string`; `totalDurationSeconds?`: `number`; `version`: `string`; }; `stress?`: { `averageLevel`: `number`; `endTime`: `string`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"stress"`; `peakLevel`: `number`; `sourceBridgeId?`: `string`; `startTime`: `string`; `version`: `string`; }; `weight?`: { `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"weight"`; `measuredAt`: `string`; `sourceBridgeId?`: `string`; `version`: `string`; `weightKilograms`: `number`; }; } = `...`

#### extensions.health.bodyComposition?

{ `basalMetabolicRateKcal?`: `number`; `bmi?`: `number`; `bodyFatPercent?`: `number`; `bodyWaterPercent?`: `number`; `boneMassKilograms?`: `number`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"bodyComposition"`; `leanMassKilograms?`: `number`; `measuredAt`: `string`; `sourceBridgeId?`: `string`; `version`: `string`; `visceralFatRating?`: `number`; } = `...`

#### extensions.health.bodyComposition.basalMetabolicRateKcal?

`number` = `...`

#### extensions.health.bodyComposition.bmi?

`number` = `...`

#### extensions.health.bodyComposition.bodyFatPercent?

`number` = `...`

#### extensions.health.bodyComposition.bodyWaterPercent?

`number` = `...`

#### extensions.health.bodyComposition.boneMassKilograms?

`number` = `...`

#### extensions.health.bodyComposition.externalId?

`string` = `...`

#### extensions.health.bodyComposition.kaiordRecordId?

`string` = `...`

#### extensions.health.bodyComposition.kind

`"bodyComposition"` = `...`

#### extensions.health.bodyComposition.leanMassKilograms?

`number` = `...`

#### extensions.health.bodyComposition.measuredAt

`string` = `...`

#### extensions.health.bodyComposition.sourceBridgeId?

`string` = `...`

#### extensions.health.bodyComposition.version

`string` = `healthVersionSchema`

#### extensions.health.bodyComposition.visceralFatRating?

`number` = `...`

#### extensions.health.daily?

{ `activeCalories`: `number`; `date`: `string`; `externalId?`: `string`; `floorsClimbed?`: `number`; `intensityMinutes`: { `moderate`: `number`; `vigorous`: `number`; }; `kaiordRecordId?`: `string`; `kind`: `"daily"`; `restingCalories`: `number`; `sourceBridgeId?`: `string`; `steps`: `number`; `version`: `string`; } = `...`

#### extensions.health.daily.activeCalories

`number` = `...`

#### extensions.health.daily.date

`string` = `...`

#### extensions.health.daily.externalId?

`string` = `...`

#### extensions.health.daily.floorsClimbed?

`number` = `...`

#### extensions.health.daily.intensityMinutes

{ `moderate`: `number`; `vigorous`: `number`; } = `...`

#### extensions.health.daily.intensityMinutes.moderate

`number` = `...`

#### extensions.health.daily.intensityMinutes.vigorous

`number` = `...`

#### extensions.health.daily.kaiordRecordId?

`string` = `...`

#### extensions.health.daily.kind

`"daily"` = `...`

#### extensions.health.daily.restingCalories

`number` = `...`

#### extensions.health.daily.sourceBridgeId?

`string` = `...`

#### extensions.health.daily.steps

`number` = `...`

#### extensions.health.daily.version

`string` = `healthVersionSchema`

#### extensions.health.hrv?

{ `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"hrv"`; `measuredAt`: `string`; `measurementWindow`: `"overnight"` | `"spot"`; `rMSSD`: `number`; `score?`: `number`; `sourceBridgeId?`: `string`; `version`: `string`; } = `...`

#### extensions.health.hrv.externalId?

`string` = `...`

#### extensions.health.hrv.kaiordRecordId?

`string` = `...`

#### extensions.health.hrv.kind

`"hrv"` = `...`

#### extensions.health.hrv.measuredAt

`string` = `...`

#### extensions.health.hrv.measurementWindow

`"overnight"` | `"spot"` = `...`

#### extensions.health.hrv.rMSSD

`number` = `...`

#### extensions.health.hrv.score?

`number` = `...`

#### extensions.health.hrv.sourceBridgeId?

`string` = `...`

#### extensions.health.hrv.version

`string` = `healthVersionSchema`

#### extensions.health.sleep?

{ `endTime`: `string`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"sleep"`; `restingHeartRate?`: `number`; `score?`: `number`; `sourceBridgeId?`: `string`; `stages`: `object`\[]; `startTime`: `string`; `totalDurationSeconds?`: `number`; `version`: `string`; } = `...`

#### extensions.health.sleep.endTime

`string` = `...`

#### extensions.health.sleep.externalId?

`string` = `...`

#### extensions.health.sleep.kaiordRecordId?

`string` = `...`

#### extensions.health.sleep.kind

`"sleep"` = `...`

#### extensions.health.sleep.restingHeartRate?

`number` = `...`

#### extensions.health.sleep.score?

`number` = `...`

#### extensions.health.sleep.sourceBridgeId?

`string` = `...`

#### extensions.health.sleep.stages

`object`\[] = `...`

#### extensions.health.sleep.startTime

`string` = `...`

#### extensions.health.sleep.totalDurationSeconds?

`number` = `...`

#### extensions.health.sleep.version

`string` = `healthVersionSchema`

#### extensions.health.stress?

{ `averageLevel`: `number`; `endTime`: `string`; `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"stress"`; `peakLevel`: `number`; `sourceBridgeId?`: `string`; `startTime`: `string`; `version`: `string`; } = `...`

#### extensions.health.stress.averageLevel

`number` = `...`

#### extensions.health.stress.endTime

`string` = `...`

#### extensions.health.stress.externalId?

`string` = `...`

#### extensions.health.stress.kaiordRecordId?

`string` = `...`

#### extensions.health.stress.kind

`"stress"` = `...`

#### extensions.health.stress.peakLevel

`number` = `...`

#### extensions.health.stress.sourceBridgeId?

`string` = `...`

#### extensions.health.stress.startTime

`string` = `...`

#### extensions.health.stress.version

`string` = `healthVersionSchema`

#### extensions.health.weight?

{ `externalId?`: `string`; `kaiordRecordId?`: `string`; `kind`: `"weight"`; `measuredAt`: `string`; `sourceBridgeId?`: `string`; `version`: `string`; `weightKilograms`: `number`; } = `...`

#### extensions.health.weight.externalId?

`string` = `...`

#### extensions.health.weight.kaiordRecordId?

`string` = `...`

#### extensions.health.weight.kind

`"weight"` = `...`

#### extensions.health.weight.measuredAt

`string` = `...`

#### extensions.health.weight.sourceBridgeId?

`string` = `...`

#### extensions.health.weight.version

`string` = `healthVersionSchema`

#### extensions.health.weight.weightKilograms

`number` = `...`

#### extensions.structured_workout?

`unknown` = `...`

#### laps?

`object`\[] = `...`

#### metadata

{ `created`: `string`; `manufacturer?`: `string`; `product?`: `string`; `serialNumber?`: `string`; `sport?`: `string`; `subSport?`: `string`; } = `krdMetadataSchema`

#### metadata.created

`string` = `...`

#### metadata.manufacturer?

`string` = `...`

#### metadata.product?

`string` = `...`

#### metadata.serialNumber?

`string` = `...`

#### metadata.sport?

`string` = `...`

**See**

sportSchema for known sport values. Accepts custom strings for forward compatibility.

Optional at the metadata level because health-metric KRD types
(sleep, weight, HRV, daily wellness, body composition, stress)
have no associated sport. A conditional refinement on `krdSchema`
still requires `sport` for the three legacy workout/activity/course
types so v1.x consumers see no change for those.

#### metadata.subSport?

`string` = `...`

#### records?

`object`\[] = `...`

#### sessions?

`object`\[] = `...`

#### type

`"structured_workout"` | `"recorded_activity"` | `"course"` | `"sleep_record"` | `"weight_measurement"` | `"hrv_summary"` | `"daily_wellness"` | `"body_composition"` | `"stress_episode"` = `fileTypeSchema`

#### version

`string` = `...`

## Returns

Validated Workout object

### extensions?

> `optional` **extensions?**: `Record`<`string`, `unknown`>

### name?

> `optional` **name?**: `string`

### notes?

> `optional` **notes?**: `string`

Workout-level free-text coaching instructions (e.g. Train2Go coach
descriptions, possibly containing markdown `[label](url)` links). Distinct
from per-step `notes` and from the short `name`. No length cap here; format
adapters whose target imposes one (FIT step notes: 256) truncate best-effort
at export rather than rejecting the KRD.

### poolLength?

> `optional` **poolLength?**: `number`

meters — always normalized to meters on ingest

### poolLengthUnit?

> `optional` **poolLengthUnit?**: `"meters"`

### sport

> **sport**: `"generic"` | `"running"` | `"cycling"` | `"transition"` | `"fitness_equipment"` | `"swimming"` | `"basketball"` | `"soccer"` | `"tennis"` | `"american_football"` | `"training"` | `"walking"` | `"cross_country_skiing"` | `"alpine_skiing"` | `"snowboarding"` | `"rowing"` | `"mountaineering"` | `"hiking"` | `"multisport"` | `"paddling"` | `"flying"` | `"e_biking"` | `"motorcycling"` | `"boating"` | `"driving"` | `"golf"` | `"hang_gliding"` | `"horseback_riding"` | `"hunting"` | `"fishing"` | `"inline_skating"` | `"rock_climbing"` | `"sailing"` | `"ice_skating"` | `"sky_diving"` | `"snowshoeing"` | `"snowmobiling"` | `"stand_up_paddleboarding"` | `"surfing"` | `"wakeboarding"` | `"water_skiing"` | `"kayaking"` | `"rafting"` | `"windsurfing"` | `"kitesurfing"` | `"tactical"` | `"jumpmaster"` | `"boxing"` | `"floor_climbing"` | `"baseball"` | `"diving"` | `"shooting"` | `"winter_sport"` | `"grinding"` | `"hiit"` | `"video_gaming"` | `"racket"` | `"wheelchair_push_walk"` | `"wheelchair_push_run"` | `"meditation"` | `"para_sport"` | `"disc_golf"` | `"team_sport"` | `"cricket"` | `"rugby"` | `"hockey"` | `"lacrosse"` | `"volleyball"` | `"water_tubing"` | `"wakesurfing"` | `"water_sport"` | `"archery"` | `"mixed_martial_arts"` | `"motor_sports"` | `"snorkeling"` | `"dance"` | `"jump_rope"` | `"pool_apnea"` | `"mobility"` | `"geocaching"` | `"canoeing"` = `sportSchema`

### steps

> **steps**: ({ `duration`: { `seconds`: `number`; `type`: `"time"`; } | { `meters`: `number`; `type`: `"distance"`; } | { `bpm`: `number`; `type`: `"heart_rate_less_than"`; } | { `bpm`: `number`; `repeatFrom`: `number`; `type`: `"repeat_until_heart_rate_greater_than"`; } | { `calories`: `number`; `type`: `"calories"`; } | { `type`: `"power_less_than"`; `watts`: `number`; } | { `type`: `"power_greater_than"`; `watts`: `number`; } | { `repeatFrom`: `number`; `seconds`: `number`; `type`: `"repeat_until_time"`; } | { `meters`: `number`; `repeatFrom`: `number`; `type`: `"repeat_until_distance"`; } | { `calories`: `number`; `repeatFrom`: `number`; `type`: `"repeat_until_calories"`; } | { `bpm`: `number`; `repeatFrom`: `number`; `type`: `"repeat_until_heart_rate_less_than"`; } | { `repeatFrom`: `number`; `type`: `"repeat_until_power_less_than"`; `watts`: `number`; } | { `repeatFrom`: `number`; `type`: `"repeat_until_power_greater_than"`; `watts`: `number`; } | { `type`: `"open"`; }; `durationType`: `"time"` | `"distance"` | `"heart_rate_less_than"` | `"repeat_until_heart_rate_greater_than"` | `"calories"` | `"power_less_than"` | `"power_greater_than"` | `"repeat_until_time"` | `"repeat_until_distance"` | `"repeat_until_calories"` | `"repeat_until_heart_rate_less_than"` | `"repeat_until_power_less_than"` | `"repeat_until_power_greater_than"` | `"open"`; `equipment?`: `"none"` | `"swim_fins"` | `"swim_kickboard"` | `"swim_paddles"` | `"swim_pull_buoy"` | `"swim_snorkel"`; `extensions?`: `Record`<`string`, `unknown`>; `intensity?`: `"warmup"` | `"active"` | `"cooldown"` | `"rest"` | `"recovery"` | `"interval"` | `"other"`; `name?`: `string`; `notes?`: `string`; `stepIndex`: `number`; `target`: { `type`: `"power"`; `value`: { `basis?`: `"percent_ftp"`; `max`: `number`; `min`: `number`; `unit`: `"range"`; } | { `unit`: `"watts"`; `value`: `number`; } | { `unit`: `"percent_ftp"`; `value`: `number`; } | { `unit`: `"zone"`; `value`: `number`; }; } | { `type`: `"heart_rate"`; `value`: { `max`: `number`; `min`: `number`; `unit`: `"range"`; } | { `unit`: `"bpm"`; `value`: `number`; } | { `unit`: `"zone"`; `value`: `number`; } | { `unit`: `"percent_max"`; `value`: `number`; }; } | { `type`: `"cadence"`; `value`: { `max`: `number`; `min`: `number`; `unit`: `"range"`; } | { `unit`: `"rpm"`; `value`: `number`; }; } | { `type`: `"pace"`; `value`: { `max`: `number`; `min`: `number`; `unit`: `"range"`; } | { `unit`: `"mps"`; `value`: `number`; } | { `unit`: `"zone"`; `value`: `number`; }; } | { `type`: `"stroke_type"`; `value`: { `unit`: `"swim_stroke"`; `value`: `number`; }; } | { `type`: `"open"`; }; `targetType`: `"cadence"` | `"power"` | `"open"` | `"heart_rate"` | `"pace"` | `"stroke_type"`; } | { `id?`: `string`; `repeatCount`: `number`; `steps`: `object`\[]; })\[]

### subSport?

> `optional` **subSport?**: `"match"` | `"map"` | `"generic"` | `"treadmill"` | `"street"` | `"trail"` | `"track"` | `"spin"` | `"indoor_cycling"` | `"road"` | `"mountain"` | `"downhill"` | `"recumbent"` | `"cyclocross"` | `"hand_cycling"` | `"track_cycling"` | `"indoor_rowing"` | `"elliptical"` | `"stair_climbing"` | `"lap_swimming"` | `"open_water"` | `"flexibility_training"` | `"strength_training"` | `"warm_up"` | `"exercise"` | `"challenge"` | `"indoor_skiing"` | `"cardio_training"` | `"indoor_walking"` | `"e_bike_fitness"` | `"bmx"` | `"casual_walking"` | `"speed_walking"` | `"bike_to_run_transition"` | `"run_to_bike_transition"` | `"swim_to_bike_transition"` | `"atv"` | `"motocross"` | `"backcountry"` | `"resort"` | `"rc_drone"` | `"wingsuit"` | `"whitewater"` | `"skate_skiing"` | `"yoga"` | `"pilates"` | `"indoor_running"` | `"gravel_cycling"` | `"e_bike_mountain"` | `"commuting"` | `"mixed_surface"` | `"navigate"` | `"track_me"` | `"single_gas_diving"` | `"multi_gas_diving"` | `"gauge_diving"` | `"apnea_diving"` | `"apnea_hunting"` | `"virtual_activity"` | `"obstacle"` | `"all"`

## Throws

If KRD is not a structured workout or workout is invalid
