{"openapi":"3.1.0","info":{"title":"Vitruve API","description":"REST API for your organization’s own Vitruve data, with the writes an external system needs to keep Vitruve in sync. Full documentation: https://vitruve-docs-prod.web.app/api/","version":"1.0.0"},"servers":[{"url":"https://api-next.vitruve.fit/v1"}],"security":[{"ApiKey":[]}],"paths":{"/organization":{"get":{"summary":"Get your organization","description":"Returns the organization that owns the API key. Use it to confirm a key works and which organization it is scoped to.","operationId":"getOrganization","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","name":"Northgate Performance","category":"professional-team","measurementSystem":"metric","phoneNumber":null,"createdAt":"2025-06-10T09:00:00.000Z","updatedAt":"2026-01-21T15:40:12.000Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/athletes":{"get":{"summary":"List athletes","description":"Active athletes of your organization, ordered by surname, then name. Each athlete carries their membership and the ids of their teams.","operationId":"getAthletes","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive. Every word must match the name, surname or email, so a full name such as `Ana García` works.","schema":{"type":"string"}},{"name":"teamId","in":"query","required":false,"description":"Only athletes in this team.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","name":"Marta","surname":"Ibáñez","email":"marta.ibanez@example.com","isVerified":true,"profession":"athlete","gender":"female","measurementSystem":"metric","avatarPath":null,"height":172,"weight":64,"birthDate":"1998-04-12T00:00:00.000Z","dominantSide":"right","createdAt":"2025-09-02T08:14:31.402Z","updatedAt":"2026-03-18T10:22:05.117Z","deletedAt":null,"organizationsToUsers":[{"id":"0d2f6b8e-5a17-4c93-b4e1-93a7c0d58f21","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"dc82d01f-1136-4fcb-97dc-11a8b2203d98","createdAt":"2025-09-02T08:14:31.402Z","updatedAt":"2025-09-02T08:14:31.402Z","deletedAt":null}],"teams":[{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64"}]}],"meta":{"limit":2,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"post":{"summary":"Create an athlete","description":"Creates an athlete in your organization and answers it in the shape of `GET /athletes/{id}`.","operationId":"postAthletes","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7E]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","surname"],"properties":{"name":{"description":"First name, up to 255 characters.","type":"string"},"surname":{"description":"Last name, up to 255 characters.","type":"string"},"email":{"description":"Email address, stored as sent. Another user with the same email, in any letter case, answers `409`.","anyOf":[{"type":"string"},{"type":"null"}]},"gender":{"description":"Gender.","anyOf":[{"type":"string","enum":["male","female","other"]},{"type":"null"}]},"birthDate":{"description":"Date of birth: `YYYY-MM-DD` or an ISO 8601 datetime with an offset. Not in the future.","anyOf":[{"type":"string"},{"type":"null"}]},"dominantSide":{"description":"Dominant side.","anyOf":[{"type":"string","enum":["left","right"]},{"type":"null"}]},"measurementSystem":{"description":"Preferred measurement system.","anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}]},"height":{"description":"Height in cm, 0–300.","anyOf":[{"type":"integer"},{"type":"null"}]},"weight":{"description":"Body weight in kg, 0–500.","anyOf":[{"type":"integer"},{"type":"null"}]},"teamIds":{"description":"Teams of your organization to add the athlete to, at most 100.","type":"array","items":{"type":"string","format":"uuid"}}}},"example":{"name":"Lucas","surname":"Moreau","email":"lucas.moreau@example.com","gender":"male","birthDate":"2003-07-21","dominantSide":"left","measurementSystem":"metric","height":184,"weight":81,"teamIds":["9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64"]}}}},"responses":{"200":{"description":"Success","headers":{"Idempotent-Replayed":{"description":"`true` when the answer is the one kept for an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","name":"Lucas","surname":"Moreau","email":"lucas.moreau@example.com","isVerified":false,"profession":"athlete","gender":"male","measurementSystem":"metric","avatarPath":null,"height":184,"weight":81,"birthDate":"2003-07-21T00:00:00.000Z","dominantSide":"left","createdAt":"2026-10-13T09:30:12.418Z","updatedAt":"2026-10-13T09:30:12.418Z","deletedAt":null,"organizationsToUsers":[{"id":"a4c81e3f-0b67-4d29-95f2-6e1d7b3c08a5","userId":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"dc82d01f-1136-4fcb-97dc-11a8b2203d98","createdAt":"2026-10-13T09:30:12.418Z","updatedAt":"2026-10-13T09:30:12.418Z","deletedAt":null}],"teams":[{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"422":{"description":"The `Idempotency-Key` was already used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"This Idempotency-Key was already used for another request"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/athletes/{id}":{"get":{"summary":"Get an athlete","description":"One athlete of your organization.","operationId":"getAthletesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","name":"Marta","surname":"Ibáñez","email":"marta.ibanez@example.com","isVerified":true,"profession":"athlete","gender":"female","measurementSystem":"metric","avatarPath":null,"height":172,"weight":64,"birthDate":"1998-04-12T00:00:00.000Z","dominantSide":"right","createdAt":"2025-09-02T08:14:31.402Z","updatedAt":"2026-03-18T10:22:05.117Z","deletedAt":null,"organizationsToUsers":[{"id":"0d2f6b8e-5a17-4c93-b4e1-93a7c0d58f21","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"dc82d01f-1136-4fcb-97dc-11a8b2203d98","createdAt":"2025-09-02T08:14:31.402Z","updatedAt":"2025-09-02T08:14:31.402Z","deletedAt":null}],"teams":[{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"patch":{"summary":"Update an athlete","description":"Changes only the fields sent, and answers the updated athlete. `null` clears an optional field.","operationId":"patchAthletesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"description":"First name, up to 255 characters.","type":"string"},"surname":{"description":"Last name, up to 255 characters.","type":"string"},"email":{"description":"Email address, stored as sent. Another user with the same email, in any letter case, answers `409`.","anyOf":[{"type":"string"},{"type":"null"}]},"gender":{"description":"Gender.","anyOf":[{"type":"string","enum":["male","female","other"]},{"type":"null"}]},"birthDate":{"description":"Date of birth: `YYYY-MM-DD` or an ISO 8601 datetime with an offset. Not in the future.","anyOf":[{"type":"string"},{"type":"null"}]},"dominantSide":{"description":"Dominant side.","anyOf":[{"type":"string","enum":["left","right"]},{"type":"null"}]},"measurementSystem":{"description":"Preferred measurement system.","anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}]},"height":{"description":"Height in cm, 0–300.","anyOf":[{"type":"integer"},{"type":"null"}]},"weight":{"description":"Body weight in kg, 0–500.","anyOf":[{"type":"integer"},{"type":"null"}]}},"minProperties":1},"example":{"weight":83,"dominantSide":"right"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","name":"Lucas","surname":"Moreau","email":"lucas.moreau@example.com","isVerified":false,"profession":"athlete","gender":"male","measurementSystem":"metric","avatarPath":null,"height":184,"weight":83,"birthDate":"2003-07-21T00:00:00.000Z","dominantSide":"right","createdAt":"2026-10-13T09:30:12.418Z","updatedAt":"2026-10-14T07:05:40.220Z","deletedAt":null,"organizationsToUsers":[{"id":"a4c81e3f-0b67-4d29-95f2-6e1d7b3c08a5","userId":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"dc82d01f-1136-4fcb-97dc-11a8b2203d98","createdAt":"2026-10-13T09:30:12.418Z","updatedAt":"2026-10-13T09:30:12.418Z","deletedAt":null}],"teams":[{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Delete an athlete","description":"Removes an athlete from your organization and answers the athlete as it was before.","operationId":"deleteAthletesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","name":"Lucas","surname":"Moreau","email":"lucas.moreau@example.com","isVerified":false,"profession":"athlete","gender":"male","measurementSystem":"metric","avatarPath":null,"height":184,"weight":83,"birthDate":"2003-07-21T00:00:00.000Z","dominantSide":"right","createdAt":"2026-10-13T09:30:12.418Z","updatedAt":"2026-10-14T07:05:40.220Z","deletedAt":null,"organizationsToUsers":[{"id":"a4c81e3f-0b67-4d29-95f2-6e1d7b3c08a5","userId":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"dc82d01f-1136-4fcb-97dc-11a8b2203d98","createdAt":"2026-10-13T09:30:12.418Z","updatedAt":"2026-10-13T09:30:12.418Z","deletedAt":null}],"teams":[{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/athletes/{id}/profile":{"get":{"summary":"Get an athlete’s sport profile","description":"The athlete’s sport profile with its dated `versions`. The version with `validTo: null` is the current one.","operationId":"getAthletesIdProfile","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"6e0b9d41-c2a8-4f35-8b17-d5a3e92c0f68","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","revision":2,"createdAt":"2025-09-02T08:20:00.000Z","updatedAt":"2026-02-01T09:00:00.000Z","deletedAt":null,"versions":[{"id":"b3a8d5f0-71e2-4c69-90a4-e1c7f2d83b56","profileId":"6e0b9d41-c2a8-4f35-8b17-d5a3e92c0f68","validFrom":"2026-02-01T00:00:00.000Z","validTo":null,"sport":"basketball","position":"guard","competitionLevel":"professional","squad":"first-team","strengthTrainingStartedYear":2016,"recordedAt":"2026-02-01T09:00:00.000Z","recordedByUserId":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/coaches":{"get":{"summary":"List coaches","description":"Owners and coaches of your organization, with their membership.","operationId":"getCoaches","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive. Every word must match the name, surname or email, so a full name such as `Ana García` works.","schema":{"type":"string"}},{"name":"roleId","in":"query","required":false,"description":"Only owners (`4aa018e6-8b22-40b1-8d07-ab4f1af51330`) or only coaches (`ef736bad-c98e-410e-bf26-af834332153b`).","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","name":"Daniel","surname":"Okafor","email":"daniel.okafor@northgate.example","isVerified":true,"profession":"coach","organizationsToUsers":[{"id":"9c4e1a73-d085-4b2f-a6e8-31f7b5d02c94","userId":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"ef736bad-c98e-410e-bf26-af834332153b","deletedAt":null}]}],"meta":{"limit":25,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/coaches/{id}":{"get":{"summary":"Get a coach","description":"One owner or coach of your organization.","operationId":"getCoachesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","name":"Daniel","surname":"Okafor","email":"daniel.okafor@northgate.example","isVerified":true,"profession":"coach","organizationsToUsers":[{"userId":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"ef736bad-c98e-410e-bf26-af834332153b"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Remove a coach","description":"Removes a coach from your organization and answers the coach as they were. Their account and athlete assignments are kept, so a coach added back sees the same athletes.","operationId":"deleteCoachesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","name":"Daniel","surname":"Okafor","email":"daniel.okafor@northgate.example","isVerified":true,"profession":"coach","organizationsToUsers":[{"userId":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","roleId":"ef736bad-c98e-410e-bf26-af834332153b"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/coaches/{id}/athletes":{"get":{"summary":"List a coach's athletes","description":"The ids of the athletes a coach is assigned to: every athlete of your organization except those unassigned from them. The owner’s id answers every athlete: the owner is never unassigned.","operationId":"getCoachesIdAthletes","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"athleteIds":["3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"put":{"summary":"Replace a coach's athletes","description":"Sets the athletes a coach is assigned to: every other athlete of your organization is unassigned from them. Answers the new `athleteIds`, sorted.","operationId":"putCoachesIdAthletes","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["athleteIds"],"properties":{"athleteIds":{"description":"Every athlete the coach is assigned to, at most 3,000. `[]` unassigns them all.","type":"array","items":{"type":"string","format":"uuid"}}}},"example":{"athleteIds":["6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42","3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"athleteIds":["3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42"]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/coaches/{id}/athletes/{athleteId}":{"put":{"summary":"Assign an athlete to a coach","description":"Assigns one athlete to a coach. An athlete already assigned stays assigned.","operationId":"putCoachesIdAthletesAthleteId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}},{"name":"athleteId","in":"path","required":true,"description":"Athlete id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"coachId":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","athleteId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","isAssigned":true}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Unassign an athlete from a coach","description":"Unassigns one athlete from a coach, who stops seeing them. An athlete already unassigned stays unassigned.","operationId":"deleteCoachesIdAthletesAthleteId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}},{"name":"athleteId","in":"path","required":true,"description":"Athlete id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"coachId":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","athleteId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","isAssigned":false}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/teams":{"get":{"summary":"List teams","description":"Teams of your organization, ordered by name, each with the ids of its athletes.","operationId":"getTeams","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the team name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64","name":"First team","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2025-09-01T10:00:00.000Z","updatedAt":"2025-09-01T10:00:00.000Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}]}],"meta":{"limit":10,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"post":{"summary":"Create a team","description":"Creates a team, with its athletes if you send them, and answers it in the shape of `GET /teams/{id}`.","operationId":"postTeams","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7E]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"description":"Team name, up to 255 characters.","type":"string"},"athleteIds":{"description":"Athletes of your organization in the team, at most 3,000.","type":"array","items":{"type":"string","format":"uuid"}}}},"example":{"name":"U23 squad","athleteIds":["c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"]}}}},"responses":{"200":{"description":"Success","headers":{"Idempotent-Replayed":{"description":"`true` when the answer is the one kept for an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"e3a7c915-4b2d-4f68-9a0e-7c5b1d83f264","name":"U23 squad","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-10-13T09:32:05.104Z","updatedAt":"2026-10-13T09:32:05.104Z","deletedAt":null,"users":[{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"422":{"description":"The `Idempotency-Key` was already used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"This Idempotency-Key was already used for another request"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/teams/{id}":{"get":{"summary":"Get a team","description":"One team with the ids of its athletes.","operationId":"getTeamsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64","name":"First team","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"patch":{"summary":"Update a team","description":"Renames a team or replaces its athletes, and answers the team.","operationId":"patchTeamsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"description":"Team name, up to 255 characters.","type":"string"},"athleteIds":{"description":"The team’s athletes, at most 3,000. Replaces the current ones; staff members the app added to the team stay.","type":"array","items":{"type":"string","format":"uuid"}}},"minProperties":1},"example":{"athleteIds":["c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"e3a7c915-4b2d-4f68-9a0e-7c5b1d83f264","name":"U23 squad","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-10-13T09:32:05.104Z","updatedAt":"2026-10-14T07:06:11.532Z","deletedAt":null,"users":[{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"},{"id":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Delete a team","description":"Deletes a team for good and answers it as it was. Its athletes stay in your organization.","operationId":"deleteTeamsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"e3a7c915-4b2d-4f68-9a0e-7c5b1d83f264","name":"U23 squad","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-10-13T09:32:05.104Z","updatedAt":"2026-10-14T07:06:11.532Z","deletedAt":null,"users":[{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"},{"id":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/teams/{id}/athletes/{athleteId}":{"put":{"summary":"Add an athlete to a team","description":"Adds one athlete to a team and answers the team. An athlete already in it stays.","operationId":"putTeamsIdAthletesAthleteId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}},{"name":"athleteId","in":"path","required":true,"description":"Athlete id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64","name":"First team","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2025-09-01T10:00:00.000Z","updatedAt":"2026-10-13T09:35:48.009Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"},{"id":"6d2b8f14-a9c3-4e57-8b06-f31c7a5d9e42"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Remove an athlete from a team","description":"Removes one athlete from a team and answers the team. The athlete stays in your organization.","operationId":"deleteTeamsIdAthletesAthleteId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}},{"name":"athleteId","in":"path","required":true,"description":"Athlete id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64","name":"First team","avatarPath":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2025-09-01T10:00:00.000Z","updatedAt":"2026-10-13T09:36:20.771Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/workouts":{"get":{"summary":"List workouts","description":"Athlete workouts of your organization, without their content. Templates are excluded; they are served by `/templates/workouts`. Fetch a workout’s blocks, sets and metrics with `GET /workouts/{id}`.","operationId":"getWorkouts","parameters":[{"name":"userId","in":"query","required":false,"description":"Only workouts of this athlete.","schema":{"type":"string","format":"uuid"}},{"name":"exerciseId","in":"query","required":false,"description":"Only workouts with at least one prescription of this exercise.","schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","required":false,"description":"`completed` for performed workouts, `pending` for assigned workouts not yet performed.","schema":{"type":"string","enum":["completed","pending"]}},{"name":"trainingType","in":"query","required":false,"description":"Only workouts with at least one prescription of this training type.","schema":{"type":"string","enum":["vbt","jump","sprint","reaction"]}},{"name":"from","in":"query","required":false,"description":"Inclusive lower bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date starts at 00:00 in `timezone`, or at the change on a day whose midnight a daylight-saving change skips.","schema":{"type":"string"}},{"name":"to","in":"query","required":false,"description":"Inclusive upper bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date covers that whole day in `timezone`.","schema":{"type":"string"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. A bare `from` / `to` date covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes with `Z` or an offset are taken as given.","schema":{"type":"string","default":"UTC"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","name":"Lower body strength A","isTemplate":false,"rpe":8,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":null,"completedAt":"2026-03-17T10:41:52.318Z","startedAt":"2026-03-17T09:58:04.902Z","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:41:52.877Z","deletedAt":null,"testType":null},{"id":"5a0e7c3d-91b4-4f26-8d58-c3e2a1f6b097","name":"Upper body power","isTemplate":false,"rpe":7,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":null,"completedAt":"2026-03-14T17:32:10.441Z","startedAt":"2026-03-14T16:55:47.019Z","createdAt":"2026-03-14T16:55:46.870Z","updatedAt":"2026-03-14T17:32:10.902Z","deletedAt":null,"testType":null}],"meta":{"limit":2,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/workouts/{id}":{"get":{"summary":"Get a workout","description":"One athlete workout with its full tree: blocks → prescriptions groups → prescriptions → serie prescriptions and series, each series with its values, set-level metrics and repetitions. Templates return 404 here; use `GET /templates/workouts/{id}`.","operationId":"getWorkoutsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","name":"Lower body strength A","isTemplate":false,"rpe":8,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":null,"completedAt":"2026-03-17T10:41:52.318Z","startedAt":"2026-03-17T09:58:04.902Z","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:41:52.877Z","deletedAt":null,"testType":null,"blocks":[{"id":"0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79","name":"Main lifts","isTemplate":false,"order":0,"workoutId":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null,"prescriptionsGroups":[{"id":"4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142","name":"Back squat","isTemplate":false,"order":0,"blockId":"0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null,"prescriptions":[{"id":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":false,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null,"seriePrescriptions":[{"id":"e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","prescriptionTypeId":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isRange":false,"isTopMode":false,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null},{"id":"9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","prescriptionTypeId":"62c8a0f4-3d19-4e7b-a5c2-f0b9d14e8a63","unitId":"b7e05a92-4f3c-4d18-86a1-2c9e7d3b5f40","order":1,"isRange":false,"isTopMode":false,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null}],"series":[{"id":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","order":0,"completedAt":"2026-03-17T10:06:30.512Z","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null,"serieValues":[{"id":"0f6d2b84-a7e1-4c39-b05d-e9a3c8f1724b","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","seriePrescriptionId":"e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":100,"valueExecuted":100,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null},{"id":"c5a19e37-04bd-4f62-8e7a-3b2d6f0c9a18","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","seriePrescriptionId":"9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":5,"valueExecuted":5,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null}],"metricValues":[{"id":"71e4c0a9-5d36-4b82-a1f7-9c8e2b4d0563","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","value":0.61,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":null,"serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:06:30.512Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null}],"repetitions":[{"id":"e19a4d83-5b60-4c27-a8f1-0d7c3e52b946","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","type":"concentric","repNumber":1,"repIndex":0,"createdAt":"2026-03-17T10:05:58.140Z","updatedAt":"2026-03-17T10:05:58.140Z","deletedAt":null,"metricValues":[{"id":"86a1c4e7-3b05-4d9f-92e8-5f1d7c0a3b94","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","value":0.64,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":"e19a4d83-5b60-4c27-a8f1-0d7c3e52b946","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:05:58.140Z","updatedAt":"2026-03-17T10:05:58.140Z","deletedAt":null},{"id":"3c7e9b20-a5f1-4d86-b2c4-71d0e8f3a659","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"2a9c6e41-b0d8-4f73-9e15-84d3c7a0b2f6","value":1.12,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":"e19a4d83-5b60-4c27-a8f1-0d7c3e52b946","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:05:58.140Z","updatedAt":"2026-03-17T10:05:58.140Z","deletedAt":null}]},{"id":"48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","type":"concentric","repNumber":2,"repIndex":1,"createdAt":"2026-03-17T10:06:03.377Z","updatedAt":"2026-03-17T10:06:03.377Z","deletedAt":null,"metricValues":[{"id":"d9c2a5e0-8b17-4f4d-a36e-5e0b7c1f9d84","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","value":0.62,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":"48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:06:03.377Z","updatedAt":"2026-03-17T10:06:03.377Z","deletedAt":null}]}]}]}]}]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/active-workouts":{"get":{"summary":"List active workouts","description":"Sessions your athletes are performing right now, without their content. A session leaves this list when the athlete finishes it (it is then in `GET /workouts`) or discards it. Fetch one with `GET /active-workouts/{id}`.","operationId":"getActiveWorkouts","parameters":[{"name":"userId","in":"query","required":false,"description":"Only the sessions of this athlete.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","version":12,"createdAt":"2026-03-17T09:58:05.114Z","updatedAt":"2026-03-17T10:21:37.502Z"}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/active-workouts/{id}":{"get":{"summary":"Get an active workout","description":"One session in progress as the app last saved it, in the same tree as `GET /workouts/{id}`: the sets done so far with their values, set-level metrics and repetitions.","operationId":"getActiveWorkoutsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","name":"Lower body strength A","isTemplate":false,"rpe":8,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":null,"completedAt":null,"startedAt":"2026-03-17T09:58:04.902Z","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:21:37.502Z","deletedAt":null,"testType":null,"blocks":[{"id":"0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79","name":"Main lifts","isTemplate":false,"order":0,"workoutId":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null,"prescriptionsGroups":[{"id":"4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142","name":"Back squat","isTemplate":false,"order":0,"blockId":"0b6d3a9e-7f21-4c58-9d14-e82a5f3c6b79","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null,"prescriptions":[{"id":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"4d1e8c75-2a93-4f06-b8e7-39c0a6d5f142","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":false,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null,"seriePrescriptions":[{"id":"e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","prescriptionTypeId":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isRange":false,"isTopMode":false,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null},{"id":"9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","prescriptionTypeId":"62c8a0f4-3d19-4e7b-a5c2-f0b9d14e8a63","unitId":"b7e05a92-4f3c-4d18-86a1-2c9e7d3b5f40","order":1,"isRange":false,"isTopMode":false,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-10T16:20:11.004Z","deletedAt":null}],"series":[{"id":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"a7f35c20-9e18-4d64-8b3a-5c2d0e91f6b8","order":0,"completedAt":"2026-03-17T10:06:30.512Z","createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null,"serieValues":[{"id":"0f6d2b84-a7e1-4c39-b05d-e9a3c8f1724b","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","seriePrescriptionId":"e3b72d05-6a1c-4f98-b4e3-1d8c9a5f0726","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":100,"valueExecuted":100,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null},{"id":"c5a19e37-04bd-4f62-8e7a-3b2d6f0c9a18","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","seriePrescriptionId":"9d4f1b68-c2e7-4a05-93d1-7b6e0f2a8c34","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":5,"valueExecuted":5,"createdAt":"2026-03-10T16:20:11.004Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null}],"metricValues":[{"id":"71e4c0a9-5d36-4b82-a1f7-9c8e2b4d0563","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","value":0.61,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":null,"serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:06:30.512Z","updatedAt":"2026-03-17T10:06:30.512Z","deletedAt":null}],"repetitions":[{"id":"e19a4d83-5b60-4c27-a8f1-0d7c3e52b946","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","type":"concentric","repNumber":1,"repIndex":0,"createdAt":"2026-03-17T10:05:58.140Z","updatedAt":"2026-03-17T10:05:58.140Z","deletedAt":null,"metricValues":[{"id":"86a1c4e7-3b05-4d9f-92e8-5f1d7c0a3b94","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","value":0.64,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":"e19a4d83-5b60-4c27-a8f1-0d7c3e52b946","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:05:58.140Z","updatedAt":"2026-03-17T10:05:58.140Z","deletedAt":null},{"id":"3c7e9b20-a5f1-4d86-b2c4-71d0e8f3a659","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"2a9c6e41-b0d8-4f73-9e15-84d3c7a0b2f6","value":1.12,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":"e19a4d83-5b60-4c27-a8f1-0d7c3e52b946","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:05:58.140Z","updatedAt":"2026-03-17T10:05:58.140Z","deletedAt":null}]},{"id":"48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","type":"concentric","repNumber":2,"repIndex":1,"createdAt":"2026-03-17T10:06:03.377Z","updatedAt":"2026-03-17T10:06:03.377Z","deletedAt":null,"metricValues":[{"id":"d9c2a5e0-8b17-4f4d-a36e-5e0b7c1f9d84","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","value":0.62,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","repetitionId":"48b3f6d1-e2a0-4c95-b7d8-06f1a9c3e5b2","serieId":"68c2e5b1-0d47-4a93-9f6e-b13a7d84c250","createdAt":"2026-03-17T10:06:03.377Z","updatedAt":"2026-03-17T10:06:03.377Z","deletedAt":null}]}]}]}]}]}],"version":12}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/programs":{"get":{"summary":"List programs","description":"Programs of your organization, newest first, each with the ids of its assigned athletes.","operationId":"getPrograms","parameters":[{"name":"isTemplate","in":"query","required":false,"description":"`true` for program templates only, `false` for programs that are not templates. Omit for both.","schema":{"type":"boolean"}},{"name":"userId","in":"query","required":false,"description":"Only programs assigned to this athlete.","schema":{"type":"string","format":"uuid"}},{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the program name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53","name":"Pre-season strength block","isTemplate":false,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","startedAt":"2026-03-02T00:00:00.000Z","createdAt":"2026-02-24T11:05:42.610Z","updatedAt":"2026-03-01T18:12:09.233Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}]}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/programs/{id}":{"get":{"summary":"Get a program","description":"One program with its assigned athletes and its phases, each with its scheduled workouts and the workout row they point to.","operationId":"getProgramsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53","name":"Pre-season strength block","isTemplate":false,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","startedAt":"2026-03-02T00:00:00.000Z","createdAt":"2026-02-24T11:05:42.610Z","updatedAt":"2026-03-01T18:12:09.233Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}],"phases":[{"id":"b45e0c97-1a68-4d32-9c7f-82f3d6a1e0b4","name":"Accumulation","isTemplate":false,"order":0,"weeks":4,"programId":"2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-24T11:05:42.610Z","updatedAt":"2026-02-24T11:05:42.610Z","deletedAt":null,"scheduledWorkouts":[{"id":"73d9f1c8-e526-4a0b-b4d3-9e8a2c5f6710","color":"#4C8BF5","phaseId":"b45e0c97-1a68-4d32-9c7f-82f3d6a1e0b4","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","include":[],"exclude":[14],"recurrence":[0,3],"createdAt":"2026-02-24T11:05:42.610Z","updatedAt":"2026-02-24T11:05:42.610Z","deletedAt":null,"workout":{"id":"a3d81f6c-07e5-4b29-9c4a-e5f2b0d7c813","name":"Lower body strength A","isTemplate":false,"rpe":null,"userId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":"73d9f1c8-e526-4a0b-b4d3-9e8a2c5f6710","completedAt":null,"startedAt":null,"createdAt":"2026-02-24T11:05:42.610Z","updatedAt":"2026-02-24T11:05:42.610Z","deletedAt":null,"testType":null}},{"id":"f0a7d3c6-29e8-4b51-9c04-a6b1e8d2f375","color":null,"phaseId":"b45e0c97-1a68-4d32-9c7f-82f3d6a1e0b4","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","include":[26],"exclude":[],"recurrence":[],"createdAt":"2026-02-24T11:07:15.032Z","updatedAt":"2026-02-24T11:07:15.032Z","deletedAt":null,"workout":{"id":"e86b2c47-d150-4f3a-a8e9-2f7c4d06b5a1","name":"Jump test","isTemplate":false,"rpe":null,"userId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":"f0a7d3c6-29e8-4b51-9c04-a6b1e8d2f375","completedAt":null,"startedAt":null,"createdAt":"2026-02-24T11:07:15.032Z","updatedAt":"2026-02-24T11:07:15.032Z","deletedAt":null,"testType":"vertical_jump"}}]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/programs/{id}/attendance":{"get":{"summary":"Get a program’s attendance","description":"How far a program’s athletes are keeping to it: every planned session that is already due, matched to the sessions they performed, per athlete, per team and per planned session. The same figures as the program page of the Vitruve app.","operationId":"getProgramsIdAttendance","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. Decides what “today” is, and so which sessions are already due.","schema":{"type":"string","default":"UTC"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"programId":"2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53","asOf":"2026-03-25","startDateKey":"2026-02-24","endDateKey":"2026-04-21","overall":{"athletesCount":2,"due":18,"fulfilled":15,"missed":3,"rate":0.8333},"completion":{"total":32,"completed":15,"remaining":17},"athletes":[{"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","due":9,"fulfilled":9,"missed":0,"rate":1,"unplanned":1},{"userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","due":9,"fulfilled":6,"missed":3,"rate":0.6667,"unplanned":0}],"teams":[{"teamId":"9a4f6d13-8b25-4c7e-93a0-1f5d2e8b7c64","name":"First team","athletesCount":2,"due":18,"fulfilled":15,"missed":3,"rate":0.8333}],"occurrences":[{"scheduledWorkoutId":"73d9f1c8-e526-4a0b-b4d3-9e8a2c5f6710","name":"Lower body strength A","dateKey":"2026-02-24","due":2,"fulfilled":2,"rate":1}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/programs/{id}/effectiveness":{"get":{"summary":"Get a program’s effectiveness","description":"How a program’s athletes are progressing towards its goals: each goal (a metric, how it is aggregated, increase, decrease or reach, and a target) evaluated per athlete and for the group, with where the group should be by now. The same figures as the program page of the Vitruve app.","operationId":"getProgramsIdEffectiveness","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. Decides what “today” is and which calendar day each measurement falls on.","schema":{"type":"string","default":"UTC"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"programId":"2f8b6a04-d3c1-4e95-87a2-c64e1b9d0f53","asOf":"2026-03-25","startDateKey":"2026-02-24","endDateKey":"2026-04-21","timeShare":0.5179,"goals":[{"goal":{"id":"d8c41f27-5a9e-4b03-a6f2-0e7b3c95d184","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","calculation":"max","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","condition":"increase","target":5},"athletes":[{"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","baseline":0.92,"current":0.97,"changePct":5.43,"achieved":true,"progress":1,"ratio":1.087},{"userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","baseline":0.88,"current":0.9,"changePct":2.27,"achieved":false,"progress":0.4545,"ratio":0.4545}],"summary":{"evaluated":2,"achieved":1,"achievedShare":0.5,"meanChangePct":3.85,"meanProgress":0.7273},"expectedProgress":0.5179,"series":{"points":[{"dateKey":"2026-02-24","value":0},{"dateKey":"2026-03-02","value":0.21},{"dateKey":"2026-03-25","value":0.7273}],"projection":[{"dateKey":"2026-02-24","value":0},{"dateKey":"2026-04-20","value":1}]}}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/workouts":{"get":{"summary":"List workout templates","description":"Workout templates of your organization’s library, newest first, without their content.","operationId":"getTemplatesWorkouts","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the template name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"41d6e9b3-a8f5-4c07-92e1-d5b0c3a76f84","name":"Lower body strength","isTemplate":true,"rpe":null,"userId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":null,"completedAt":null,"startedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"testType":null}],"meta":{"limit":20,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/workouts/{id}":{"get":{"summary":"Get a workout template","description":"One workout template with its full tree: blocks → prescription groups → prescriptions → parameters and planned sets.","operationId":"getTemplatesWorkoutsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"41d6e9b3-a8f5-4c07-92e1-d5b0c3a76f84","name":"Lower body strength","isTemplate":true,"rpe":null,"userId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":null,"completedAt":null,"startedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"testType":null,"blocks":[{"id":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","name":"Strength","isTemplate":true,"order":0,"workoutId":"41d6e9b3-a8f5-4c07-92e1-d5b0c3a76f84","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"prescriptionsGroups":[{"id":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Main lift","isTemplate":true,"order":0,"blockId":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"prescriptions":[{"id":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":true,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"seriePrescriptions":[{"id":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","prescriptionTypeId":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isRange":false,"isTopMode":false,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"series":[{"id":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","order":0,"completedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"serieValues":[{"id":"5f03d8b6-e917-4c2a-8b45-c6a2f1e7d390","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","seriePrescriptionId":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":80,"valueExecuted":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"metricValues":[],"repetitions":[]}]}]}]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/phases":{"get":{"summary":"List phase templates","description":"Phase templates of your organization’s library, newest first, without their scheduled workouts.","operationId":"getTemplatesPhases","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the template name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"d71a5c38-6e04-4f9b-a2c7-8b3d0f6e1a95","name":"Accumulation","isTemplate":true,"order":null,"weeks":4,"programId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"meta":{"limit":20,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/phases/{id}":{"get":{"summary":"Get a phase template","description":"One phase template with its scheduled workouts, oldest first. Each scheduled workout carries its workout row, without content.","operationId":"getTemplatesPhasesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"d71a5c38-6e04-4f9b-a2c7-8b3d0f6e1a95","name":"Accumulation","isTemplate":true,"order":null,"weeks":4,"programId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"scheduledWorkouts":[{"id":"30e8b6f2-d5a9-4c17-9e63-a4f1c07b2d58","color":"#69E0C1","phaseId":"d71a5c38-6e04-4f9b-a2c7-8b3d0f6e1a95","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","include":[],"exclude":[],"recurrence":[1,4],"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"workout":{"id":"c9f42e60-17b8-4d3a-b5e1-6d0a8c3f9b27","name":"Lower body strength","isTemplate":true,"rpe":null,"userId":null,"organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","scheduledWorkoutId":"30e8b6f2-d5a9-4c17-9e63-a4f1c07b2d58","completedAt":null,"startedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"testType":null}}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/blocks":{"get":{"summary":"List block templates","description":"Block templates of your organization’s library, newest first, without their content.","operationId":"getTemplatesBlocks","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the template name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","name":"Strength","isTemplate":true,"order":0,"workoutId":"41d6e9b3-a8f5-4c07-92e1-d5b0c3a76f84","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"meta":{"limit":20,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/blocks/{id}":{"get":{"summary":"Get a block template","description":"One block template with its tree: prescription groups → prescriptions → parameters and planned sets.","operationId":"getTemplatesBlocksId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","name":"Strength","isTemplate":true,"order":0,"workoutId":"41d6e9b3-a8f5-4c07-92e1-d5b0c3a76f84","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"prescriptionsGroups":[{"id":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Main lift","isTemplate":true,"order":0,"blockId":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"prescriptions":[{"id":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":true,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"seriePrescriptions":[{"id":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","prescriptionTypeId":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isRange":false,"isTopMode":false,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"series":[{"id":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","order":0,"completedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"serieValues":[{"id":"5f03d8b6-e917-4c2a-8b45-c6a2f1e7d390","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","seriePrescriptionId":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":80,"valueExecuted":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"metricValues":[],"repetitions":[]}]}]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/prescriptions-groups":{"get":{"summary":"List prescription group templates","description":"Prescription group (superset) templates of your organization’s library, newest first, without their content.","operationId":"getTemplatesPrescriptionsGroups","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the template name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Main lift","isTemplate":true,"order":0,"blockId":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"meta":{"limit":20,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/prescriptions-groups/{id}":{"get":{"summary":"Get a prescription group template","description":"One prescription group template with its prescriptions, their parameters and planned sets.","operationId":"getTemplatesPrescriptionsGroupsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Main lift","isTemplate":true,"order":0,"blockId":"6a2f9d14-b8c3-4e70-a5d1-0c7e3b94f826","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"prescriptions":[{"id":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":true,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"seriePrescriptions":[{"id":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","prescriptionTypeId":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isRange":false,"isTopMode":false,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"series":[{"id":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","order":0,"completedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"serieValues":[{"id":"5f03d8b6-e917-4c2a-8b45-c6a2f1e7d390","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","seriePrescriptionId":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":80,"valueExecuted":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"metricValues":[],"repetitions":[]}]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/prescriptions":{"get":{"summary":"List prescription templates","description":"Single-exercise templates of your organization’s library, newest first, without their parameters and sets.","operationId":"getTemplatesPrescriptions","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the template name.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":true,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"meta":{"limit":20,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/templates/prescriptions/{id}":{"get":{"summary":"Get a prescription template","description":"One single-exercise template with its parameters (`seriePrescriptions`) and planned sets (`series`).","operationId":"getTemplatesPrescriptionsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","prescriptionsGroupId":"e8b40c7d-5f19-4a26-9d83-2b6a1e0f7c45","name":"Back squat","order":0,"note":"Stop the set if mean velocity drops below 0.55 m/s.","isTemplate":true,"isVbt":true,"trainingType":"vbt","trainingAlgorithm":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"seriePrescriptions":[{"id":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","prescriptionTypeId":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isRange":false,"isTopMode":false,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"series":[{"id":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","prescriptionId":"1f7c3e95-a2d8-4b61-8e04-d93b5a2c6f17","order":0,"completedAt":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null,"serieValues":[{"id":"5f03d8b6-e917-4c2a-8b45-c6a2f1e7d390","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","serieId":"b2c86f41-03ad-4e95-b7d2-5e18a9c04f63","seriePrescriptionId":"9d5e2a07-c4b1-4f38-a6e9-71f0d3c8b524","valuePrescriptedInf":null,"valuePrescriptedSup":null,"valuePrescripted":80,"valueExecuted":null,"createdAt":"2026-02-11T09:30:00.000Z","updatedAt":"2026-02-11T09:30:00.000Z","deletedAt":null}],"metricValues":[],"repetitions":[]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/equations":{"get":{"summary":"List load-velocity profiles","description":"Load-velocity profiles of your organization’s athletes, newest first: the fitted coefficients without the points they were fitted on.","operationId":"getEquations","parameters":[{"name":"userId","in":"query","required":false,"description":"Only profiles of this athlete.","schema":{"type":"string","format":"uuid"}},{"name":"exerciseId","in":"query","required":false,"description":"Only profiles of this exercise.","schema":{"type":"string","format":"uuid"}},{"name":"metricId","in":"query","required":false,"description":"Only profiles fitted on this velocity metric.","schema":{"type":"string","format":"uuid"}},{"name":"isSelected","in":"query","required":false,"description":"`true` for the profiles the app uses, `false` for the others.","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Back squat LVP","a":0,"b":-64.286,"c":119.286,"r2":0.987,"isSelected":true,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","deletedAt":null}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"post":{"summary":"Create a load-velocity profile","description":"Creates a load-velocity profile and makes it the athlete’s selected one for the exercise. Answers it in the shape of `GET /equations/{id}`.","operationId":"postEquations","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7E]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["userId","exerciseId","metricId","b","c"],"properties":{"userId":{"description":"Athlete of your organization.","type":"string","format":"uuid"},"exerciseId":{"description":"A load-velocity exercise, global or your own: not a jump, sprint or reaction one.","type":"string","format":"uuid"},"metricId":{"description":"Velocity metric the profile is fitted on. See `GET /metrics?isEquationMetric=true`.","type":"string","format":"uuid"},"name":{"description":"Profile name, up to 255 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"a":{"description":"Only `0`: profiles are linear. Any other value answers `400`.","type":"number"},"b":{"description":"Slope: load as % of 1RM = `b`·velocity (m/s) + `c`.","type":"number"},"c":{"description":"Intercept, in %1RM.","type":"number"},"r2":{"description":"Goodness of fit, 0–1.","anyOf":[{"type":"number"},{"type":"null"}]},"equationSeries":{"description":"The tested sets, in order, at most 100: `weight` in kg and `velocity` in m/s, both 0 or more.","type":"array","items":{"type":"object","additionalProperties":false,"required":["weight","velocity"],"properties":{"weight":{"description":"Load lifted, in kg.","type":"number"},"velocity":{"description":"Velocity at that load, in m/s.","type":"number"}}}}}},"example":{"userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Back squat LVP","b":-61.9,"c":117.4,"r2":0.991,"equationSeries":[{"weight":70,"velocity":1.02},{"weight":90,"velocity":0.81},{"weight":110,"velocity":0.57}]}}}},"responses":{"200":{"description":"Success","headers":{"Idempotent-Replayed":{"description":"`true` when the answer is the one kept for an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Back squat LVP","a":0,"b":-61.9,"c":117.4,"r2":0.991,"isSelected":true,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","deletedAt":null,"equationSeries":[{"id":"0f6a2d94-7c1e-4b38-a5d0-93e7b1c4f826","equationId":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","weight":70,"velocity":1.02,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","order":0},{"id":"d35b8e10-49f2-4a67-8c1b-2e6f0a9d7c53","equationId":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","weight":90,"velocity":0.81,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","order":1},{"id":"7e19c4b2-a053-4d8e-b6f7-c0d2915a3e48","equationId":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","weight":110,"velocity":0.57,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","order":2}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"422":{"description":"The `Idempotency-Key` was already used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"This Idempotency-Key was already used for another request"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/equations/{id}":{"get":{"summary":"Get a load-velocity profile","description":"One load-velocity profile with the points it was fitted on (`equationSeries`), in order.","operationId":"getEquationsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Back squat LVP","a":0,"b":-64.286,"c":119.286,"r2":0.987,"isSelected":true,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","deletedAt":null,"equationSeries":[{"id":"5a9c2e71-d4b8-4f06-a3e9-17c0b6d8f2a4","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":60,"velocity":1.14,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":0},{"id":"c38f0b5d-7e2a-4c91-b6d4-e09a3f1c7b58","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":80,"velocity":0.9,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":1},{"id":"81d6a4f3-0c5e-4b27-9a8f-d3e2b7c05a19","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":100,"velocity":0.66,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":2},{"id":"e72b9c08-3f1d-4a65-8e4b-6c0d9a2f7b31","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":115,"velocity":0.48,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":3}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"patch":{"summary":"Update a load-velocity profile","description":"Changes only the fields sent, and answers the updated profile with its points.","operationId":"patchEquationsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"description":"Profile name, up to 255 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"a":{"description":"Only `0`: profiles are linear. Any other value answers `400`.","type":"number"},"b":{"description":"Slope: load as % of 1RM = `b`·velocity (m/s) + `c`.","type":"number"},"c":{"description":"Intercept, in %1RM.","type":"number"},"r2":{"description":"Goodness of fit, 0–1.","anyOf":[{"type":"number"},{"type":"null"}]},"isSelected":{"description":"Only `true`: makes this the athlete’s selected profile for the exercise and unselects the others. To unselect a profile, select another one.","type":"boolean"},"equationSeries":{"description":"The tested sets, in order, at most 100: `weight` in kg and `velocity` in m/s, both 0 or more. Replaces the current points.","type":"array","items":{"type":"object","additionalProperties":false,"required":["weight","velocity"],"properties":{"weight":{"description":"Load lifted, in kg.","type":"number"},"velocity":{"description":"Velocity at that load, in m/s.","type":"number"}}}}},"minProperties":1},"example":{"name":"Back squat LVP, March"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Back squat LVP, March","a":0,"b":-64.286,"c":119.286,"r2":0.987,"isSelected":true,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-10-13T09:44:03.127Z","deletedAt":null,"equationSeries":[{"id":"5a9c2e71-d4b8-4f06-a3e9-17c0b6d8f2a4","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":60,"velocity":1.14,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":0},{"id":"c38f0b5d-7e2a-4c91-b6d4-e09a3f1c7b58","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":80,"velocity":0.9,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":1},{"id":"81d6a4f3-0c5e-4b27-9a8f-d3e2b7c05a19","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":100,"velocity":0.66,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":2},{"id":"e72b9c08-3f1d-4a65-8e4b-6c0d9a2f7b31","equationId":"ad30e6f9-8c47-4b12-a5d8-e91f2c7b4063","weight":115,"velocity":0.48,"createdAt":"2026-02-04T09:12:00.000Z","updatedAt":"2026-02-04T09:12:00.000Z","order":3}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Delete a load-velocity profile","description":"Deletes a load-velocity profile for good and answers it as it was, with its points.","operationId":"deleteEquationsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Back squat LVP","a":0,"b":-61.9,"c":117.4,"r2":0.991,"isSelected":true,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","deletedAt":null,"equationSeries":[{"id":"0f6a2d94-7c1e-4b38-a5d0-93e7b1c4f826","equationId":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","weight":70,"velocity":1.02,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","order":0},{"id":"d35b8e10-49f2-4a67-8c1b-2e6f0a9d7c53","equationId":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","weight":90,"velocity":0.81,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","order":1},{"id":"7e19c4b2-a053-4d8e-b6f7-c0d2915a3e48","equationId":"b7f1d4a3-62e9-4c05-8d7b-1a3e9f50c428","weight":110,"velocity":0.57,"createdAt":"2026-10-13T09:42:17.551Z","updatedAt":"2026-10-13T09:42:17.551Z","order":2}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/leaderboards":{"get":{"summary":"List leaderboards","description":"Leaderboard definitions of your organization, newest first, each with the ids of its athletes.","operationId":"getLeaderboards","parameters":[{"name":"metricId","in":"query","required":false,"description":"Only leaderboards ranking this metric.","schema":{"type":"string","format":"uuid"}},{"name":"exerciseId","in":"query","required":false,"description":"Only leaderboards of this exercise.","schema":{"type":"string","format":"uuid"}},{"name":"userId","in":"query","required":false,"description":"Only leaderboards this athlete is on.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25","name":"Back squat: best mean velocity","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","createdAt":"2025-11-03T08:00:00.000Z","updatedAt":"2025-11-03T08:00:00.000Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}]}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/leaderboards/{id}":{"get":{"summary":"Get a leaderboard","description":"One leaderboard definition with the ids of its athletes.","operationId":"getLeaderboardsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"17b9d4e2-60a5-4c83-bf19-4a8e3d0c6f25","name":"Back squat: best mean velocity","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","createdAt":"2025-11-03T08:00:00.000Z","updatedAt":"2025-11-03T08:00:00.000Z","deletedAt":null,"users":[{"id":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62"},{"id":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/wellness-tests":{"get":{"summary":"List wellness questionnaires","description":"Answered wellness questionnaires of your organization’s athletes, newest first, each with its questions and answers.","operationId":"getWellnessTests","parameters":[{"name":"userId","in":"query","required":false,"description":"Only questionnaires answered by this athlete.","schema":{"type":"string","format":"uuid"}},{"name":"workoutId","in":"query","required":false,"description":"Only the questionnaire answered for this workout.","schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","required":false,"description":"Inclusive lower bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date starts at 00:00 in `timezone`, or at the change on a day whose midnight a daylight-saving change skips.","schema":{"type":"string"}},{"name":"to","in":"query","required":false,"description":"Inclusive upper bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date covers that whole day in `timezone`.","schema":{"type":"string"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. A bare `from` / `to` date covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes with `Z` or an offset are taken as given.","schema":{"type":"string","default":"UTC"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","workoutId":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","createdAt":"2026-03-18T08:47:12.000Z","updatedAt":"2026-03-18T08:47:12.000Z","deletedAt":null,"questions":[{"id":"2b7e4f90-c613-4d8a-95e2-a0f3d71c6b48","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","baseQuestionId":"7c1d9a35-e840-4f62-b0a7-58e3c2d4f916","wellnessTestId":"c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3","order":0,"question":"How fatigued do you feel?","placeholderMinValue":"Very Fatigated","placeholderMaxValue":"Not Fatigated","minValue":1,"maxValue":5,"integerValue":4,"stringValue":null,"isSelected":true,"type":"numeric","createdAt":"2026-03-18T08:47:12.000Z","updatedAt":"2026-03-18T08:47:12.000Z","deletedAt":null},{"id":"f05a8c3e-29d7-4b16-a4c9-6e1b7d0f3a82","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","baseQuestionId":"4e8b2d61-a0f5-4c39-8d17-b9c6e3a05f24","wellnessTestId":"c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3","order":1,"question":"Write whatever you want","placeholderMinValue":null,"placeholderMaxValue":null,"minValue":null,"maxValue":null,"integerValue":null,"stringValue":"Slight tightness in the left calf.","isSelected":true,"type":"text","createdAt":"2026-03-18T08:47:12.000Z","updatedAt":"2026-03-18T08:47:12.000Z","deletedAt":null}]}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/wellness-tests/{id}":{"get":{"summary":"Get a wellness questionnaire","description":"One answered questionnaire with its questions and answers.","operationId":"getWellnessTestsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","workoutId":"f2c8e1a6-3d49-4b75-8e02-6a9d4c1b7f35","createdAt":"2026-03-18T08:47:12.000Z","updatedAt":"2026-03-18T08:47:12.000Z","deletedAt":null,"questions":[{"id":"2b7e4f90-c613-4d8a-95e2-a0f3d71c6b48","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","baseQuestionId":"7c1d9a35-e840-4f62-b0a7-58e3c2d4f916","wellnessTestId":"c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3","order":0,"question":"How fatigued do you feel?","placeholderMinValue":"Very Fatigated","placeholderMaxValue":"Not Fatigated","minValue":1,"maxValue":5,"integerValue":4,"stringValue":null,"isSelected":true,"type":"numeric","createdAt":"2026-03-18T08:47:12.000Z","updatedAt":"2026-03-18T08:47:12.000Z","deletedAt":null},{"id":"f05a8c3e-29d7-4b16-a4c9-6e1b7d0f3a82","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","baseQuestionId":"4e8b2d61-a0f5-4c39-8d17-b9c6e3a05f24","wellnessTestId":"c4e7a18d-9f32-4b50-8d6a-2b1f5e09a7c3","order":1,"question":"Write whatever you want","placeholderMinValue":null,"placeholderMaxValue":null,"minValue":null,"maxValue":null,"integerValue":null,"stringValue":"Slight tightness in the left calf.","isSelected":true,"type":"text","createdAt":"2026-03-18T08:47:12.000Z","updatedAt":"2026-03-18T08:47:12.000Z","deletedAt":null}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/injury-reports":{"get":{"summary":"List injury reports","description":"Injury reports filed for your organization’s athletes, newest first.","operationId":"getInjuryReports","parameters":[{"name":"userId","in":"query","required":false,"description":"Only reports of this athlete.","schema":{"type":"string","format":"uuid"}},{"name":"recovered","in":"query","required":false,"description":"`false` for open injuries, `true` for recovered ones.","schema":{"type":"boolean"}},{"name":"from","in":"query","required":false,"description":"Inclusive lower bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date starts at 00:00 in `timezone`, or at the change on a day whose midnight a daylight-saving change skips.","schema":{"type":"string"}},{"name":"to","in":"query","required":false,"description":"Inclusive upper bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date covers that whole day in `timezone`.","schema":{"type":"string"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. A bare `from` / `to` date covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes with `Z` or an offset are taken as given.","schema":{"type":"string","default":"UTC"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdBy":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","injuryType":"Hamstring strain","side":"left","severity":"mid","recoveryEstimatedDate":"2026-04-15T00:00:00.000Z","recovered":false,"notes":"Grade 1. Return to running in two weeks.","createdAt":"2026-03-20T16:05:41.000Z","updatedAt":"2026-03-20T16:05:41.000Z","deletedAt":null}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"post":{"summary":"Create an injury report","description":"Files an injury report for an athlete, in the name of the coach or owner in `createdBy`. Answers it in the shape of `GET /injury-reports/{id}`.","operationId":"postInjuryReports","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7E]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["userId","createdBy","injuryType","severity","recoveryEstimatedDate"],"properties":{"userId":{"description":"Injured athlete, one of your organization’s.","type":"string","format":"uuid"},"createdBy":{"description":"Coach or owner filing the report: the API key has no user of its own. See `GET /coaches`.","type":"string","format":"uuid"},"injuryType":{"description":"The injury, as free text, up to 2,000 characters.","type":"string"},"severity":{"description":"Severity.","type":"string","enum":["low","mid","high"]},"recoveryEstimatedDate":{"description":"Expected return date: `YYYY-MM-DD` (UTC midnight) or an ISO 8601 datetime with an offset. Can’t be `null`.","type":"string"},"side":{"description":"Injured side.","anyOf":[{"type":"string","enum":["left","right"]},{"type":"null"}]},"recovered":{"description":"Whether the athlete has recovered.","type":"boolean","default":false},"notes":{"description":"Notes, up to 2,000 characters.","anyOf":[{"type":"string"},{"type":"null"}]}}},"example":{"userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","createdBy":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","injuryType":"Ankle sprain","severity":"low","recoveryEstimatedDate":"2026-10-27","side":"right","notes":"Inversion sprain in training. Back to running in a week."}}}},"responses":{"200":{"description":"Success","headers":{"Idempotent-Replayed":{"description":"`true` when the answer is the one kept for an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093","userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdBy":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","injuryType":"Ankle sprain","side":"right","severity":"low","recoveryEstimatedDate":"2026-10-27T00:00:00.000Z","recovered":false,"notes":"Inversion sprain in training. Back to running in a week.","createdAt":"2026-10-13T09:45:30.226Z","updatedAt":"2026-10-13T09:45:30.226Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"422":{"description":"The `Idempotency-Key` was already used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"This Idempotency-Key was already used for another request"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/injury-reports/{id}":{"get":{"summary":"Get an injury report","description":"One injury report.","operationId":"getInjuryReportsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdBy":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","injuryType":"Hamstring strain","side":"left","severity":"mid","recoveryEstimatedDate":"2026-04-15T00:00:00.000Z","recovered":false,"notes":"Grade 1. Return to running in two weeks.","createdAt":"2026-03-20T16:05:41.000Z","updatedAt":"2026-03-20T16:05:41.000Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"patch":{"summary":"Update an injury report","description":"Changes only the fields sent, for example `{ \"recovered\": true }`, and answers the updated report. `null` clears `side` or `notes`.","operationId":"patchInjuryReportsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"injuryType":{"description":"The injury, as free text, up to 2,000 characters.","type":"string"},"severity":{"description":"Severity.","type":"string","enum":["low","mid","high"]},"recoveryEstimatedDate":{"description":"Expected return date: `YYYY-MM-DD` (UTC midnight) or an ISO 8601 datetime with an offset. Can’t be `null`.","type":"string"},"side":{"description":"Injured side.","anyOf":[{"type":"string","enum":["left","right"]},{"type":"null"}]},"recovered":{"description":"Whether the athlete has recovered.","type":"boolean"},"notes":{"description":"Notes, up to 2,000 characters.","anyOf":[{"type":"string"},{"type":"null"}]}},"minProperties":1},"example":{"recovered":true}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"8f1a3c56-e0d7-4294-b5a8-7d4c9e2f1b60","userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdBy":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","injuryType":"Hamstring strain","side":"left","severity":"mid","recoveryEstimatedDate":"2026-04-15T00:00:00.000Z","recovered":true,"notes":"Grade 1. Return to running in two weeks.","createdAt":"2026-03-20T16:05:41.000Z","updatedAt":"2026-04-13T08:20:11.000Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Delete an injury report","description":"Deletes an injury report for good and answers it as it was.","operationId":"deleteInjuryReportsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"5a0d8e36-f1b7-4c92-b4a5-e86c2d71f093","userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","createdBy":"5e2a7b90-4c13-4f8d-a6b1-d93f0e8c2a47","injuryType":"Ankle sprain","side":"right","severity":"low","recoveryEstimatedDate":"2026-10-27T00:00:00.000Z","recovered":false,"notes":"Inversion sprain in training. Back to running in a week.","createdAt":"2026-10-13T09:45:30.226Z","updatedAt":"2026-10-13T09:45:30.226Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/analytics/trend":{"get":{"summary":"Get a metric trend","description":"One metric aggregated per athlete and period over a date range: the series Vitruve Labs charts. Not paginated.","operationId":"getAnalyticsTrend","parameters":[{"name":"metricId","in":"query","required":true,"description":"Metric to aggregate. Resolve with `GET /metrics/{id}`, which also gives its `unitId`.","schema":{"type":"string","format":"uuid"}},{"name":"calculation","in":"query","required":true,"description":"How each athlete’s values are combined: average, maximum, minimum, total, median, or the most recent value. Not every metric takes every calculation: `sum` only applies to additive metrics, body metrics take `latest`, `avg`, `max` or `min`, and categorical metrics only `latest`. Any other combination answers `400`.","schema":{"type":"string","enum":["avg","max","min","sum","median","latest"]}},{"name":"from","in":"query","required":true,"description":"Inclusive lower bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date starts at 00:00 in `timezone`, or at the change on a day whose midnight a daylight-saving change skips.","schema":{"type":"string"}},{"name":"to","in":"query","required":true,"description":"Inclusive upper bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date covers that whole day in `timezone`.","schema":{"type":"string"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. A bare `from` / `to` date covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes with `Z` or an offset are taken as given. It also sets where days, weeks and months start.","schema":{"type":"string","default":"UTC"}},{"name":"userIds","in":"query","required":false,"description":"Comma-separated athlete ids, at most 100. Defaults to every athlete of your organization you can see.","schema":{"type":"string"}},{"name":"teamId","in":"query","required":false,"description":"Only athletes in this team.","schema":{"type":"string","format":"uuid"}},{"name":"exerciseId","in":"query","required":false,"description":"Exercise the values were captured on. Required for per-exercise metrics (velocity, power, load…) and rejected for the others (body weight…).","schema":{"type":"string","format":"uuid"}},{"name":"repetitionType","in":"query","required":false,"description":"Repetition phase to read. Repetition metrics default to `concentric`; rejected for metrics without phases unless `all`.","schema":{"type":"string","enum":["concentric","eccentric","all"]}},{"name":"filterMetricId","in":"query","required":false,"description":"Companion metric to filter on, such as the load. Only values whose companion value is within `filterMin` / `filterMax` are kept. Needs at least one of the bounds.","schema":{"type":"string","format":"uuid"}},{"name":"filterMin","in":"query","required":false,"description":"Inclusive lower bound on `filterMetricId`, in that metric’s stored unit (kg for load).","schema":{"type":"number"}},{"name":"filterMax","in":"query","required":false,"description":"Inclusive upper bound on `filterMetricId`, in that metric’s stored unit.","schema":{"type":"number"}},{"name":"granularity","in":"query","required":false,"description":"Bucket size: `day` for ranges up to 93 days, `week` up to 731, `month` for any range. Defaults to the one the range implies; a range longer than the granularity covers answers `400`.","schema":{"type":"string","enum":["day","week","month"]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","calculation":"max","granularity":"month","from":"2025-11-30T23:00:00.000Z","to":"2026-03-31T21:59:59.999Z","repetitionType":"concentric","athleteCount":12,"athletes":[{"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","buckets":[{"bucketStart":"2025-11-30T23:00:00.000Z","value":0.71},{"bucketStart":"2025-12-31T23:00:00.000Z","value":0.74},{"bucketStart":"2026-01-31T23:00:00.000Z","value":0.78},{"bucketStart":"2026-02-28T23:00:00.000Z","value":0.81}]},{"userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","buckets":[{"bucketStart":"2025-12-31T23:00:00.000Z","value":0.69},{"bucketStart":"2026-02-28T23:00:00.000Z","value":0.72}]}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/analytics/ranking":{"get":{"summary":"Rank athletes on a metric","description":"One metric aggregated per athlete over a date range, sorted into a ranking. Not paginated.","operationId":"getAnalyticsRanking","parameters":[{"name":"metricId","in":"query","required":true,"description":"Metric to aggregate. Resolve with `GET /metrics/{id}`, which also gives its `unitId`.","schema":{"type":"string","format":"uuid"}},{"name":"calculation","in":"query","required":true,"description":"How each athlete’s values are combined: average, maximum, minimum, total, median, or the most recent value. Not every metric takes every calculation: `sum` only applies to additive metrics, body metrics take `latest`, `avg`, `max` or `min`, and categorical metrics only `latest`. Any other combination answers `400`.","schema":{"type":"string","enum":["avg","max","min","sum","median","latest"]}},{"name":"from","in":"query","required":true,"description":"Inclusive lower bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date starts at 00:00 in `timezone`, or at the change on a day whose midnight a daylight-saving change skips.","schema":{"type":"string"}},{"name":"to","in":"query","required":true,"description":"Inclusive upper bound: `YYYY-MM-DD` or an ISO 8601 datetime. A bare date covers that whole day in `timezone`.","schema":{"type":"string"}},{"name":"timezone","in":"query","required":false,"description":"IANA time zone, such as `Europe/Madrid`. A bare `from` / `to` date covers that whole day in it, and a datetime without an offset is a wall-clock time in it. Datetimes with `Z` or an offset are taken as given. It also sets where days, weeks and months start.","schema":{"type":"string","default":"UTC"}},{"name":"userIds","in":"query","required":false,"description":"Comma-separated athlete ids, at most 100. Defaults to every athlete of your organization you can see.","schema":{"type":"string"}},{"name":"teamId","in":"query","required":false,"description":"Only athletes in this team.","schema":{"type":"string","format":"uuid"}},{"name":"exerciseId","in":"query","required":false,"description":"Exercise the values were captured on. Required for per-exercise metrics (velocity, power, load…) and rejected for the others (body weight…).","schema":{"type":"string","format":"uuid"}},{"name":"repetitionType","in":"query","required":false,"description":"Repetition phase to read. Repetition metrics default to `concentric`; rejected for metrics without phases unless `all`.","schema":{"type":"string","enum":["concentric","eccentric","all"]}},{"name":"filterMetricId","in":"query","required":false,"description":"Companion metric to filter on, such as the load. Only values whose companion value is within `filterMin` / `filterMax` are kept. Needs at least one of the bounds.","schema":{"type":"string","format":"uuid"}},{"name":"filterMin","in":"query","required":false,"description":"Inclusive lower bound on `filterMetricId`, in that metric’s stored unit (kg for load).","schema":{"type":"number"}},{"name":"filterMax","in":"query","required":false,"description":"Inclusive upper bound on `filterMetricId`, in that metric’s stored unit.","schema":{"type":"number"}},{"name":"order","in":"query","required":false,"description":"`desc` puts the highest value first, `asc` the lowest. Ties are ordered by `userId`.","schema":{"type":"string","enum":["desc","asc"]}},{"name":"limit","in":"query","required":false,"description":"Athletes returned, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"metricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","calculation":"max","order":"desc","from":"2026-03-01T00:00:00.000Z","to":"2026-03-31T23:59:59.999Z","repetitionType":"concentric","athleteCount":24,"rankedCount":2,"athletes":[{"rank":1,"userId":"3b9c1e24-6f7a-4d2b-8c15-a40e9d7f1b62","value":0.71,"date":"2026-03-18T10:21:47.302Z"},{"rank":2,"userId":"c81d5f07-92ab-4e63-b0d4-7a3e6c1f9e28","value":0.64,"date":"2026-03-11T17:05:12.880Z"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/exercises":{"get":{"summary":"List exercises","description":"Vitruve’s global exercise library plus the exercises your organization created, ordered by name. Each exercise carries its primary and secondary muscles and your organization’s `exerciseMetadata`.","operationId":"getExercises","parameters":[{"name":"search","in":"query","required":false,"description":"Case-insensitive match on the exercise name.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Exact, case-sensitive match on `category`, e.g. `strength` or `plyometrics`.","schema":{"type":"string"}},{"name":"source","in":"query","required":false,"description":"`global` returns only Vitruve’s library, `organization` only your own exercises, `all` both.","schema":{"type":"string","enum":["all","global","organization"]}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","name":"Back Squat","organizationId":null,"isMain":true,"isJump":false,"isReaction":false,"isSprint":false,"equipment":"barbell","force":"push","level":"intermediate","mechanic":"compound","instructions":"Set the bar across your upper back and unrack it with feet shoulder-width apart. Bend at the hips and knees until the thighs are at least parallel, then drive up through the whole foot to stand.","category":"strength","youtubeUrl":"https://www.youtube.com/results?search_query=how%20to%20do%20Back%20Squat","googleUrl":"https://www.google.com/search?q=how%20to%20do%20Back%20Squat","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null,"primaryMuscles":[{"id":"5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52","name":"quadriceps","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"secondaryMuscles":[{"id":"2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","name":"glutes","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null},{"id":"e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035","name":"hamstrings","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"exerciseMetadata":[{"id":"9d5c2a71-e4f8-4b36-8c0d-6a1e3f7b9c52","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","videoUrl":"https://videos.northgate.example/back-squat.mp4","createdAt":"2025-10-03T11:12:40.000Z","updatedAt":"2025-10-03T11:12:40.000Z"}]}],"meta":{"limit":2,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"post":{"summary":"Create an exercise","description":"Creates an exercise for your organization and answers it in the shape of `GET /exercises/{id}`.","operationId":"postExercises","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Request header. 1 to 255 visible ASCII characters you choose per operation, such as a UUID or your own record’s id. A retry with the same key and the same request returns the first answer instead of creating again.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7E]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"description":"Exercise name, up to 255 characters.","type":"string"},"category":{"description":"Free-text category, up to 255 characters, e.g. `strength`.","anyOf":[{"type":"string"},{"type":"null"}]},"equipment":{"description":"Equipment, up to 255 characters, e.g. `barbell`.","anyOf":[{"type":"string"},{"type":"null"}]},"force":{"description":"Force type.","anyOf":[{"type":"string","enum":["pull","push","static"]},{"type":"null"}]},"level":{"description":"Difficulty.","anyOf":[{"type":"string","enum":["beginner","intermediate","expert"]},{"type":"null"}]},"mechanic":{"description":"Mechanic.","anyOf":[{"type":"string","enum":["compound","isolation"]},{"type":"null"}]},"instructions":{"description":"How to perform the exercise, up to 10,000 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"isMain":{"description":"Flags the exercise as a main lift.","type":"boolean"},"isJump":{"description":"Jump exercise. At most one of `isJump`, `isReaction` and `isSprint` is `true`.","type":"boolean"},"isReaction":{"description":"Reaction exercise. Needs timing gates in the plan.","type":"boolean"},"isSprint":{"description":"Sprint exercise. Needs timing gates in the plan.","type":"boolean"},"youtubeUrl":{"description":"Link to a demonstration video: an `http` or `https` URL, up to 255 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"googleUrl":{"description":"Web link: an `http` or `https` URL, up to 255 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"primaryMuscleIds":{"description":"Main muscles worked, at most 50. See `GET /muscles`.","type":"array","items":{"type":"string","format":"uuid"}},"secondaryMuscleIds":{"description":"Supporting muscles, at most 50.","type":"array","items":{"type":"string","format":"uuid"}}}},"example":{"name":"Safety Bar Squat","category":"strength","equipment":"safety squat bar","force":"push","level":"intermediate","mechanic":"compound","isMain":true,"primaryMuscleIds":["5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52"],"secondaryMuscleIds":["2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264"]}}}},"responses":{"200":{"description":"Success","headers":{"Idempotent-Replayed":{"description":"`true` when the answer is the one kept for an earlier request with the same `Idempotency-Key`.","schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"2c9e5a71-d083-4b6f-a1e4-58f0b7c3d926","name":"Safety Bar Squat","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","isMain":true,"isJump":false,"isReaction":false,"isSprint":false,"equipment":"safety squat bar","force":"push","level":"intermediate","mechanic":"compound","instructions":null,"category":"strength","youtubeUrl":null,"googleUrl":null,"updatedAt":"2026-10-13T09:40:02.318Z","createdAt":"2026-10-13T09:40:02.318Z","deletedAt":null,"primaryMuscles":[{"id":"5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52","name":"quadriceps","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"secondaryMuscles":[{"id":"2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","name":"glutes","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"exerciseMetadata":[]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"422":{"description":"The `Idempotency-Key` was already used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"This Idempotency-Key was already used for another request"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/exercises/{id}":{"get":{"summary":"Get an exercise","description":"One global exercise or one of your organization’s exercises, with its muscles and your organization’s `exerciseMetadata`.","operationId":"getExercisesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","name":"Back Squat","organizationId":null,"isMain":true,"isJump":false,"isReaction":false,"isSprint":false,"equipment":"barbell","force":"push","level":"intermediate","mechanic":"compound","instructions":"Set the bar across your upper back and unrack it with feet shoulder-width apart. Bend at the hips and knees until the thighs are at least parallel, then drive up through the whole foot to stand.","category":"strength","youtubeUrl":"https://www.youtube.com/results?search_query=how%20to%20do%20Back%20Squat","googleUrl":"https://www.google.com/search?q=how%20to%20do%20Back%20Squat","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null,"primaryMuscles":[{"id":"5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52","name":"quadriceps","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"secondaryMuscles":[{"id":"2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","name":"glutes","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null},{"id":"e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035","name":"hamstrings","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"exerciseMetadata":[{"id":"9d5c2a71-e4f8-4b36-8c0d-6a1e3f7b9c52","exerciseId":"1c7a5e93-f804-4b26-a9d1-3e6b0d82c4f7","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","videoUrl":"https://videos.northgate.example/back-squat.mp4","createdAt":"2025-10-03T11:12:40.000Z","updatedAt":"2025-10-03T11:12:40.000Z"}]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"patch":{"summary":"Update an exercise","description":"Changes only the fields sent, and answers the updated exercise. `null` clears an optional field.","operationId":"patchExercisesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"description":"Exercise name, up to 255 characters.","type":"string"},"category":{"description":"Free-text category, up to 255 characters, e.g. `strength`.","anyOf":[{"type":"string"},{"type":"null"}]},"equipment":{"description":"Equipment, up to 255 characters, e.g. `barbell`.","anyOf":[{"type":"string"},{"type":"null"}]},"force":{"description":"Force type.","anyOf":[{"type":"string","enum":["pull","push","static"]},{"type":"null"}]},"level":{"description":"Difficulty.","anyOf":[{"type":"string","enum":["beginner","intermediate","expert"]},{"type":"null"}]},"mechanic":{"description":"Mechanic.","anyOf":[{"type":"string","enum":["compound","isolation"]},{"type":"null"}]},"instructions":{"description":"How to perform the exercise, up to 10,000 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"isMain":{"description":"Flags the exercise as a main lift.","type":"boolean"},"isJump":{"description":"Jump exercise. At most one of `isJump`, `isReaction` and `isSprint` is `true`.","type":"boolean"},"isReaction":{"description":"Reaction exercise. Needs timing gates in the plan.","type":"boolean"},"isSprint":{"description":"Sprint exercise. Needs timing gates in the plan.","type":"boolean"},"youtubeUrl":{"description":"Link to a demonstration video: an `http` or `https` URL, up to 255 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"googleUrl":{"description":"Web link: an `http` or `https` URL, up to 255 characters.","anyOf":[{"type":"string"},{"type":"null"}]},"primaryMuscleIds":{"description":"Main muscles worked, at most 50. See `GET /muscles`. Replaces the current list.","type":"array","items":{"type":"string","format":"uuid"}},"secondaryMuscleIds":{"description":"Supporting muscles, at most 50. Replaces the current list.","type":"array","items":{"type":"string","format":"uuid"}}},"minProperties":1},"example":{"instructions":"Hold the handles in front of you with the pads on your upper back. Squat to depth and stand up tall.","secondaryMuscleIds":["2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"2c9e5a71-d083-4b6f-a1e4-58f0b7c3d926","name":"Safety Bar Squat","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","isMain":true,"isJump":false,"isReaction":false,"isSprint":false,"equipment":"safety squat bar","force":"push","level":"intermediate","mechanic":"compound","instructions":"Hold the handles in front of you with the pads on your upper back. Squat to depth and stand up tall.","category":"strength","youtubeUrl":null,"googleUrl":null,"updatedAt":"2026-10-14T07:12:45.903Z","createdAt":"2026-10-13T09:40:02.318Z","deletedAt":null,"primaryMuscles":[{"id":"5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52","name":"quadriceps","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"secondaryMuscles":[{"id":"2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","name":"glutes","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null},{"id":"e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035","name":"hamstrings","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"exerciseMetadata":[]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}},"delete":{"summary":"Delete an exercise","description":"Archives an exercise and answers it with `deletedAt` set. Workouts that used it keep showing it.","operationId":"deleteExercisesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"2c9e5a71-d083-4b6f-a1e4-58f0b7c3d926","name":"Safety Bar Squat","organizationId":"7d3f8a52-1c0e-4b8e-9f4a-2e6b1d9c5a10","isMain":true,"isJump":false,"isReaction":false,"isSprint":false,"equipment":"safety squat bar","force":"push","level":"intermediate","mechanic":"compound","instructions":"Hold the handles in front of you with the pads on your upper back. Squat to depth and stand up tall.","category":"strength","youtubeUrl":null,"googleUrl":null,"updatedAt":"2026-10-14T08:02:19.640Z","createdAt":"2026-10-13T09:40:02.318Z","deletedAt":"2026-10-14T08:02:19.640Z","primaryMuscles":[{"id":"5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52","name":"quadriceps","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"secondaryMuscles":[{"id":"2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","name":"glutes","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null},{"id":"e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035","name":"hamstrings","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"exerciseMetadata":[]}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"409":{"description":"The write conflicts with existing data, or the first request with the same `Idempotency-Key` is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"A user with email marta.ibanez@example.com already exists"}}}},"413":{"description":"The request body is larger than 1 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Payload too large"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/muscles":{"get":{"summary":"List muscles","description":"Every muscle exercises can reference (see `primaryMuscleIds` / `secondaryMuscleIds`), ordered by name. Names are lowercase, e.g. `quadriceps`, `lower back`.","operationId":"getMuscles","parameters":[{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"2b7e4f19-c6a3-4d80-9e51-a8d3f0c7b264","name":"glutes","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null},{"id":"e6a09c3d-5f72-4b18-8d4e-17c9b2a6f035","name":"hamstrings","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}],"meta":{"limit":2,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/muscles/{id}":{"get":{"summary":"Get a muscle","description":"One muscle.","operationId":"getMusclesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"5c8f2d06-a931-4e7b-96d4-0b3e8a1f7c52","name":"quadriceps","updatedAt":"2026-05-04T07:30:00.000Z","createdAt":"2024-01-15T09:00:00.000Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/metrics":{"get":{"summary":"List metrics","description":"Metric definitions, ordered by `order`. Use them to name and unit the values inside workouts.","operationId":"getMetrics","parameters":[{"name":"group","in":"query","required":false,"description":"Only metrics in this group. Exact, case-sensitive match.","schema":{"type":"string","enum":["General","Weight","Time","Distance","Velocity","Fatigue","Percentage","Power","Force","Acceleration","Scale","Heart Rate","Temperature","Pressure","Energy","Volume","Pace","Oxygen Consumption","Concentration"]}},{"name":"isRepetitionMetric","in":"query","required":false,"description":"Only metrics recorded per repetition (`true`) or not (`false`).","schema":{"type":"boolean"}},{"name":"isSerieMetric","in":"query","required":false,"description":"Only metrics recorded per set (`true`) or not (`false`).","schema":{"type":"boolean"}},{"name":"isUserMetric","in":"query","required":false,"description":"Only athlete metrics such as body weight (`true`) or not (`false`).","schema":{"type":"boolean"}},{"name":"isEquationMetric","in":"query","required":false,"description":"Only metrics usable in equations (`true`) or not (`false`).","schema":{"type":"boolean"}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Mean Propulsive Velocity","key":"mean-propulsive-velocity","group":"Velocity","dimension":null,"unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isMainVelocityMetric":true,"isRepetitionMetric":true,"isSerieMetric":false,"isQuickStartMetric":true,"isEquationMetric":true,"isUserMetric":false,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null}],"meta":{"limit":1,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/metrics/{id}":{"get":{"summary":"Get a metric","description":"One metric definition.","operationId":"getMetricsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","name":"Mean Propulsive Velocity","key":"mean-propulsive-velocity","group":"Velocity","dimension":null,"unitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","order":0,"isMainVelocityMetric":true,"isRepetitionMetric":true,"isSerieMetric":false,"isQuickStartMetric":true,"isEquationMetric":true,"isUserMetric":false,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/prescription-types":{"get":{"summary":"List prescription types","description":"The parameters a coach can prescribe for a set (weight, repetitions, velocity targets, fatigue limits…), ordered by name. Use them to read `seriePrescriptions` in workouts, programs and templates.","operationId":"getPrescriptionTypes","parameters":[{"name":"group","in":"query","required":false,"description":"Only prescription types in this group. Exact, case-sensitive match.","schema":{"type":"string","enum":["General","VBT","Velocity","Jump","Sprint","Reaction","Time","Test","Other"]}},{"name":"trainingModality","in":"query","required":false,"description":"Only prescription types for this modality. Types that apply to any modality have none and are left out.","schema":{"type":"string","enum":["vbt","jump","sprint","reaction"]}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"b8d24f6a-0c97-4e35-a1f8-5d3e9c7b2a16","name":"Fatigue [MPV]","label":"Fatigue [MPV]","metricId":"4c9e7b20-d1a5-4f83-b6e2-a07f3d58c914","primaryMetricId":"d06b3f81-4e92-4a7c-8c15-b7e29a0d5f63","group":"VBT","prescriptionGroup":null,"trainingModality":"vbt","valueType":"int","placeholder":"0","formatRegex":"^(100|\\d{0,2})?$","hasRange":false,"hasTopMode":false,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null},{"id":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","name":"Weight","label":"Weight","metricId":"62f0d8a4-b3c9-4e17-8a5d-0e4c7f1b9d28","primaryMetricId":null,"group":"General","prescriptionGroup":null,"trainingModality":null,"valueType":"float","placeholder":"0","formatRegex":"^\\d{0,5}(\\.\\d{0,2})?$","hasRange":true,"hasTopMode":false,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null}],"meta":{"limit":2,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/prescription-types/{id}":{"get":{"summary":"Get a prescription type","description":"One prescription type.","operationId":"getPrescriptionTypesId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"3e9d7a12-c5b8-4f40-a136-d82e4b6f9c05","name":"Weight","label":"Weight","metricId":"62f0d8a4-b3c9-4e17-8a5d-0e4c7f1b9d28","primaryMetricId":null,"group":"General","prescriptionGroup":null,"trainingModality":null,"valueType":"float","placeholder":"0","formatRegex":"^\\d{0,5}(\\.\\d{0,2})?$","hasRange":true,"hasTopMode":false,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/units":{"get":{"summary":"List units","description":"Units of measure, ordered by name. Each unit converts to its base unit with `conversionFactor`: `base = value × conversionFactor`. For pounds the factor is `0.45359237`, so 100 lb is 45.359237 kg.","operationId":"getUnits","parameters":[{"name":"dimension","in":"query","required":false,"description":"Only units of this physical quantity. Exact, case-sensitive match.","schema":{"type":"string","enum":["Acceleration","Cadence","Distance","Energy","Force","Frequency","Heart Rate","Oxygen Consumption","Pace","Power","Pressure","Temperature","Time","Velocity","Volume","Weight"]}},{"name":"measurementSystem","in":"query","required":false,"description":"Only metric or only imperial units.","schema":{"type":"string","enum":["metric","imperial"]}},{"name":"limit","in":"query","required":false,"description":"Page size, 1–100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"`meta.nextCursor` from the previous page. Omit it to get the first page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":[{"id":"09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246","name":"Kilograms","dimension":"Weight","measurementSystem":"metric","label":"kg","baseUnitId":"09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246","pairUnitId":"7b13e9c5-48d2-4a06-b9f1-c2e8a5d4f317","conversionFactor":1,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null,"prescriptionTypeId":null},{"id":"7b13e9c5-48d2-4a06-b9f1-c2e8a5d4f317","name":"Pounds","dimension":"Weight","measurementSystem":"imperial","label":"lb","baseUnitId":"09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246","pairUnitId":"09e4b7a3-d2c6-4158-b8f0-a71d5c3e9246","conversionFactor":0.45359237,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null,"prescriptionTypeId":null}],"meta":{"limit":50,"hasMore":true,"nextCursor":"ZTU2M2ZlYzMtM2IxYy00…"}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}},"/units/{id}":{"get":{"summary":"Get a unit","description":"One unit, with `conversionFactor` as a number.","operationId":"getUnitsId","parameters":[{"name":"id","in":"path","required":true,"description":"Resource id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true,"timestamp":1738247125207,"data":{"id":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","name":"Meters per Second","dimension":"Velocity","measurementSystem":"metric","label":"m/s","baseUnitId":"fa52c8d4-17e3-4b69-8d0a-6c3f9e1b2a78","pairUnitId":null,"conversionFactor":1,"createdAt":"2024-01-15T09:00:00.000Z","updatedAt":"2026-05-04T07:30:00.000Z","deletedAt":null,"prescriptionTypeId":null}}}}},"400":{"description":"The request was understood but a parameter or a body field is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Invalid query parameters: 'limit': Number must be less than or equal to 100"}}}},"401":{"description":"The API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Missing X-API-Key header"}}}},"403":{"description":"The key is valid but this access is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Your plan no longer includes API access"}}}},"404":{"description":"The resource does not exist in your organization, or the route does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Athlete not found"}}}},"429":{"description":"The key exceeded 30 requests per minute, or authentication failed too often.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Rate limit of 30 requests per minute exceeded"}}}},"500":{"description":"Something failed on our side.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Internal server error"}}}},"503":{"description":"The service is temporarily unable to serve requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"ok":false,"timestamp":1738247125207,"message":"Service temporarily unavailable"}}}}}}}},"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Organization API key from Settings → API Access (example: YOUR_API_KEY)."}},"schemas":{"Error":{"type":"object","required":["ok","timestamp","message"],"properties":{"ok":{"type":"boolean","const":false},"timestamp":{"type":"integer","description":"Unix milliseconds."},"message":{"type":"string"}}}}}}