{"openapi":"3.1.0","info":{"title":"Vekta API","version":"0.1.0","description":"Query your training data and the data of the athletes you coach. The `userId` path parameter accepts the id of any user returned by `GET /users`, or the special value `me` for the user owning the api key.\n\nRequests are rate limited per api key (300 requests per minute overall) and per queried user (30 requests per minute each), so fetching several users in parallel is fine. Rate limited requests receive a 429 response with a `Retry-After` header."},"paths":{"/users":{"get":{"tags":["Users"],"operationId":"users.listUsers","parameters":[],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"The users with the athlete role in at least one workspace where you are coach or admin. The returned ids can be used as the userId path parameter of the other endpoints. Your own data is available through the special value \"me\".","summary":"List your athletes"}},"/users/{userId}":{"get":{"tags":["Users"],"operationId":"users.getProfile","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true}],"security":[{"bearer":[]}],"responses":{"200":{"description":"The full profile of a Vekta user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"Profile of yourself (\"me\") or one of your athletes. The workspaces field is only returned for your own profile. Responds with 404 if the user does not exist or is not accessible to you.","summary":"Get a user's profile"}},"/users/{userId}/activities":{"get":{"tags":["Activities"],"operationId":"activities.listActivities","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true},{"name":"from","in":"query","schema":{"type":"string","description":"Inclusive start of the date range (YYYY-MM-DD)","examples":["2026-08-01"],"format":"date"},"required":false},{"name":"to","in":"query","schema":{"type":"string","description":"Inclusive end of the date range (YYYY-MM-DD)","examples":["2026-08-31"],"format":"date"},"required":false}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Activity"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"Summaries of the user's activities, most recent first, optionally restricted to a local date range. Responds with 404 if the user does not exist or is not accessible to you.","summary":"List a user's activities"}},"/activities/{activityId}/streams":{"get":{"tags":["Activities"],"operationId":"activities.getStreams","parameters":[{"name":"activityId","in":"path","schema":{"type":"string","description":"Id of an activity of a user you have access to, obtained from the activity list endpoint","examples":["act_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"required":true}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Column-oriented time series of an activity: one array per recorded field, all of the same length and aligned by index. A column is absent when the activity did not record that field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityStreams"}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"Recorded time series of an activity in column-oriented form: one array per field, aligned by index. Requests to this endpoint are only counted against the per api key rate limit. Responds with 404 if the activity does not exist, is not accessible to you, or has no streams.","summary":"Get an activity's streams"}},"/users/{userId}/training-prescriptions":{"get":{"tags":["Training prescriptions"],"operationId":"trainingPrescriptions.listTrainingPrescriptions","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true},{"name":"from","in":"query","schema":{"type":"string","description":"Inclusive start of the date range (YYYY-MM-DD)","examples":["2026-08-01"],"format":"date"},"required":false},{"name":"to","in":"query","schema":{"type":"string","description":"Inclusive end of the date range (YYYY-MM-DD)","examples":["2026-08-31"],"format":"date"},"required":false}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrainingPrescription"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"Workouts planned for the user, most recent first, optionally restricted to a date range. Responds with 404 if the user does not exist or is not accessible to you.","summary":"List a user's training prescriptions"}},"/users/{userId}/notes":{"get":{"tags":["Notes"],"operationId":"notes.listNotes","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true},{"name":"from","in":"query","schema":{"type":"string","description":"Inclusive start of the date range (YYYY-MM-DD)","examples":["2026-08-01"],"format":"date"},"required":false},{"name":"to","in":"query","schema":{"type":"string","description":"Inclusive end of the date range (YYYY-MM-DD)","examples":["2026-08-31"],"format":"date"},"required":false}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Note"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"The user's notes, most recent first, optionally restricted to a date range. Notes hidden until a future date are only returned to their creator. Responds with 404 if the user does not exist or is not accessible to you.","summary":"List a user's notes"}},"/users/{userId}/events":{"get":{"tags":["Events"],"operationId":"events.listEvents","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true},{"name":"from","in":"query","schema":{"type":"string","description":"Inclusive start of the date range (YYYY-MM-DD)","examples":["2026-08-01"],"format":"date"},"required":false},{"name":"to","in":"query","schema":{"type":"string","description":"Inclusive end of the date range (YYYY-MM-DD)","examples":["2026-08-31"],"format":"date"},"required":false}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"The user's planned events and races, most recent first, optionally restricted to a date range. Responds with 404 if the user does not exist or is not accessible to you.","summary":"List a user's events"}},"/users/{userId}/metrics":{"get":{"tags":["Metrics"],"operationId":"metrics.listMetrics","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true},{"name":"from","in":"query","schema":{"type":"string","description":"Inclusive start of the date range (YYYY-MM-DD)","examples":["2026-08-01"],"format":"date"},"required":false},{"name":"to","in":"query","schema":{"type":"string","description":"Inclusive end of the date range (YYYY-MM-DD)","examples":["2026-08-31"],"format":"date"},"required":false}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Metric"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"Full history of the user's body and performance metrics, ordered by date, optionally restricted to a date range. Responds with 404 if the user does not exist or is not accessible to you.","summary":"List a user's metrics"}},"/users/{userId}/sleeps":{"get":{"tags":["Sleep"],"operationId":"sleep.listSleeps","parameters":[{"name":"userId","in":"path","schema":{"type":"string","description":"Id of a user you have access to (see `GET /users`), or the special value `me` for the user owning the api key","examples":["me","usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true},{"name":"from","in":"query","schema":{"type":"string","description":"Inclusive start of the date range (YYYY-MM-DD)","examples":["2026-08-01"],"format":"date"},"required":false},{"name":"to","in":"query","schema":{"type":"string","description":"Inclusive end of the date range (YYYY-MM-DD)","examples":["2026-08-31"],"format":"date"},"required":false}],"security":[{"bearer":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Sleep"}}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"The user's recorded nights of sleep, most recent first, optionally restricted to a date range matching the day field. Responds with 404 if the user does not exist or is not accessible to you.","summary":"List a user's sleeps"}},"/workspaces/{workspaceId}/invitations":{"post":{"tags":["Workspaces"],"operationId":"workspaces.createInvitation","parameters":[{"name":"workspaceId","in":"path","schema":{"type":"string","description":"Id of a workspace where you are admin or coach (see the workspaces field of GET /users/me)","examples":["wke_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"required":true}],"security":[{"bearer":[]}],"responses":{"200":{"description":"A pending invitation to join a workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceInvitation"}}}},"400":{"description":"BadRequestError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}}},"401":{"description":"UnauthorizedError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"404":{"description":"NotFoundError","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"RateLimitedError","headers":{"retry-after":{"schema":{"type":"integer","description":"Seconds until the current rate limit window ends","examples":[42]},"required":true}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitedError"}}}}},"description":"Invites an email address to join the workspace as athlete or coach. If the email already has a pending invitation in the workspace, its expiry is extended by two days and the existing code is returned instead of creating a new invitation. Set sendInvitationEmail to true to have Vekta email the code to the invitee. Requests to this endpoint are only counted against the per api key rate limit. Responds with 404 if the workspace does not exist or you are not one of its admins or coaches.","summary":"Invite someone to a workspace","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWorkspaceInvitation"}}},"required":true}}}},"components":{"schemas":{"User":{"type":"object","properties":{"id":{"type":"string","examples":["usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"firstName":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Alex"]},"lastName":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Rivera"]},"dateOfBirth":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["1990-05-15"],"format":"date"},"gender":{"anyOf":[{"type":"string","enum":["male","female","other"]},{"type":"null"}],"examples":["male"]},"height":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In cm","examples":[180]},"dataOnboardingStatus":{"type":"string","enum":["not started","ongoing","failed","done"],"description":"Progress of the user's historical data import","examples":["done"]},"userMetricReadiness":{"anyOf":[{"type":"object","properties":{"hasVektaCyclingCriticalPower":{"type":"boolean","examples":[true]},"hasVektaRunningCriticalPower":{"type":"boolean","examples":[true]},"hasVektaRunningCriticalSpeed":{"type":"boolean","examples":[false]}},"required":["hasVektaCyclingCriticalPower","hasVektaRunningCriticalPower","hasVektaRunningCriticalSpeed"],"additionalProperties":false},{"type":"null"}],"description":"Which Vekta performance models are available"}},"required":["id","firstName","lastName","dateOfBirth","gender","height","dataOnboardingStatus","userMetricReadiness"],"additionalProperties":false,"description":"A Vekta user"},"UnauthorizedError":{"type":"object","properties":{"code":{"type":"string","enum":["unauthorized"]},"error":{"type":"string","description":"Human readable explanation of the error","examples":["invalid api key"]}},"required":["code","error"],"additionalProperties":false},"RateLimitedError":{"type":"object","properties":{"code":{"type":"string","enum":["rate_limited"]},"error":{"type":"string","description":"Human readable explanation of the error","examples":["rate limit of 30 requests per minute exceeded, retry after the `Retry-After` header"]}},"required":["code","error"],"additionalProperties":false},"BadRequestError":{"type":"object","properties":{"code":{"type":"string","enum":["bad_request"]},"error":{"type":"string","description":"Human readable explanation of the error","examples":["invalid query: Expected YYYY-MM-DD"]}},"required":["code","error"],"additionalProperties":false},"LatestMetric":{"type":"object","properties":{"sport":{"type":"string","enum":["global","cycling","running","swimming"],"examples":["cycling"]},"type":{"type":"string","enum":["weight","critical power","w prime","d prime","max power","vo2max","critical speed","max heart rate","resting heart rate","spo2","body fat"],"examples":["critical power"]},"source":{"anyOf":[{"type":"string","enum":["user","vekta"]},{"type":"null"}],"examples":["vekta"]},"value":{"type":"number","examples":[280]}},"required":["sport","type","source","value"],"additionalProperties":false,"description":"Latest value of a metric per (sport, type) combination"},"WorkspaceMembership":{"type":"object","properties":{"id":{"type":"string","examples":["wke_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"name":{"type":"string","examples":["Endurance Squad"]},"slug":{"type":"string","examples":["endurance-squad"]},"role":{"type":"string","enum":["athlete","coach","admin"],"description":"Your role in the workspace","examples":["coach"]}},"required":["id","name","slug","role"],"additionalProperties":false,"description":"A workspace the user belongs to"},"UserProfile":{"type":"object","properties":{"id":{"type":"string","examples":["usr_01JGXW3KQ2B8C4D5E6F7G8H9J0"]},"firstName":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Alex"]},"lastName":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Rivera"]},"dateOfBirth":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["1990-05-15"],"format":"date"},"gender":{"anyOf":[{"type":"string","enum":["male","female","other"]},{"type":"null"}],"examples":["male"]},"height":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In cm","examples":[180]},"dataOnboardingStatus":{"type":"string","enum":["not started","ongoing","failed","done"],"description":"Progress of the user's historical data import","examples":["done"]},"userMetricReadiness":{"anyOf":[{"type":"object","properties":{"hasVektaCyclingCriticalPower":{"type":"boolean","examples":[true]},"hasVektaRunningCriticalPower":{"type":"boolean","examples":[true]},"hasVektaRunningCriticalSpeed":{"type":"boolean","examples":[false]}},"required":["hasVektaCyclingCriticalPower","hasVektaRunningCriticalPower","hasVektaRunningCriticalSpeed"],"additionalProperties":false},{"type":"null"}],"description":"Which Vekta performance models are available"},"latestMetrics":{"type":"array","items":{"$ref":"#/components/schemas/LatestMetric"},"description":"Latest value per (sport, type) combination"},"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceMembership"},"description":"Only returned when querying your own profile."}},"required":["id","firstName","lastName","dateOfBirth","gender","height","dataOnboardingStatus","userMetricReadiness","latestMetrics"],"additionalProperties":false,"description":"The full profile of a Vekta user"},"NotFoundError":{"type":"object","properties":{"code":{"type":"string","enum":["not_found"]},"error":{"type":"string","description":"Human readable explanation of the error","examples":["athlete not found"]}},"required":["code","error"],"additionalProperties":false},"Lap":{"type":"object","properties":{"intensity":{"type":"string","enum":["neuromuscular","anaerobic","vo2max","threshold","aerobic","recovery","tempo"],"examples":["threshold"]},"characteristic":{"anyOf":[{"type":"string","enum":["maximum","torque","cadence","progressive","intra-recovery","dynamic"]},{"type":"null"}],"description":"Secondary trait, when Vekta detected one","examples":["progressive"]},"startedAtIndex":{"type":"number","description":"0-based streams index","examples":[0]},"endedAtIndex":{"type":"number","description":"0-based streams index","examples":[1800]},"startedAt":{"type":"string","examples":["2026-08-05 06:30:00+00"]},"endedAt":{"type":"string","examples":["2026-08-05 07:00:00+00"]},"duration":{"type":"number","description":"In seconds","examples":[1800]},"distance":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[12500]},"averagePower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[268]},"maxPower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[412]},"averageCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[90]},"maxCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[110]},"averageHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[168]},"maxHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[176]},"averageSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[6.94]},"maxSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[12.5]},"averageAltitude":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[340]},"elevationGain":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[85]},"elevationLoss":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[12]},"averageTorque":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In Nm (float)","examples":[28.5]},"maxTorque":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In Nm (float)","examples":[52.1]},"averageTemperature":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In °C (float)","examples":[19]},"workBefore":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kJ, cumulative before this lap","examples":[0]}},"required":["intensity","characteristic","startedAtIndex","endedAtIndex","startedAt","endedAt","duration","distance","averagePower","maxPower","averageCadence","maxCadence","averageHeartRate","maxHeartRate","averageSpeed","maxSpeed","averageAltitude","elevationGain","elevationLoss","averageTorque","maxTorque","averageTemperature","workBefore"],"additionalProperties":false,"description":"A Vekta-classified lap, ordered by `startedAtIndex`"},"Climb":{"type":"object","properties":{"startedAtIndex":{"type":"number","description":"0-based streams index","examples":[600]},"endedAtIndex":{"type":"number","description":"0-based streams index","examples":[2400]},"startedAt":{"type":"string","examples":["2026-08-05 06:40:00+00"]},"endedAt":{"type":"string","examples":["2026-08-05 07:10:00+00"]},"duration":{"type":"number","description":"In seconds","examples":[1800]},"distance":{"type":"number","description":"In meters","examples":[11000]},"averageGrade":{"type":"number","description":"In % (float)","examples":[6.2]},"maxGrade":{"type":"number","description":"In % (float)","examples":[11.5]},"averagePower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[275]},"maxPower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[430]},"averagePowerPerKilo":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"W/kg (float)","examples":[3.8]},"maxPowerPerKilo":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"W/kg (float)","examples":[5.9]},"workBefore":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kJ, cumulative before this climb","examples":[320]},"averageCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[78]},"maxCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[96]},"averageHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[172]},"maxHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[182]},"averageSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[6.1]},"maxSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[9.8]},"minAltitude":{"type":"number","description":"In meters","examples":[340]},"maxAltitude":{"type":"number","description":"In meters","examples":[590]},"elevationGain":{"type":"number","description":"In meters","examples":[250]},"averageTemperature":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In °C (float)","examples":[17]}},"required":["startedAtIndex","endedAtIndex","startedAt","endedAt","duration","distance","averageGrade","maxGrade","averagePower","maxPower","averagePowerPerKilo","maxPowerPerKilo","workBefore","averageCadence","maxCadence","averageHeartRate","maxHeartRate","averageSpeed","maxSpeed","minAltitude","maxAltitude","elevationGain","averageTemperature"],"additionalProperties":false,"description":"A detected climb, ordered by `startedAtIndex`"},"Length":{"type":"object","properties":{"startedAtIndex":{"type":"number","description":"0-based streams index","examples":[0]},"endedAtIndex":{"type":"number","description":"0-based streams index","examples":[45]},"startedAt":{"type":"string","examples":["2026-08-05 07:15:00+00"]},"endedAt":{"type":"string","examples":["2026-08-05 07:15:38+00"]},"duration":{"type":"number","description":"In seconds","examples":[38]},"strokeType":{"anyOf":[{"type":"string","enum":["freestyle","backstroke","breaststroke","butterfly","drill","mixed","im","imByRound","rimo"]},{"type":"null"}],"examples":["freestyle"]},"averageSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[1.32]},"averageHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[142]},"maxHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[148]},"averageCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In strokes/min","examples":[32]},"strokeCount":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[18]}},"required":["startedAtIndex","endedAtIndex","startedAt","endedAt","duration","strokeType","averageSpeed","averageHeartRate","maxHeartRate","averageCadence","strokeCount"],"additionalProperties":false,"description":"A single pool length of a lap_swimming activity, ordered by `startedAtIndex`"},"ProviderLap":{"type":"object","properties":{"startedAt":{"type":"string","examples":["2026-08-05 06:30:00+00"]},"endedAt":{"type":"string","examples":["2026-08-05 07:00:00+00"]},"intensity":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Provider-reported label, unmodeled by Vekta","examples":["active"]},"lapTrigger":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"What ended the lap (manual, distance, time...)","examples":["manual"]}},"required":["startedAt","endedAt","intensity","lapTrigger"],"additionalProperties":false,"description":"A lap as reported by the original data provider"},"Activity":{"type":"object","properties":{"id":{"type":"string","examples":["act_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"groupId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Groups the legs of a multisport activity","examples":[null]},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Morning Ride"]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":[null]},"sport":{"anyOf":[{"type":"string","enum":["cycling","running","swimming","training","multisport","walking","crossCountrySkiing","alpineSkiing","rowing","hiking","hiit","fitnessEquipment","racket","tennis","golf","standUpPaddleboarding","snowboarding","meditation","kayaking","soccer","rockClimbing","iceSkating","windsurfing","mixedMartialArts","sailing","mountaineering","surfing","boating","basketball","eBiking","hockey","snowshoeing","inlineSkating","kitesurfing","mobility","tactical","hunting","fishing","jumpRope","boxing","floorClimbing","snorkeling","motorcycling","baseball","paddling","canoeing","rafting","rugby","discGolf","wakeboarding","wakesurfing","waterTubing","waterSkiing","waterSport","snowmobiling","dance","flying","americanFootball","diving","cricket","volleyball","wheelchairPushWalk","wheelchairPushRun","paraSport","hangGliding","skyDiving","jumpmaster","horsebackRiding","driving","motorSports","shooting","archery","winterSport","videoGaming","geocaching","lacrosse","poolApnea","teamSport","grinding","transition","generic"]},{"type":"null"}],"examples":["cycling"]},"subSport":{"anyOf":[{"type":"string","enum":["generic","treadmill","street","trail","track","spin","indoorCycling","road","mountain","downhill","recumbent","cyclocross","handCycling","trackCycling","indoorRowing","elliptical","stairClimbing","lapSwimming","openWater","flexibilityTraining","strengthTraining","warmUp","match","exercise","challenge","indoorSkiing","cardioTraining","indoorWalking","eBikeFitness","bmx","casualWalking","speedWalking","bikeToRunTransition","runToBikeTransition","swimToBikeTransition","atv","motocross","backcountry","resort","rcDrone","wingsuit","whitewater","skateSkiing","yoga","pilates","indoorRunning","gravelCycling","eBikeMountain","commuting","mixedSurface","navigate","trackMe","map","singleGasDiving","multiGasDiving","gaugeDiving","apneaDiving","apneaHunting","virtualActivity","obstacle","breathing","ccrDiving","sailRace","expedition","ultra","indoorClimbing","bouldering","hiit","indoorGrinding","huntingWithDogs","amrap","emom","tabata","esport","triathlon","duathlon","brick","swimRun","adventureRace","truckerWorkout","pickleball","padel","indoorWheelchairWalk","indoorWheelchairRun","indoorHandCycling","field","ice","ultimate","platform","squash","badminton","racquetball","tableTennis","overland","trollingMotor","flyCanopy","flyParaglide","flyParamotor","flyPressurized","flyNavigate","flyTimer","flyAltimeter","flyWx","flyVfr","flyIfr","dynamicApnea","enduro","rucking","rally","poolTriathlon","eBikeEnduro","timeTrial"]},{"type":"null"}],"examples":["road"]},"startedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["2026-08-05 06:30:00+00"]},"utcOffset":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In minutes from UTC","examples":[120]},"startedAtLocal":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["2026-08-05 08:30:00+00"]},"movingDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds","examples":[7020]},"effectiveDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, elapsed minus pauses","examples":[7200]},"totalDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds","examples":[7500]},"trainingStimulus":{"anyOf":[{"type":"string","enum":["neuromuscular","anaerobic","vo2max","threshold","tempo","aerobic","recovery","lactate clearance","durability","activation","test","race","heat"]},{"type":"null"}],"description":"Dominant physiological stimulus, classified by Vekta","examples":["tempo"]},"raceType":{"anyOf":[{"type":"string","enum":["flat","hilly","mountain","time trial","team time trial"]},{"type":"null"}],"description":"Only set when the activity is a race","examples":[null]},"distance":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[62000]},"elevationLoss":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[540]},"elevationGain":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[550]},"minElevation":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[210]},"averageElevation":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[340]},"maxElevation":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[610]},"startLatitude":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In degrees (float)","examples":[45.764]},"startLongitude":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In degrees (float)","examples":[4.8357]},"averageSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[8.6]},"maxSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[18.2]},"averageCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[88]},"maxCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[112]},"averageRunningCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In strides/min","examples":[null]},"maxRunningCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In strides/min","examples":[null]},"minTemperature":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[14]},"averageTemperature":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[19]},"maxTemperature":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[24]},"averageHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[142]},"maxHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[178]},"averagePower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[205]},"normalizedPower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[220]},"maxPower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[850]},"work":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kJ","examples":[1480]},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Vekta training load score","examples":[43]},"intensity":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"0 to 100","examples":[55]},"calories":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kcal","examples":[1450]},"rpe":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"1 (very easy) to 10 (max effort)","examples":[7]},"feeling":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"1 (very weak) to 5 (very strong)","examples":[4]},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"AI-generated","examples":["Tempo ride with 3 x 12 min efforts around threshold."]},"laps":{"type":"array","items":{"$ref":"#/components/schemas/Lap"},"description":"Vekta-classified laps; populated for cycling, empty otherwise"},"climbs":{"type":"array","items":{"$ref":"#/components/schemas/Climb"},"description":"Detected climbs; populated for cycling, empty otherwise"},"lengths":{"type":"array","items":{"$ref":"#/components/schemas/Length"},"description":"Pool lengths; populated for lap_swimming, empty otherwise"},"providerLaps":{"type":"array","items":{"$ref":"#/components/schemas/ProviderLap"},"description":"Raw laps from the data provider, before Vekta classification"}},"required":["id","groupId","name","description","sport","subSport","startedAt","utcOffset","startedAtLocal","movingDuration","effectiveDuration","totalDuration","trainingStimulus","raceType","distance","elevationLoss","elevationGain","minElevation","averageElevation","maxElevation","startLatitude","startLongitude","averageSpeed","maxSpeed","averageCadence","maxCadence","averageRunningCadence","maxRunningCadence","minTemperature","averageTemperature","maxTemperature","averageHeartRate","maxHeartRate","averagePower","normalizedPower","maxPower","work","volume","intensity","calories","rpe","feeling","summary","laps","climbs","lengths","providerLaps"],"additionalProperties":false,"description":"Summary of a recorded activity"},"ActivityStreams":{"type":"object","properties":{"timestamp":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":"UTC timestamp of each datapoint (ISO 8601)","examples":[["2026-08-05T06:30:00.000Z","2026-08-05T06:30:01.000Z"]]},"power":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"distance":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"heartRate":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"cadence":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"temperature":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"altitude":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"speed":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"grade":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"positionLat":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"positionLong":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"leftRightBalance":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"coreTemperature":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"skinTemperature":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"heatStrainIndex":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"breathingRate":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"tidalVolume":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"minuteVentilation":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"torque":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"wPrimeBalance":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"intensity":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"groundContactTime":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"stepLength":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"verticalOscillation":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"fluidLoss":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"},"sodiumLoss":{"type":"array","items":{"anyOf":[{"anyOf":[{"type":"number"},{"type":"string","enum":["Infinity","-Infinity","NaN"]}]},{"type":"null"}]},"description":"One value per datapoint, null where the device did not report one"}},"additionalProperties":false,"description":"Column-oriented time series of an activity: one array per recorded field, all of the same length and aligned by index. A column is absent when the activity did not record that field."},"StructureIntensity":{"type":"object","properties":{"vektaIntensity":{"anyOf":[{"type":"string","enum":["neuromuscular","anaerobic","vo2max","threshold","aerobic","recovery","tempo"]},{"type":"null"}],"description":"Classified by Vekta","examples":["threshold"]},"zone":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Zone name, when prescribed from zones","examples":["Z4"]},"fromPower":{"anyOf":[{"type":"string","enum":["zone","metric","absolute"]},{"type":"null"}],"examples":["zone"]},"fromHeartRate":{"anyOf":[{"type":"string","enum":["zone","metric","absolute"]},{"type":"null"}],"examples":["zone"]},"minPower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[250]},"maxPower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[280]},"minPowerThresholdPercentage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In % of critical power","examples":[95]},"maxPowerThresholdPercentage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In % of critical power","examples":[106]},"minHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[160]},"maxHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[172]},"minMaxHeartRatePercentage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In % of max heart rate","examples":[85]},"maxMaxHeartRatePercentage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In % of max heart rate","examples":[91]},"minCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[85]},"maxCadence":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[95]},"fromSpeed":{"anyOf":[{"type":"string","enum":["zone","metric","absolute"]},{"type":"null"}],"examples":["zone"]},"minSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[3.6]},"maxSpeed":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In m/s (float)","examples":[4.2]},"minSpeedThresholdPercentage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In % of critical speed","examples":[92]},"maxSpeedThresholdPercentage":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In % of critical speed","examples":[104]}},"required":["vektaIntensity","zone","fromPower","fromHeartRate","minPower","maxPower","minPowerThresholdPercentage","maxPowerThresholdPercentage","minHeartRate","maxHeartRate","minMaxHeartRatePercentage","maxMaxHeartRatePercentage","minCadence","maxCadence"],"additionalProperties":false,"description":"Intensity targets of a structured workout step"},"StructureStep":{"type":"object","properties":{"type":{"type":"string","enum":["step"]},"label":{"type":"string","enum":["warm up","active","intra-recovery","rest","cool down","maximum"],"examples":["active"]},"intensity":{"$ref":"#/components/schemas/StructureIntensity"},"length":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["free"]}},"required":["type"],"additionalProperties":false,"description":"Open-ended step: the athlete decides when to move on"},{"type":"object","properties":{"type":{"type":"string","enum":["duration"]},"duration":{"type":"number","description":"In seconds","examples":[1200]}},"required":["type","duration"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["distance"]},"distance":{"type":"number","description":"In meters","examples":[5000]}},"required":["type","distance"],"additionalProperties":false}],"description":"How the length of the step is defined"}},"required":["type","label","intensity","length"],"additionalProperties":false,"description":"A single step of a structured workout"},"StructureRepetition":{"type":"object","properties":{"type":{"type":"string","enum":["repetition"]},"nRepetitions":{"type":"number","examples":[4]},"steps":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/StructureStep"},{"$ref":"#/components/schemas/StructureRepetition"}]},"description":"Steps executed at each repetition"}},"required":["type","nRepetitions","steps"],"additionalProperties":false,"description":"A repeated block of steps of a structured workout"},"TrainingPrescription":{"type":"object","properties":{"id":{"type":"string","examples":["tpr_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"date":{"type":"string","examples":["2026-08-12"],"format":"date"},"time":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Local time (HH:MM:SS)","examples":["06:30:00"]},"title":{"type":"string","examples":["3 x 12 min threshold"]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":[null]},"sport":{"type":"string","enum":["cycling","running","swimming","training","multisport","walking","crossCountrySkiing","alpineSkiing","rowing","hiking","hiit","fitnessEquipment","racket","tennis","golf","standUpPaddleboarding","snowboarding","meditation","kayaking","soccer","rockClimbing","iceSkating","windsurfing","mixedMartialArts","sailing","mountaineering","surfing","boating","basketball","eBiking","hockey","snowshoeing","inlineSkating","kitesurfing","mobility","tactical","hunting","fishing","jumpRope","boxing","floorClimbing","snorkeling","motorcycling","baseball","paddling","canoeing","rafting","rugby","discGolf","wakeboarding","wakesurfing","waterTubing","waterSkiing","waterSport","snowmobiling","dance","flying","americanFootball","diving","cricket","volleyball","wheelchairPushWalk","wheelchairPushRun","paraSport","hangGliding","skyDiving","jumpmaster","horsebackRiding","driving","motorSports","shooting","archery","winterSport","videoGaming","geocaching","lacrosse","poolApnea","teamSport","grinding","transition","generic"],"examples":["cycling"]},"subSport":{"anyOf":[{"type":"string","enum":["generic","treadmill","street","trail","track","spin","indoorCycling","road","mountain","downhill","recumbent","cyclocross","handCycling","trackCycling","indoorRowing","elliptical","stairClimbing","lapSwimming","openWater","flexibilityTraining","strengthTraining","warmUp","match","exercise","challenge","indoorSkiing","cardioTraining","indoorWalking","eBikeFitness","bmx","casualWalking","speedWalking","bikeToRunTransition","runToBikeTransition","swimToBikeTransition","atv","motocross","backcountry","resort","rcDrone","wingsuit","whitewater","skateSkiing","yoga","pilates","indoorRunning","gravelCycling","eBikeMountain","commuting","mixedSurface","navigate","trackMe","map","singleGasDiving","multiGasDiving","gaugeDiving","apneaDiving","apneaHunting","virtualActivity","obstacle","breathing","ccrDiving","sailRace","expedition","ultra","indoorClimbing","bouldering","hiit","indoorGrinding","huntingWithDogs","amrap","emom","tabata","esport","triathlon","duathlon","brick","swimRun","adventureRace","truckerWorkout","pickleball","padel","indoorWheelchairWalk","indoorWheelchairRun","indoorHandCycling","field","ice","ultimate","platform","squash","badminton","racquetball","tableTennis","overland","trollingMotor","flyCanopy","flyParaglide","flyParamotor","flyPressurized","flyNavigate","flyTimer","flyAltimeter","flyWx","flyVfr","flyIfr","dynamicApnea","enduro","rucking","rally","poolTriathlon","eBikeEnduro","timeTrial"]},{"type":"null"}],"examples":["road"]},"trainingStimulus":{"anyOf":[{"type":"string","enum":["neuromuscular","anaerobic","vo2max","threshold","tempo","aerobic","recovery","lactate clearance","durability","activation","test","race","heat"]},{"type":"null"}],"description":"Targeted physiological stimulus","examples":["threshold"]},"structure":{"anyOf":[{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/StructureStep"},{"$ref":"#/components/schemas/StructureRepetition"}]}},{"type":"null"}],"description":"Structured steps, null for unstructured prescriptions"},"zonesType":{"anyOf":[{"type":"string","enum":["power","speed","heartRate"]},{"type":"null"}],"description":"Which zones the structure intensities are expressed in","examples":["power"]},"distance":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[null]},"duration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds","examples":[4500]},"freeDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, assumed for each free-length step","examples":[600]},"elevationGain":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[null]},"averagePower":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In watts","examples":[210]},"work":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kJ","examples":[950]},"calories":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kcal","examples":[980]},"rpe":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"1 (very easy) to 10 (max effort)","examples":[7]},"carbIntake":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In g/h","examples":[60]},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":[null]},"activityId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Paired activity, once completed","examples":[null]}},"required":["id","date","time","title","description","sport","subSport","trainingStimulus","structure","zonesType","distance","duration","freeDuration","elevationGain","averagePower","work","calories","rpe","carbIntake","comment","activityId"],"additionalProperties":false,"description":"A planned workout prescribed to a user"},"Note":{"type":"object","properties":{"id":{"type":"string","examples":["not_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"type":{"type":"string","enum":["rest day","availability","training","medical","nutrition","mental","other"],"examples":["training"]},"title":{"type":"string","examples":["Race week reminders"]},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Keep the intensity low and hydrate well."]},"date":{"type":"string","examples":["2026-08-10"],"format":"date"},"time":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Local time (HH:MM:SS)","examples":[null]}},"required":["id","type","title","content","date","time"],"additionalProperties":false,"description":"A dated note written by the user or one of their coaches"},"Event":{"type":"object","properties":{"id":{"type":"string","examples":["evt_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"name":{"type":"string","examples":["Gran Fondo"]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":[null]},"date":{"type":"string","examples":["2026-09-14"],"format":"date"},"time":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Local start time (HH:MM:SS)","examples":["09:30:00"]},"sport":{"type":"string","enum":["cycling","running","swimming","training","multisport","walking","crossCountrySkiing","alpineSkiing","rowing","hiking","hiit","fitnessEquipment","racket","tennis","golf","standUpPaddleboarding","snowboarding","meditation","kayaking","soccer","rockClimbing","iceSkating","windsurfing","mixedMartialArts","sailing","mountaineering","surfing","boating","basketball","eBiking","hockey","snowshoeing","inlineSkating","kitesurfing","mobility","tactical","hunting","fishing","jumpRope","boxing","floorClimbing","snorkeling","motorcycling","baseball","paddling","canoeing","rafting","rugby","discGolf","wakeboarding","wakesurfing","waterTubing","waterSkiing","waterSport","snowmobiling","dance","flying","americanFootball","diving","cricket","volleyball","wheelchairPushWalk","wheelchairPushRun","paraSport","hangGliding","skyDiving","jumpmaster","horsebackRiding","driving","motorSports","shooting","archery","winterSport","videoGaming","geocaching","lacrosse","poolApnea","teamSport","grinding","transition","generic"],"examples":["cycling"]},"subSport":{"anyOf":[{"type":"string","enum":["generic","treadmill","street","trail","track","spin","indoorCycling","road","mountain","downhill","recumbent","cyclocross","handCycling","trackCycling","indoorRowing","elliptical","stairClimbing","lapSwimming","openWater","flexibilityTraining","strengthTraining","warmUp","match","exercise","challenge","indoorSkiing","cardioTraining","indoorWalking","eBikeFitness","bmx","casualWalking","speedWalking","bikeToRunTransition","runToBikeTransition","swimToBikeTransition","atv","motocross","backcountry","resort","rcDrone","wingsuit","whitewater","skateSkiing","yoga","pilates","indoorRunning","gravelCycling","eBikeMountain","commuting","mixedSurface","navigate","trackMe","map","singleGasDiving","multiGasDiving","gaugeDiving","apneaDiving","apneaHunting","virtualActivity","obstacle","breathing","ccrDiving","sailRace","expedition","ultra","indoorClimbing","bouldering","hiit","indoorGrinding","huntingWithDogs","amrap","emom","tabata","esport","triathlon","duathlon","brick","swimRun","adventureRace","truckerWorkout","pickleball","padel","indoorWheelchairWalk","indoorWheelchairRun","indoorHandCycling","field","ice","ultimate","platform","squash","badminton","racquetball","tableTennis","overland","trollingMotor","flyCanopy","flyParaglide","flyParamotor","flyPressurized","flyNavigate","flyTimer","flyAltimeter","flyWx","flyVfr","flyIfr","dynamicApnea","enduro","rucking","rally","poolTriathlon","eBikeEnduro","timeTrial"]},{"type":"null"}],"examples":["road"]},"distance":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[120000]},"elevationGain":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In meters","examples":[2400]},"duration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds","examples":[18000]},"work":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In kJ","examples":[3200]},"carbIntake":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In g/h","examples":[60]},"activityId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Paired activity, once completed","examples":[null]}},"required":["id","name","description","date","time","sport","subSport","distance","elevationGain","duration","work","carbIntake","activityId"],"additionalProperties":false,"description":"A planned event or race"},"Metric":{"type":"object","properties":{"id":{"type":"string","examples":["mtr_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"type":{"type":"string","enum":["weight","critical power","w prime","d prime","max power","vo2max","critical speed","max heart rate","resting heart rate","spo2","body fat"],"examples":["weight"]},"value":{"type":"number","description":"In `unit`","examples":[71.5]},"unit":{"anyOf":[{"type":"string","enum":["kg","kJ","W","J","mL/min/kg","m/s","bpm","%","m"]},{"type":"null"}],"examples":["kg"]},"source":{"anyOf":[{"type":"string","enum":["user","vekta"]},{"type":"null"}],"description":"'user' when measured by the user, 'vekta' when estimated by Vekta","examples":["user"]},"date":{"type":"string","examples":["2026-08-01"],"format":"date"},"sport":{"type":"string","enum":["global","cycling","running","swimming"],"examples":["global"]}},"required":["id","type","value","unit","source","date","sport"],"additionalProperties":false,"description":"A dated body or performance metric value"},"Sleep":{"type":"object","properties":{"id":{"type":"string","examples":["slp_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"day":{"type":"string","description":"Date of the local wake-up time","examples":["2026-08-01"],"format":"date"},"startedAt":{"type":"string","examples":["2026-07-31 22:45:00+00"]},"endedAt":{"type":"string","examples":["2026-08-01 06:30:00+00"]},"utcOffset":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In minutes from UTC","examples":[120]},"startedAtLocal":{"type":"string","examples":["2026-08-01 00:45:00+00"]},"endedAtLocal":{"type":"string","examples":["2026-08-01 08:30:00+00"]},"totalDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, light + REM + deep + no data","examples":[27900]},"inBedDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds","examples":[29700]},"awakeDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, awake while in bed","examples":[1800]},"lightDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, light sleep","examples":[14400]},"remDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, REM sleep","examples":[7200]},"deepDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, deep sleep","examples":[5400]},"noDataDuration":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In seconds, no device data","examples":[900]},"averageHrv":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In ms, RMSSD","examples":[62]},"restingHeartRate":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[46]},"skinBodyTemperature":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[33.8]},"skinBodyTemperatureDeviation":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"In °C from baseline","examples":[0.2]}},"required":["id","day","startedAt","endedAt","utcOffset","startedAtLocal","endedAtLocal","totalDuration","inBedDuration","awakeDuration","lightDuration","remDuration","deepDuration","noDataDuration","averageHrv","restingHeartRate","skinBodyTemperature","skinBodyTemperatureDeviation"],"additionalProperties":false,"description":"A night of sleep recorded by a connected provider"},"CreateWorkspaceInvitation":{"type":"object","properties":{"email":{"type":"string","description":"Email address of the person to invite","examples":["athlete@example.com"],"format":"email"},"role":{"type":"string","enum":["athlete","coach"],"examples":["athlete"]},"sendInvitationEmail":{"type":"boolean","description":"When true, Vekta emails the invitation code to the invitee. Defaults to false.","examples":[true]}},"required":["email","role"],"additionalProperties":false},"WorkspaceInvitation":{"type":"object","properties":{"id":{"type":"string","examples":["win_01JK4W2N9XQ3F5H7B8C6D2E9GT"]},"email":{"type":"string","examples":["athlete@example.com"]},"role":{"type":"string","enum":["athlete","coach","admin"],"examples":["athlete"]},"code":{"type":"string","description":"Six character code to join the workspace","examples":["7XK2QW"]},"expiresAt":{"type":"string","description":"ISO 8601 UTC","examples":["2026-08-28T09:30:00.000Z"]}},"required":["id","email","role","code","expiresAt"],"additionalProperties":false,"description":"A pending invitation to join a workspace"}},"securitySchemes":{"bearer":{"description":"Vekta api key, e.g. `Authorization: Bearer vk_...`","type":"http","scheme":"Bearer"}}},"security":[],"tags":[{"name":"Users","description":"Data of the users you have access to: yourself (`me`) and the athletes you coach."},{"name":"Activities","description":"Recorded activities of the users you have access to: summaries and raw time series."},{"name":"Training prescriptions","description":"Planned workouts prescribed to the users you have access to."},{"name":"Notes","description":"Notes on the calendars of the users you have access to, written by them or their coaches."},{"name":"Events","description":"Planned events and races of the users you have access to."},{"name":"Metrics","description":"Body and performance metrics of the users you have access to."},{"name":"Sleep","description":"Sleep recorded for the users you have access to by their connected providers."},{"name":"Workspaces","description":"Manage the workspaces where you are admin or coach."}],"servers":[{"url":"https://api.joinvekta.com"}]}