{"openapi":"3.1.0","info":{"title":"Budy Partner API","description":"# Introduction\n\nThe Budy Partner API puts Budy's AI coaching inside your app: workout plans built from your own exercise library and coaching rules, today's workout, logging, adjustments and regeneration. Your servers call it with a secret key; your app calls it with a short-lived member token for one member.\n\nThe overview is at [AI fitness API for gyms and fitness apps](https://budy.fit/ai-fitness-infrastructure); this guide is how to build on it.\n\n**Base URL:** `https://partners.budy.fit/v1`. Every request and answer is JSON, with camelCase field names.\n\n**Live and test.** Each partner has a live and a test environment, each with its own members, library, rules and request logs. The key decides which one a request reaches: `bdy_live_\u2026` keys reach live members and `bdy_test_\u2026` keys reach test members. A test key can never reach a live member. Build on test keys; live keys come after the go-live review and work only while your account is live.\n\n**What the test environment includes.** It's for building, not for running your service: up to 25 members, unless Budy has set you another number. Past that you get a clear error (`test_member_limit_reached`); nothing is lost. Test members are never billed.\n\n**Whose AI keys.** Your AI runs on your own AI key, for live and test alike: add your OpenAI key on your console's AI keys page, and your provider bills you. Until a key is ready, a call that would start AI answers `own_ai_key_required` and starts nothing. Budy can also open its own keys to your account. Then, without a key of yours, your AI runs on Budy's keys and is billed to you at cost, with $25 of AI a calendar month (UTC) on test keys unless Budy has set you another number (past it, `test_ai_allowance_used`). Your AI keys page says which applies to you. While your AI can't run, a member's next phase or next plan waits, and carries on by itself once it can.\n\n## Credentials\n\nSend one credential on every request, as `Authorization: Bearer \u2026`:\n\n| Credential | Who holds it | What it reaches |\n|---|---|---|\n| Secret key, `bdy_live_\u2026` or `bdy_test_\u2026` | Your server, never your app | Every member, your library, your rules |\n| Member token, from `POST /v1/members/{memberId}/tokens` | Your app, for one member | That member only, as `me`: `/v1/members/me/\u2026` |\n| Publishable app key, `bdy_pk_live_\u2026` or `bdy_pk_test_\u2026` | Your app, if Budy signs your members in | The sign-in routes only, `/v1/auth/\u2026` |\n\nA secret key is shown once, when it is created. Keep it on your server, and revoke it in the console if it leaks. A member token lasts 60 minutes; your server asks for a new one when it expires (`token_expired`). Its public keys are at `https://partners.budy.fit/.well-known/jwks.json`, so your server can check a token itself.\n\n## Member IDs\n\nEverything Budy keeps about a member belongs to the ID you send, so send the same one every time. Use an ID that never changes, and never an email.\n\n- **IDs are exact.** A different ID is a new, empty member, and `FM-1` and `fm-1` are two members. A mistyped ID in a `POST` or `PUT` creates that member: there's no sign-up step to catch it. You can erase it. Nothing joins two IDs later, so the plan and history stay with the old one.\n- **A wrong ID is yours to catch.** Budy reaches whichever member your server names, so a wrong ID shows one person another person's plan.\n- **Guests.** To let someone start before they sign up, have your server give them an ID, and keep that ID when they sign up. Without a server of your own, a member starts when they sign in.\n- **One way in.** Give each member your own ID, or let Budy's sign-in make one (`acct_\u2026`, which your server can use too), not both. Someone your server created who then signs in through Budy is a second member.\n\n## A member's data\n\n- **Exporting.** `GET /v1/members/{memberId}/export` gives all Budy holds on a member as one JSON document, for when someone asks for their data. Your app can ask for its own member with `GET /v1/members/me/export`. Your uploads aren't in it; the document names the ones each read used.\n- **Erasing.** `DELETE /v1/members/{memberId}` erases the member and all Budy holds on them, including the pictures only their reads used: lab pages, body-scan sheets, progress and gear photos. A picture another member's read also used, or one an exercise uses, stays.\n- **Live and test.** Your uploads are shared between them, until a read names one for a member: from then on only keys of that member's environment see it.\n\n# Quickstart: a plan from your own library\n\nFive calls take you from an empty test environment to a member's plan built from your own exercises. Use a test key (`bdy_test_\u2026`) from your console. The plan's AI runs on your own AI key, so add your OpenAI key on the console's AI keys page first, unless Budy has opened its own keys to you.\n\n**1. Add your exercises.** One call per exercise, with your own ID for it. The name and equipment are what the AI reads; notes and media links are yours to show in your app.\n\n```http\nPUT /v1/exercises/slider-reverse-lunge\nAuthorization: Bearer bdy_test_\u2026\nContent-Type: application/json\n\n{\n  \"name\": \"Slider Reverse Lunge\",\n  \"equipment\": [\"Slider discs\"],\n  \"notes\": \"Keep the front knee over the ankle.\",\n  \"media\": [{ \"url\": \"https://cdn.example.com/videos/slider-reverse-lunge.mp4\", \"type\": \"video\" }]\n}\n```\n\n`201` when it's new, `200` when it replaced an exercise with that ID. Check what plans will pick from with `GET /v1/exercises/search?q=lunge`.\n\n**2. Add your coaching rules.** You start with ready-made rules; add yours in plain text, one rule per call, with your own ID for each.\n\n```http\nPUT /v1/coaching-rules/no-jumps-over-60\nAuthorization: Bearer bdy_test_\u2026\nContent-Type: application/json\n\n{ \"text\": \"Members over 60 never do jumping exercises.\" }\n```\n\n**3. Tell Budy about the member.** Use your own ID for them. There's no separate sign-up: the first `POST` or `PUT` with your secret key for a new ID creates the member, whichever product it's for, and every later call with that ID adds to the same profile. So you can send what they told your app now, or with the call that needs it. `PUT /v1/members/{memberId}` takes everything in one call, all optional: who they are, how they train, what they eat and your own daily targets. Free text is fine: the AI reads it. A plan needs their goal, days, a place, sex, birth year (or `birthDate`), height and weight.\n\n```http\nPUT /v1/members/fm-8812\nAuthorization: Bearer bdy_test_\u2026\nContent-Type: application/json\n\n{\n  \"goal\": \"Get stronger and lose 4 kg before summer\",\n  \"sex\": \"female\",\n  \"birthYear\": 1994,\n  \"heightCm\": 168,\n  \"weightKg\": 66,\n  \"days\": [\"MON\", \"WED\", \"SAT\"],\n  \"minutesPerSession\": 45,\n  \"places\": [{ \"name\": \"Home\", \"kind\": \"home\", \"equipment\": [\"Slider discs\", \"Dumbbells 2\u201310 kg\", \"Mat\"] }],\n  \"limits\": \"Lower back gets sore after deadlifts\",\n  \"active\": true\n}\n```\n\n**4. Ask for plan options.** Three options, built in the background in 2 to 4 minutes.\n\n```http\nPOST /v1/members/fm-8812/plan-options\nAuthorization: Bearer bdy_test_\u2026\nIdempotency-Key: 6f1c2a9e-0d4b-4c43-9b7e-2f5e8a1d3c10\n```\n\nThe answer is `202` with the job: its `id`, and its address in `Location`. You hear back through the `plan_options.ready` webhook, or poll `GET /v1/jobs/{jobId}`.\n\n**5. Build the option the member picked.** About 1 to 7 minutes, then the `plan.ready` webhook. (To skip the choice, see [one call](#one-call) below.)\n\n```http\nPOST /v1/members/fm-8812/plans\nAuthorization: Bearer bdy_test_\u2026\nIdempotency-Key: 1b0e7d52-93a4-4f2e-8f61-7c2d9e4b5a08\nContent-Type: application/json\n\n{ \"option\": \"BALANCED\" }\n```\n\nRead the plan with `GET /v1/members/fm-8812/plan`: its phases and the schedule of workouts. A workout's exercises, with their sets and alternatives, are in `GET /v1/members/fm-8812/today` and `GET /v1/members/fm-8812/workouts/{workoutId}`. Each exercise names its `exerciseId`: for one of yours, the `budyId` your `PUT` returned, so your app shows your own media for it; any other is a name from Budy's catalogue, without media (only with `budyCatalogue`, below).\n\n<a id=\"one-call\"></a>**Or do steps 4 and 5 in one call.** If you don't show members a choice of three options, `POST /v1/members/fm-8812/plans` builds their plan directly. It takes who they are and how they train, the same fields as `PUT` without the food, all optional and saved first, and creates the member if the ID is new:\n\n```http\nPOST /v1/members/fm-8812/plans\nAuthorization: Bearer bdy_test_\u2026\nIdempotency-Key: 9a7c3f10-52de-4b8a-a1c6-3e0f7d2b4c11\nContent-Type: application/json\n\n{\n  \"goal\": \"Get stronger and lose 4 kg before summer\",\n  \"sex\": \"female\",\n  \"birthYear\": 1994,\n  \"heightCm\": 168,\n  \"weightKg\": 66,\n  \"days\": [\"MON\", \"WED\", \"SAT\"],\n  \"places\": [{ \"name\": \"Home\", \"kind\": \"home\", \"equipment\": [\"Dumbbells 2\u201310 kg\", \"Mat\"] }]\n}\n```\n\nIt's one job and one `plan.ready` webhook, with no `plan_options.ready`, about 3 to 11 minutes, and it counts as one plan toward the member's limit. Budy makes the plan options itself and builds `BALANCED`, or the `option` you send (`AGGRESSIVE`, `BALANCED` or `RELAXED`). It's the same plan either way: the AI designs one week of the phase, and how much to do in each week of it. Later phases follow by themselves. Without `option`, options the member already has are reused only if they're unused and you sent nothing new.\n\nThen your app takes over for the member: your server gets a member token (`POST /v1/members/fm-8812/tokens`), and the app reads `GET /v1/members/me/today` with it.\n\n**How the member is doing.** Beside the workout, `\u2026/today` says how to treat the member:\n\n| Field | What it says |\n|---|---|\n| `missedWorkout` | A training day passed with no workout. True for two days after it, never on a training day, when today's workout is the way back |\n| `longBreak` | A training day was missed and nothing has been done for 14 days: a welcome back suits them better than a reminder |\n| `recovery` | While either of those holds: the workout that gets them back on track (`workoutId`, `name`) and `missedSince`, the last training day missed. Otherwise null |\n| `weeklyReset` | `nextMove`, their one next step: `type` is `start_due_workout`, `start_recovery_workout`, `view_next_week` or `on_track`, and `label` is a short line in English, to show or to replace with your own. `focus` is a headline for the week, in English |\n| `nextPlan` | Null until their next plan is on its way. Then `status` (`preparing`, `generating_plan`, `refreshing`, `ready`, `activated`, `blocked` or `failed`) and `planId` once it's ready. The `plan.renewed` webhook says when it starts |\n\nKeep the profile current: `PUT` what changes, such as a new injury in `limits`. The next AI run reads it: later phases, adjustments, regenerations and the next plan. Workouts already built stay as they are until an adjustment or a regeneration changes them. New training days, as many as before and at the same places, move the current phase at once. Your app can do this too: `PUT /v1/members/me` with the member token changes their profile, but never `active` or `tier`.\n\nThe Postman collection walks through these calls with variables for your key and IDs.\n\n# Changing a member's workouts\n\n**Regenerate.** `POST /v1/members/{memberId}/regenerations` rebuilds the unfinished workouts of a phase, the way Budy's own app does. Finished and skipped workouts stay. Everything is optional, so an empty call rebuilds the current phase:\n\n```http\nPOST /v1/members/fm-8812/regenerations\nAuthorization: Bearer bdy_test_\u2026\nContent-Type: application/json\n\n{\n  \"difficulty\": \"easier\",\n  \"words\": \"My knee hurts, fewer jumps please\"\n}\n```\n\n| Field | What it does |\n|---|---|\n| `phase` | The phase to rebuild; the current one if you don't name one |\n| `difficulty` | `harder` or `easier`, this once |\n| `words` | What the member wants changed, in their words |\n| `exerciseIds` | The `exerciseId`s, from their workouts, of exercises that don't suit them |\n| `calibrationContext` | How their recent workouts really went, for this rebuild only |\n| The member's details | `goal`, `days`, `places`, `limits` and the rest: saved first, then used |\n\nIt's a job: poll `GET /v1/jobs/{jobId}`, or wait for the `regeneration.ready` webhook. While it runs, `GET \u2026/plan` shows the phase as `building`. It uses one of the member's workout updates (`GET \u2026/quota`), and a failed one gives it back. It needs Workout updates in your plan.\n\nThe finished job's `result` says what changed in the phase's next unfinished week:\n\n```json\n{\n  \"planId\": \"cmh2x\u2026\",\n  \"phase\": 1,\n  \"changes\": {\n    \"week\": 2,\n    \"items\": [\n      { \"type\": \"replaced\", \"day\": \"Mon\", \"from\": \"Box Jump\", \"to\": \"Step-Up\" },\n      { \"type\": \"sets\", \"day\": \"Wed\", \"name\": \"Goblet Squat\", \"from\": 4, \"to\": 3 }\n    ],\n    \"more\": 0,\n    \"summary\": { \"replaced\": 1, \"added\": 0, \"removed\": 0, \"sets\": 1, \"minutesBefore\": 45, \"minutesAfter\": 40 }\n  }\n}\n```\n\nAn item's `type` is `replaced`, `added`, `removed`, `sets`, `warmup`, `cooldown`, `minutes`, `dayAdded` or `dayRemoved`. `items` holds up to 40, and `more` counts the rest. `changes` is `null` if the two couldn't be compared; the workouts are rebuilt all the same.\n\n**Adjust.** `POST /v1/members/{memberId}/adjustments` is lighter: it changes the rest of the phase from the member's feedback on some exercises, or from how workout 1 or 2 of the phase felt. It also uses one workout update.\n\n**Swap.** `POST /v1/members/{memberId}/swaps` trades one exercise in one workout for one of its alternatives. No AI, and free.\n\n# Your library\n\nYour exercise library lives in your own database at Budy. Plans pick from it through one search, and the AI sees only each exercise's name and equipment, so write names the way a coach would say them and list the equipment it needs.\n\nBring your exercises in first: `POST /v1/exercises/imports` takes a whole file, and `POST /v1/exercises/batch` up to 100 at once. While your library is empty, plan requests answer `409 no_exercises`.\n\n**Budy's exercises and equipment** are an extra that Budy switches on for you, at an extra charge: `budyCatalogue` in `GET /v1/features`. With it on, plans, the search and equipment scans use Budy's names as well as yours. The meals the AI recommends come from Budy's recipes either way, for every partner with nutrition.\n\n- `PUT /v1/exercises/{exerciseRef}` adds or replaces an exercise. Fields you leave out take their defaults.\n- `PATCH /v1/exercises/{exerciseRef}` changes only the fields you send, for example `{\"hidden\": true}`. A list is replaced whole, and `[]` clears it; `null` clears a text or a list, and leaves `measurement`, `perSide`, `requiresWeight` and `hidden` as they are.\n- `GET /v1/exercises` lists your library (`hidden=true` or `false` to filter); `GET /v1/exercises/{exerciseRef}` reads one.\n- `GET /v1/exercises/search?q=\u2026` shows what plan generation finds for those words: your exercises (`\"source\": \"library\"`), and Budy's names (`\"source\": \"budy\"`) with `budyCatalogue`, best first. On a close match yours come first.\n- `GET /v1/exercises/schema` lists every field with its limits and options, the IDs the routes keep (`search`, `schema`, `imports`, `export`, `batch`), the CSV's rules and the import limits.\n\n**What an exercise has.**\n\n| Field | What it does |\n|---|---|\n| `name`, `equipment` | What the AI reads to pick it. Equipment in your own words, for example \"Slider discs\"; empty for bodyweight |\n| `measurement` | `reps` (the default) or `time`: a plank gets timed sets |\n| `perSide` | Sets are done on each side, for example a lunge |\n| `requiresWeight` | Sets ask the member for the weight used |\n| `instructions`, `safetyTips`, `commonMistakes` | What members are shown with it, in order. Display only: the AI and the search never read them |\n| `tags` | Your own labels, for finding exercises, each once whatever its case; the AI never reads them |\n| `notes` | Your own notes, kept for you; never shown in workouts |\n| `media` | Links to your own videos and images (below) |\n| `hidden` | Hidden exercises leave the search and new plans (below) |\n\nPlans set the sets and reps themselves; an exercise has no default sets or reps. To steer them, write a coaching rule (below). Workouts show your exercises with their equipment, media (an upload once it's ready) and what members are shown (`library`), never your notes.\n\n**Your media, hosted by Budy.** Instead of a link, a media item can name a video or picture you uploaded: `{\"type\": \"video\", \"assetId\": \"ma_\u2026\"}`. Upload with `POST /v1/media/uploads` (`filename`, `contentType`, `sizeBytes`): you get one signed `PUT` link per 8 MiB part. `PUT` the parts straight to them, keep each answer's `ETag`, then `POST /v1/media/{assetId}/complete` with every part's number and ETag. Budy makes a 720p and a 480p version and a poster (pictures: 1280, 640 and 320 px WebP) and tells your webhooks `media.ready`. Reads of your exercises then carry signed links, good for at least 12 hours: store the `assetId`, never a link. Videos up to 500 MB, 3 minutes and 4K either way up (MP4, MOV, WebM), pictures up to 20 MB (JPEG, PNG, WebP, HEIC); `GET /v1/media/usage` shows your storage. An upload used by an exercise can't be deleted until you take it out.\n\n**Hidden, never deleted.** Members' workouts may point at an exercise, so exercises are hidden rather than deleted. A hidden exercise leaves the search and new plans; workouts that already have it keep it. Unhide it with `PATCH {\"hidden\": false}`.\n\n**Media.** `media` holds up to 10 links to your own videos or images: public `https` URLs, without a user name or password. Budy's exercise videos are licensed for Budy's own apps only, so they never reach partners: links to Budy's media are refused, and Budy's exercise names come without any.\n\nLimits: names up to 200 characters; up to 20 equipment names of up to 100 characters; up to 12 instruction lines, 8 safety tips and 8 common mistakes of up to 300 characters each; up to 20 tags of up to 50 characters; notes up to 4,000 characters.\n\n## Many exercises at once\n\n- `POST /v1/exercises/batch` adds or replaces up to 100 exercises, each as PUT takes it plus its `id`. Each is checked on its own: the ones that fit are written together, and `results` says for each `created`, `replaced`, `unchanged` or `error` (with `code`, `message` and `field`). One naming an upload that isn't yours is an `error` of its own (`invalid_asset`, `media.assetId`). Send an `Idempotency-Key` to retry safely.\n- `GET /v1/exercises/export?format=csv` (or `ndjson`) downloads your library, every exercise unless you add `hidden=true` or `false`, in an import's columns.\n\nAn **import** takes a whole file, checks it first, and changes nothing until you apply it:\n\n1. `POST /v1/exercises/imports` with `format` (`csv` or `ndjson`), `mode`, `filename` and `sizeBytes`. One import at a time is receiving, checking or applying: another is `409 import_running`.\n2. `PUT /v1/exercises/imports/{importId}/source` with the file as the body, typed `text/csv` or `application/x-ndjson`: up to 1 MB here (`GET /v1/exercises/schema` says so); your console takes files up to 20 MB. The check starts by itself.\n3. `GET /v1/exercises/imports/{importId}` until `status` is `checked` (or `failed`, with `error`). It has `counts` (`rows`, `create`, `update`, `unchanged`, `hide`, `error`), the first 50 `errors` (`row`, `column`, `code`, `message`) and `warnings` (columns left out). `GET \u2026/{importId}/rows?outcome=\u2026` pages through the rows, with each update's `changes`, and `GET \u2026/{importId}/report.csv` is the rows with errors as your file had them, plus an `error` column, to fix and import again.\n4. `POST /v1/exercises/imports/{importId}/apply`. Rows with errors are skipped. If your library changed since the check, it's checked again first, and its counts update. When it's done, `status` is `applied` and a `library.imported` webhook event says so.\n5. `POST /v1/exercises/imports/{importId}/cancel`, while it's receiving, checking or checked.\n\nAn import expires 7 days after you start it. Modes: `upsert` (the default) adds new exercises and changes existing ones. `create_only` only adds: an ID already in your library is an error. `mirror` also hides your exercises the file leaves out; hiding never deletes, and showing one again is an edit.\n\n**Files.** CSV is UTF-8 with a header row: `id` is your ID for the exercise, and the other headers are the schema's `csv` names (`per_side`, `safety_tips`, \u2026), matched ignoring case, spaces, `_` and `-`. A column Budy doesn't take is a warning and left out. Lists are separated by `|`; put a backslash before a `|` or a backslash that's part of an item. True and false are `true`/`false`, `yes`/`no` or `1`/`0`. A media cell is `|`-separated links, each a video, image or other by its extension, with no title; one of your uploads is `asset:<assetId>` (an export writes them so, never their links, which expire), and its type is the upload's own. Rows are numbered as a spreadsheet numbers them: the header is row 1. NDJSON is one JSON object a line, PUT's body plus `id`, with full media objects; lines end at `\\n` only. What can't be stored (a NUL character, NaN, an infinity, JSON nested too deep, a number of thousands of digits) is an error of its row. In both, a field the file doesn't have keeps the exercise's value, and a blank cell clears its field. A new exercise takes the defaults for what the file leaves out. Up to 10,000 exercises in one import.\n\nRow errors have codes: `required`, `too_long`, `too_many`, `invalid_choice`, `invalid_boolean`, `invalid_url`, `licence` (Budy's media), `invalid_id`, `reserved_id`, `duplicate_id` (an ID on two rows), `exists` (`create_only`), `invalid_asset` (an upload that isn't yours, or isn't usable: checked at the check and again as it's applied), `invalid_json` and `wrong_type`. A file that can't be read at all fails with `file_unreadable`, `empty`, `no_id_column` or `too_many_rows`.\n\n# Coaching rules\n\nCoaching rules are your guidance in plain words, such as \"Members over 60 never do jumping exercises\" or \"Call them sessions, not workouts\". The AI reads them with each member's own profile whenever it does the work they're for: plans and their changes, meal plans and ideas, meal photos, the coach, supplement assessments, scans and imports. It follows them where they apply. They reach it after Budy's own instructions and win where the two differ, health and safety guidance included, so a rule can override a member's own health limits: what you change reaches your members as you wrote it. How the AI handles a medical emergency, self-harm, an eating disorder or a food allergy never changes, and neither does the output format.\n\nYou start with ready-made rules for all of this, at version `0`: the AI reads them from your first run. Change them as you like: remove, reword or switch one off and the AI stops following it, add your own and it follows them. Your first change, of any rule, keeps the ready-made ones as your own rules beside it. In your console's Coaching page they sit on one sheet per kind of work, one rule per row, to edit, add, remove and reorder, and each sheet can go back to its ready-made rules. Some things aren't on a sheet because no rule can change them: how the AI handles those emergencies; what Budy checks in code whatever the AI says (recipes in meal plans and meal ideas against allergies and foods to avoid, and in meal plans against what a diet rules out; supplements against banned substances, doses, duplicates and allergies, with clinician review where it's due; plans for real exercises and the member's days and weeks); and the output format. Gear, moves to skip, session length and health limits are input to the AI: code doesn't check them.\n\n- `GET /v1/coaching-rules` lists every rule with the set's `version`.\n- `PUT /v1/coaching-rules/{ruleId}` adds a rule (`201`) or changes it (`200`): `{\"text\": \"\u2026\", \"features\": [\"weekly_workout\"], \"enabled\": true}`.\n- `GET /v1/coaching-rules/{ruleId}` reads one; `DELETE /v1/coaching-rules/{ruleId}` removes it (`204`).\n\n`features` says which AI runs read a rule: `plan_options`, `plan_continuation` (the next plan's options), `weekly_workout` (the workouts of each phase, and of a regeneration), `phase_edit` (adjustments), `meal_plan`, `meal_suggestion` (meal ideas), `meal_photo`, `coach` (the coach's answers), `supplement`, `equipment_identify` (gear photos), `body_scan` (body composition sheets), `body_photos` (progress photos), `blood_test` (lab reports) and `workout_import`. Leave it out and a new rule reaches `plan_options`, `plan_continuation`, `weekly_workout`, `phase_edit` and `coach`. `enabled: false` keeps a rule that no run reads. A change that leaves them out keeps the rule's own.\n\nEvery change raises the set's `version` by one. A change reaches the AI's next run for a member: new plan options and plans, the next phases and the next plan of current members, adjustments and regenerations. Workouts already built keep what they were built with. A plan shows the versions that last shaped it: `GET /v1/members/{memberId}/plan` has `coaching.rulesVersion` and `coaching.profileVersion` (null while none is known).\n\nLimits: up to 100 rules and 20,000 characters on each sheet (the runs a rule's `features` name decide which), each rule up to 2,000 characters.\n\nTo try your rules before members get them, save them on your test environment and use **Try it** on your console's Coaching page: it builds plan options, a day's meals or a meal idea for a sample member, and nothing is kept for a member. A meal idea picked when the AI doesn't answer doesn't read your rules. A change reaches a member's next meal plan: the one they have today stays.\n\nIf Budy looks after your rules for you, these routes answer `403 feature_not_enabled`, your console's Coaching page shows your coach alone, and the AI reads the ready-made rules.\n\n# Coaching profile\n\nYour coach, for the AI: its name, its voice, and where its exercises come from.\n\n```json\nPUT /v1/coaching-profile\n{\"coachName\": \"Lina\", \"voice\": \"supportive\", \"exerciseSource\": \"library_first\"}\n```\n\n- `coachName`: up to 40 characters. The AI speaks as that coach. Without one it uses neutral wording, never \"Budy\".\n- `voice`: `supportive`, `motivational`, `direct`, `analytical` or `funny`, the coach's tone and wording, never what members train; null for the default tone.\n- `exerciseSource`: what the AI's exercise search shows it. `mixed` (the default) shows your library and Budy's exercises, yours first on a tie. `library_first` shows your matching exercises ahead of Budy's. `library_only` shows your library alone. It decides what the AI sees, never what it must pick. Without `budyCatalogue` the AI sees your library alone, whatever this says.\n\n`PUT` changes the fields you send (null clears one) and keeps the rest; `GET /v1/coaching-profile` reads it. Each change raises its `version` by one (0 is the defaults); the same profile again changes nothing. Send `expectVersion` to refuse a change if someone saved since (`409 profile_changed`). Like the rules, the profile reaches the AI after Budy's own instructions, and nothing checks or rewrites what the AI answers. Test keys change the test profile, live keys the live one. Your console keeps every version, can restore one, previews a draft on test, and promotes test to live.\n\n# Readers\n\nBudy reads what your members photograph: gear, body composition sheets, progress photos and lab reports. Each reader is a feature of its own (`GET /v1/features`): `equipmentScan`, `bodyScans` (sheets and progress photos) and `supplements` (lab reports and the monthly assessment).\n\n**Pictures are your uploads.** Upload each picture with `POST /v1/media/uploads` (JPEG, PNG, WebP or HEIC, up to 20 MB), then name it by `assetId`. A PDF's pages go as pictures, at most 4 pages a read. A read can start the moment an upload completes: it waits for the picture to be ready. The reads take a secret key, as uploads do.\n\n**Your uploads stay until you delete them.** A lab report, body composition sheet, progress photo or gear photo you upload for a reader is an upload like any other: it stays in your media library (`GET /v1/media`) and counts toward your storage. Budy never deletes it by itself. To remove one once it has been read, `DELETE /v1/media/{assetId}`: it leaves your library at once and Budy stops signing links to it (a link already handed out works until it expires, at most 13 hours). Its files go when Budy purges deleted media; `purgeDays` in `GET /v1/media/usage` says after how long, and is null while no purge is scheduled.\n\n| Route | What it does |\n|---|---|\n| `POST \u2026/equipment-scans` | `{\"photos\": [assetId, \u2026], \"place\": {\"kind\": \"gym\", \"name\": \"Hotel gym\"}}`: up to 10 photos of one place. Each photo's `items` are the pieces of gear in it, `matched` or `choose` (the member picks), from the equipment your exercises list (Budy's too with `budyCatalogue`), with `equipmentId` (`own:\u2026` for gear from your exercises) and `name`. A piece that fits none of it isn't listed. Put names in the member's `places[].equipment` |\n| `POST \u2026/body-scan-reads` | `{\"pages\": [assetId]}`: an InBody (or similar) sheet's values in kg, L and kcal, for the member to check |\n| `POST \u2026/body-scans`, `GET \u2026/body-scans` | Save the values the member checked (`scanDate`, `values`, `source` read or typed); one scan a calendar month. The newest reaches the member's plans and supplement assessments |\n| `POST \u2026/progress-photo-insights` | `{\"photos\": [{\"angle\": \"FRONT\", \"assetId\": \u2026}]}`: a short, neutral body summary the workout AI and the coach read. Each angle (`FRONT`, `SIDE_LEFT`, `SIDE_RIGHT`, `BACK`) is read once a member; asking is the member's opt-in to photos in their plans |\n| `POST \u2026/blood-test-reads` | `{\"pages\": [assetId]}`: a lab report's 9 PhenoAge markers as printed, and its other results, for the member to check |\n| `POST \u2026/blood-tests`, `GET \u2026/blood-tests` | Save the markers the member checked: with all 9, the biological age. One such test a calendar month |\n| `POST \u2026/supplement-assessments`, `GET \u2026/supplement-assessments` | This calendar month's (UTC) supplement assessment, once. Send the member's `health` answers with it the first time (medicines, current supplements, pregnancy, the medical disclaimer and the AI health-data consent your app asked for); the member's first plan gives their age and sex |\n\nReads answer `202` with a job; its webhook says it finished, and `GET /v1/jobs/{jobId}` has the result. The webhook leaves the result out: members' readings stay in your database at Budy. Every number a reader returns is for the member to check before you save it. Budy keeps what is saved (scans, tests and their biological age, assessments, the body summary) and each read's result on its job, all erased with the member.\n\n**Limits.** A member's gear photos a day (UTC), and their sheet reads and lab report reads a calendar month (in their time zone, 3 of each unless your plan says otherwise), are limited; the member's tier can set its own numbers. `GET /v1/features` has your limits (`limitPerMember`) and `GET \u2026/quota` what the member has left. Past them, `429 daily_limit_reached` or `429 read_limit_reached`.\n\n# Coach\n\nA chat between your member and your coach, with your coaching profile and rules, that knows the member's plan and can change it on the member's say-so. Switch Coach on in your console first (`feature_not_enabled` otherwise). Your app calls these with the member token (`me`); your server can call them for any member.\n\n```http\nPOST /v1/members/me/coach/messages\n{\"text\": \"The squat rack is taken today, what can I do instead?\"}\n```\n\nThe reply is a job (`202`, `Location: /v1/jobs/{jobId}`): poll `GET /v1/jobs/{jobId}`, or wait for `coach_reply.ready` and then GET it (the webhook leaves the messages out, as the readers' do). Its `result` has `memberMessage`, `coachMessage` and `quota`. A coach message has `text` (one line), `steps`, `basedOn` (facts from the member's data), `quickReplies` and `cards`. One reply runs at a time per member (`409 coach_reply_in_progress`).\n\n- **Cards.** A `change` card is something the coach proposes; nothing changes until the member chooses. A `clarify` card is a question the coach asks: send the member's answer with `replyTo` set to that coach message's `id` (free).\n- **Changes.** `kind` is `workout_update` (the rest of the phase harder, easier or with the member's wish; one workout update), `swap` (an exercise of today's workout for one of its plan swaps), `rest_today` (today's workout moved to tomorrow), `skip` (this week's skip) or `exercise_note` (the member's note on an exercise, used from the next phase). `POST \u2026/coach/changes/{changeId}/apply` with one of its `choices[].id` (or `decline`) applies it once; a workout update answers `202` and its `jobId` (`coach_change.ready` when the rebuilt workouts are checked). `POST \u2026/undo` undoes it while `canUndo`. A change whose data moved since comes back `stale` with a fresh proposal in `replacement`. `rows`, `costs` and the `result`'s `checks` are codes for your app's own words; `title` and the coach's text come in the member's language.\n- **History.** `GET \u2026/coach/messages` pages back with `next`/`cursor`; `DELETE` clears it (the changes stay). `GET \u2026/coach/changes` lists what the coach changed.\n- **Limits.** A new chat uses one of the member's chats for the day (`GET \u2026/coach/quota`, your Coach limit, reset at the member's midnight); follow-ups inside an open chat and answers to the coach's question are free. Past them, `429 daily_limit_reached`. A message that plainly describes self-harm, a medical emergency or an eating-disorder risk gets the coach's fixed safety reply and uses no chat. This check reads English wording; anything else goes to the AI, whose instructions on these no rule can change.\n\nThe coach never names Budy. The member's details (goal, days, places, limits) stay yours: the coach tells the member to change them in your app, and carries a wish into a workout update meanwhile.\n\n# Voice\n\n**Not available yet.** Voice is built, but it can't be switched on today: your console shows it as coming later. This section is here so you can plan for it.\n\nVoice-guided workouts: a coach's voice that talks members through each workout, in one of Budy's coach voices or your own. Switch Voice on in your console first. Each phase of a member's plan is voiced once it's built.\n\n- **A workout's clips.** `GET /v1/members/{memberId}/workouts/{workoutId}/voice` has `introUrl`, `outroUrl` and, per exercise in the workout's order, `nameUrl`, `instructionUrl` and `restUrl` (between sets), once `status` is `ready`. Until then it's `pending` or `generating` (with `estimatedReadyAt`); clips that failed are made again by themselves. `off` means the member turned the voice off.\n- **A member's voice.** `GET /v1/members/{memberId}/voice`; `PUT` it with a `voiceId` from `GET /v1/voices` and `enabled`. The first pick is free; then the changes a month your workout quality level allows (`429 voice_change_limit_reached`). A change re-voices the current phase.\n- **Your own voices.** An instructor's voice for your members:\n\n```http\nPUT /v1/voices/coach-lina\n{\"name\": \"Coach Lina\", \"consent\": {\"speakerName\": \"Lina Ortiz\", \"confirmed\": true}}\n```\n\n`confirmed: true` is your statement that you hold Lina's written consent to record her voice and to have it made into a voice that guides your members' workouts in your app. Then send the recording, 10 to 60 seconds of her talking clearly, up to 1 MB, typed as audio: `PUT /v1/voices/coach-lina/recording` (`202`). It's prepared by itself: `voice.ready`, or `voice.failed` with `failureReason` (`too_short`, `too_quiet`, `server_error`; send a new recording). Members can then pick its `voiceId`. `DELETE /v1/voices/coach-lina` stops it being offered or used; members who had it hear the default coach voice from their next clips.\n# Sign-in for your members\n\nIf your app has no server of its own, Budy can sign your members in (the Accounts feature). Your app calls `/v1/auth/\u2026` with its publishable app key, which is fine to ship inside the app: it opens these routes and nothing else. Each sign-in answers with a member token (60 minutes) and a refresh token:\n\n```json\n{\"token\": \"eyJ\u2026\", \"tokenType\": \"Bearer\", \"expiresAt\": \"\u2026\", \"expiresIn\": 3600,\n \"refreshToken\": \"bdy_rt_\u2026\", \"refreshExpiresAt\": \"\u2026\", \"sessionId\": \"ses_\u2026\", \"memberId\": \"acct_\u2026\", \"newMember\": true}\n```\n\n- **Email and password.** `POST /v1/auth/sign-up` with `email`, `password` (8 to 128 characters) and an optional `name`, then `POST /v1/auth/email/verify` with the 6-digit `code` from the email and the same `password`. Sign-up answers `202` whether or not the email already has an account; an existing account gets an email instead of a code. `POST /v1/auth/sign-in` signs in; until the email is confirmed it answers `email_not_verified` and sends a new code (`POST /v1/auth/email/resend` sends one too). Codes last 30 minutes and allow 5 tries.\n- **Apple and Google.** `POST /v1/auth/apple` with the `identityToken` (and `firstName`, `lastName` the first time, since Apple sends the name once), or `POST /v1/auth/google` with the `idToken`. Budy takes a token only when it was issued for your own app's IDs, set up in your console. A verified email joins the account that has it.\n- **Staying signed in.** When the member token expires, `POST /v1/auth/refresh` with the refresh token. You get a new pair, and the old refresh token stops working; send the new one next time. A session nobody uses for 90 days ends (your console sets the days).\n- **Signing out.** `POST /v1/auth/sign-out` with the member token ends this phone's session; `{\"everywhere\": true}` ends every session and member token. A forgotten password: `POST /v1/auth/password/forgot`, then `POST /v1/auth/password/reset` with the `code` and `newPassword`, which also signs out every phone.\n- **Deleting the account.** `DELETE /v1/members/me` with the member token erases the member and everything Budy holds on them. App stores ask apps to offer this inside the app. (Your server erases any member with its secret key: `DELETE /v1/members/{memberId}`.)\n- **Finding a member.** `GET /v1/members?email=\u2026` with your secret key finds the member who signs in with that email, for example when someone writes to you asking to be deleted. Members your server created have no email at Budy.\n- **Your own sign-in service.** If your app signs members in with Firebase Auth, Auth0, Clerk, Supabase or Cognito, `POST /v1/auth/exchange` with that service's ID token as `token` gives a member token (60 minutes, no refresh token: exchange a fresh ID token when it runs out). Set the service up in your console: its issuer (Firebase: `https://securetoken.google.com/<project>`) and the audiences its tokens name. Budy checks the signature against the keys the service publishes, the issuer, audience and dates, and refuses anonymous sign-ins. The same person always gets the same `memberId`.\n- **App checks.** Because the publishable key is inside your app, your console can ask that the routes making accounts, checking passwords or sending email (sign-up, `email/resend`, sign-in, `apple`, `google`, `password/forgot`, `exchange`) prove they come from your real app. iOS uses App Attest: attest a key once (`POST /v1/auth/app-attest/challenge`, then `POST /v1/auth/app-attest/keys` with `keyId`, the `attestation` in base64 and the `challenge`, attested over the challenge's SHA-256), then send `X-Budy-App-Check-Platform: ios`, `X-Budy-App-Attest-Key-Id` and `X-Budy-App-Check` (the assertion over the SHA-256 of the request body, base64). Android uses Play Integrity: a standard request with `requestHash` set to the hex SHA-256 of the body, sent as `X-Budy-App-Check-Platform: android` and `X-Budy-App-Check`. The web uses Cloudflare Turnstile: `X-Budy-App-Check-Platform: web` and the widget's token in `X-Budy-App-Check`. Start in report mode, which only logs; enforce refuses calls without a valid check, on live keys only, so simulators and debug builds keep working with test keys.\n\nThe same email at another app, or in the Budy app, is a different account: each app's members are in its own database. Errors never say whether an email has an account.\n\n# Notifications\n\nBudy sends push and email to your members in your app's name (the Notifications feature). Push goes out with your own Apple and Google credentials, set up in your console: an APNs key (the .p8 file, its key ID, your Team ID and the app's bundle ID) and a Firebase service account. Email comes from your app's name at Budy's sending domain, or from your own domain once it is verified with Budy, with replies going to your address.\n\n**Phones.** When your app gets a push token, register it: `POST /v1/members/me/devices` with the member token (or `POST /v1/members/{memberId}/devices` from your server) and `{\"platform\": \"ios\", \"token\": \"\u2026\", \"environment\": \"production\", \"locale\": \"de\"}`. Use `\"environment\": \"sandbox\"` for an iOS build run from Xcode. Registering a token another member had moves it to this one. `GET \u2026/devices` lists the member's phones (the token's last 6 characters, never the token), and `DELETE \u2026/devices/{deviceId}` stops pushes to one; call it when the member signs out. A member has at most 10 phones.\n\n**Your messages.** `POST /v1/notifications` from your server:\n\n```json\n{\"members\": [\"m_123\", \"m_456\"], \"channels\": [\"push\"], \"title\": \"Class moved\", \"body\": \"Your 6 pm class is at 7 pm today\",\n \"data\": {\"deep_link\": \"studio://classes/42\"}}\n```\n\nUp to 500 members a call, by `push`, `email` or both. Send `title` and `body`, or `template` (one of your templates, like `custom.class_moved`) with `variables` for its `{name}` placeholders; `{appName}` is always there. `data` goes to your app with the push (string values, 4 KB at most). The answer is `202` with the notification's `id`, how many deliveries were queued, and any `unknownMembers`; `GET /v1/notifications/{id}` counts its deliveries by channel and status.\n\n**Budy's events.** In your console, turn on the events your members should hear about, like `plan.ready` or `coach_reply.ready`, by push, email or both. Budy sends each in your words when you've written them, else in its own.\n\n**What happened.** `GET /v1/members/{memberId}/notifications` lists what Budy sent a member, newest first, with each delivery's `status`: `queued`, `sent`, `skipped` (nothing to send it with: no phone, no credential, no email address), `not_delivered` (no phone took it), `paused` or `failed`. Budy tries again for about 9 hours when a push service or email is busy, and removes phones the push services say are gone.\n\n**Email limits.** Each app has a daily email limit, test and live counted apart. The first email past it pauses your app's email, sign-in's codes included, until it is resumed: a burst that size is usually someone scripting sign-ups. Members whose email Budy doesn't know (members your server created) get push only.\n\n# Your app's data\n\nYour app can keep its own data for each member at Budy, under keys you choose (the App data and media feature): settings, progress, anything your app needs. Budy stores each document as you send it, never reads it, and never shows it to an AI.\n\n```json\nPUT /v1/members/me/data/settings\n{\"value\": {\"units\": \"kg\", \"reminders\": [\"MON\", \"THU\"]}}\n```\n\n- **Documents.** `PUT /v1/members/{memberId}/data/{key}` adds (`201`) or replaces (`200`) a document: any JSON but null, up to 64 KB as compact JSON, and 200 documents a member. Keys are 1 to 128 letters, digits and `. _ : @ -`. `GET \u2026/data/{key}` reads one, `DELETE \u2026/data/{key}` removes it (`204`), and `GET \u2026/data` lists them, oldest first, 100 a page.\n- **Your server or your app.** A secret key reaches any member's documents; a member token its own member's, as `me`, so your app can keep its members' data without a server of yours.\n- **Writes that don't clash.** Each document has an `etag`, also in the `ETag` header, and every write gives it a new one. Send it as `If-Match` with `PUT` or `DELETE` to change only that version: if another phone wrote in between, you get `412 precondition_failed` with the current `etag` in `details`; read the document again and retry. `If-Match: *` changes a document only if it exists.\n- **Erasing.** A member's documents go when the member is erased: `DELETE /v1/members/{memberId}` from your server, or, with Budy's sign-in, `DELETE /v1/members/me` from your app.\n\n# Errors\n\nEvery error has the same shape:\n\n```json\n{\"error\": {\"code\": \"member_not_found\", \"message\": \"No member with that ID\", \"requestId\": \"cmvt\u2026\"}}\n```\n\nAct on `code`, which never changes; `message` is for people and may. `requestId` is also in the `X-Request-Id` header and in your console's request logs; quote it when you contact us. You can send your own `X-Request-Id` and we use it.\n\n| Status | Code | What happened |\n|---|---|---|\n| 400 | `invalid_request` | The body, query or a header doesn't fit the route |\n| 400 | `unknown_tier` | You haven't made a member tier with that key: make it in your console first |\n| 401 | `invalid_credentials` | No key or token, or one that isn't valid |\n| 401 | `token_expired` | A member token past its 60 minutes: get a new one |\n| 403 | `forbidden` | This credential can't use this route (a member token on a secret-key route) |\n| 403 | `feature_not_enabled` | Your plan doesn't include this feature (`GET /v1/features`) |\n| 403 | `feature_not_in_tier` | The member's tier doesn't include this feature (their `features` say what it does) |\n| 403 | `tenant_suspended` | Your partner account is suspended |\n| 403 | `tenant_not_live` | A live key or member token while your account isn't live |\n| 403 | `test_member_limit_reached` | The test environment holds all the members it may (`details.limit`): delete one, or ask us to raise it |\n| 403 | `test_ai_allowance_used` | This month's test AI on Budy's keys is used up; it comes back on `details.resetsOn`. Your own AI key carries on |\n| 403 | `ai_credit_limit_reached` | This month's AI credit limit on Budy's keys is reached; new AI comes back on `details.resetsOn`, or once we raise it. Your own AI key carries on |\n| 403 | `own_ai_key_required` | Your account runs only on your own AI keys, and none is ready: add your OpenAI key, or test the one saved, on your console's AI keys page. Nothing was started |\n| 404 | `not_found` | No such route |\n| 404 | `member_not_found` | No member with that ID for this key or token. A read never creates one, nor does a call that needs something the member would already have, like logging a workout |\n| 404 | `exercise_not_found` | No exercise with that ID in your library |\n| 404 | `rule_not_found` | No coaching rule with that ID |\n| 409 | `profile_changed` | The coaching profile changed since your `expectVersion`: read it again |\n| 405 | `method_not_allowed` | The route doesn't take that method |\n| 409 | `idempotency_in_progress` | A request with this `Idempotency-Key` is still running; retry after `Retry-After` |\n| 413 | `payload_too_large` | The body is over 1 MB |\n| 422 | `idempotency_key_reused` | This `Idempotency-Key` came with a different request |\n| 429 | `rate_limited` | Too many requests; wait `Retry-After` seconds |\n| 500 | `internal_error` | Something went wrong at Budy; it was logged |\n| 503 | `service_unavailable` | Budy can't answer right now; retry after `Retry-After` |\n\nValidation errors are `400`, never `422`.\n\nThe workout routes add their own codes:\n\n| Status | Code | What happened |\n|---|---|---|\n| 400 | `profile_incomplete` | A plan needs the member's goal, days (or `daysPerWeek`), places, sex, `birthYear` (or `birthDate`), `heightCm` and `weightKg`; `details.missing` names what's left, and no AI runs until they're there |\n| 400 | `unknown_exercise` | That exercise isn't in the catalogue or your library |\n| 403 | `member_inactive` | No AI work for a member set `active: false` |\n| 403 | `quota_exhausted` | The member has no workout updates left for an adjustment or a regeneration; the message says when more come |\n| 404 | `plan_not_found` | The member has no active plan; build one with `POST \u2026/plans` |\n| 404 | `workout_not_found` | No workout with that ID for this member |\n| 404 | `job_not_found` | No job with that ID |\n| 409 | `no_exercises` | Your library is empty and plans pick from it: add your exercises first (`POST /v1/exercises/imports`, `POST /v1/exercises/batch` or `PUT /v1/exercises/{exerciseRef}`) |\n| 409 | `plan_options_required` | The plan options to build from are gone: `POST \u2026/plans` again without `option` |\n| 409 | `plan_options_changed` | The member's plan options changed since; build from the new ones |\n| 409 | `plan_already_active` | The member already has an active plan |\n| 409 | `plan_in_progress`, `adjustment_in_progress`, `regeneration_in_progress` | One is already being built for this member; the message names its job |\n| 409 | `phase_in_progress` | This phase is being built; try again when it's done |\n| 409 | `regeneration_not_possible` | The phase can't be rebuilt now: it hasn't been built yet, a workout in it is under way, or all its workouts are finished |\n| 409 | `not_an_alternative` | A swap must be one of that exercise's alternatives |\n| 409 | `exercise_not_in_workout`, `workout_finished` | The exercise isn't in that workout, or the workout is already done |\n| 409 | Other snake_case codes | The member's plan isn't in a state that allows this right now, for example `no_active_plan`, `nothing_to_adjust`, `phase_has_no_workouts_left`, `exercises_not_ahead`, `workout_not_finished` or `workout_not_calibratable`. The message says why |\n| 429 | `daily_limit_reached` | Plan options and plans each have your plans-a-day number a member in 24 hours (3 unless you set it); wait `Retry-After` seconds |\n\nThe readers add theirs:\n\n| Status | Code | What happened |\n|---|---|---|\n| 400 | `profile_incomplete` | The assessment needs the member's `health` answers (`details.missing`), or a biological age their `birthYear` |\n| 400 | `out_of_range`, `unit_unknown`, `no_values` | A saved value is outside what a scan or lab reports, in a unit Budy doesn't read, or missing (`details.key`) |\n| 409 | `read_in_progress` | A read of this kind is already running for the member; the message names its job |\n| 409 | `monthly_limit` | This month's scan, biological age or assessment is in; `details.nextFrom` says when the next one can be |\n| 409 | `plan_required` | Supplements read the member's age and sex from their first plan: build it first |\n| 429 | `read_limit_reached` | The member's sheet or report reads this month are used (`details.limit`, 3 unless your plan or their tier says otherwise); `details.nextReadFrom`, `Retry-After` |\n| 429 | `daily_limit_reached` | The member's equipment photos for today (UTC) are used; `Retry-After` |\n\nA read that can't finish fails its job with one of these in `error.code`: `picture_unusable` (an upload failed or was deleted), `pictures_not_ready` (not ready within 30 minutes), `pictures_unavailable`, `monthly_limit`, `read_limit_reached`, `member_inactive`, `feature_not_enabled`, `profile_incomplete` or `read_failed` (Budy's quiet retries ran out; send it again).\n\nLibrary imports add theirs:\n\n| Status | Code | What happened |\n|---|---|---|\n| 404 | `import_not_found` | No import with that ID |\n| 409 | `import_running` | Another import is receiving, checking or applying; the message names it |\n| 409 | `import_not_receiving` | The import takes no file now |\n| 409 | `import_not_checked` | The import isn't checked yet (apply, `report.csv`) |\n| 409 | `import_finished` | The import is applied, failed, cancelled or expired already |\n| 410 | `import_expired` | The import is past its 7 days: start a new one |\n| 413 | `import_too_large` | The file is over the limit (1 MB on `/v1`) |\n| 415 | `import_wrong_type` | The file isn't typed `text/csv` or `application/x-ndjson`, as its format |\n\nThe coach adds its own:\n\n| Status | Code | What happened |\n|---|---|---|\n| 404 | `change_not_found` | No coach change with that ID for this member |\n| 409 | `coach_reply_in_progress` | The coach is still answering this member; the message names the job |\n| 409 | `undo_not_possible` | The change can't be undone (its window passed, or what it changed moved on); `details.reason` says which |\n| 429 | `daily_limit_reached` | The member's coach chats today are used; wait `Retry-After` seconds |\n\nVoice adds its own:\n\n| Status | Code | What happened |\n|---|---|---|\n| 400 | `consent_required` | A new voice needs your consent statement |\n| 404 | `voice_not_found` | No voice with that ID |\n| 409 | `voice_not_ready` | That voice isn't ready yet |\n| 409 | `voice_not_waiting` | The voice already has its recording (being prepared, or ready); add a new voice for another |\n| 415 | `voice_wrong_type` | The recording isn't typed as audio |\n| 429 | `voice_change_limit_reached` | The member's voice changes this month are used; wait `Retry-After` seconds |\nSign-in adds its own:\n\n| Status | Code | What happened |\n|---|---|---|\n| 400 | `invalid_code` | The email code, or the password sent with it, isn't right, or the code expired: ask for a new one |\n| 401 | `invalid_credentials` | Wrong email or password, or an Apple or Google token that isn't for your app |\n| 401 | `session_expired` | The refresh token was signed out, expired or used twice: sign in again |\n| 403 | `email_not_verified` | The email isn't confirmed yet; a new code is on its way |\n| 403 | `sign_in_method_unavailable` | That sign-in method isn't set up for your app |\n| 403 | `app_check_failed` | Your app checks are enforced and the call's app check is missing or doesn't hold |\n| 409 | `email_in_use` | An account with this email signs in another way |\n| 429 | `rate_limited` | Too many failed sign-ins for this email or from this address; wait `Retry-After` seconds |\n| 503 | `service_unavailable` | Sign-in can't count attempts right now, or your sign-in service, Google or Cloudflare didn't answer; try again after `Retry-After` |\n\nNotifications add their own:\n\n| Status | Code | What happened |\n|---|---|---|\n| 400 | `template_not_found` | You have no template of that name for one of the channels asked |\n| 404 | `device_not_found` | No such phone for this member |\n| 404 | `notification_not_found` | No notification with that ID |\n| 409 | `too_many_devices` | The member has 10 phones already; remove one first |\n\nApp data adds its own:\n\n| Status | Code | What happened |\n|---|---|---|\n| 404 | `document_not_found` | The member has no document with that key |\n| 409 | `document_limit_reached` | The member has 200 documents: delete one first |\n| 412 | `precondition_failed` | The document changed since your `If-Match` version, or isn't there; `details.etag` is the current one |\n| 413 | `document_too_large` | The document is over 64 KB as compact JSON; `details.maxBytes`, `details.sizeBytes` |\n\n# Safe retries\n\nSend an `Idempotency-Key` header (1 to 255 printable characters, a UUID is ideal) on any `POST` or `PUT`, and the request runs once however often you send it. We keep the key and the answer for 24 hours.\n\n- The same key with the same request gets the first answer again, with `Idempotent-Replayed: true`.\n- The same key with a different request gets `422 idempotency_key_reused`.\n- While the first request is still running, a retry gets `409 idempotency_in_progress` with `Retry-After`.\n\nOnly successful (`2xx`) answers are kept: after an error the key is free and a retry runs again. Keys belong to your server (all your secret keys share them) or to one member (their member tokens). Member tokens are never kept, so a retry of `POST /v1/members/{memberId}/tokens` gets a fresh token.\n\n# Pagination\n\nLists return up to `limit` items (1 to 100; 100 when you leave it out) and a `next` cursor:\n\n```json\n{\"data\": [ \u2026 ], \"next\": \"eyJjIjoi\u2026\"}\n```\n\nPass `next` back as `cursor` for the following page. `next` is `null` on the last page. Cursors are opaque: don't build or change them.\n\n# Rate limits\n\n- **600 requests a minute** for each secret key, and for each member's tokens. Past it, `429 rate_limited` with `Retry-After` in seconds.\n- **Plan options and plans:** your plans-a-day number for each, a member in 24 hours (3 unless you set it in your console's Member limits). Past it, `429 daily_limit_reached` with `Retry-After`.\n- **Readers, a member:** equipment photos up to Budy's daily number (UTC day; `429 daily_limit_reached`); 3 sheet reads and 3 report reads a calendar month, counted once the AI answered (`429 read_limit_reached`); one body scan, one biological age and one supplement assessment a calendar month (`409 monthly_limit`).\n- **Coach chats:** your Coach limit a member a day, reset at the member's midnight; follow-ups inside an open chat are free. Past it, `429 daily_limit_reached` with `Retry-After`.\n- **Bad credentials:** past 30 requests a minute from one address with keys or tokens that don't work, the next one gets `429` instead of `401`. A key or token that works is never refused for this.\n- **Bodies** are at most 1 MB (`413 payload_too_large`).\n\nBack off when you see `429` or `503`, and spread large imports out over time.\n\n# Webhooks\n\nLong AI work answers `202` with a job (and its address in `Location`), and Budy tells your server when it's done by calling the webhook endpoints you set up in the console. You can also poll `GET /v1/jobs/{jobId}`.\n\n| Event | When |\n|---|---|\n| `plan_options.ready` | A plan-options job finished; the options are in `data.job.result` |\n| `plan.ready` | A plan job finished; it is the member's plan now |\n| `adjustment.ready` | An adjustment job finished |\n| `regeneration.ready` | A regeneration job finished; its phase is rebuilt, and what changed is in `data.job.result` |\n| `job.failed` | A job failed after Budy's own quiet retries |\n| `block.ready` | A phase of a member's plan is built: the next one, or one rebuilt (`data.rebuilt` is `true`) |\n| `plan.renewed` | A member's next plan has started |\n| `library.imported` | A library import was applied: `data.importId`, `data.env`, `data.counts` |\n| `media.ready` | An upload is ready to play or show: `data.asset` (no links; `GET /v1/media/{assetId}` for them) |\n| `media.failed` | An upload can't be used: `data.asset.error.code` says why |\n| `equipment_scan.ready`, `body_scan_read.ready`, `progress_photo_insight.ready`, `blood_test_read.ready`, `supplement_assessment.ready` | A reader's job finished: `data.job` without its result; `GET /v1/jobs/{jobId}` for it |\n| `meal_plan.ready` | A meal plan job finished: `data.job.result` has its `mealPlanId` and `date` |\n| `meal_idea.ready` | A meal idea job finished; `data.job.result` names the recipe, with the nutrition and the reason. `GET /v1/jobs/{jobId}` has the whole recipe |\n| `meal_photo.ready` | A meal photo job finished: `data.job` without its estimate; `GET /v1/jobs/{jobId}` for it |\n| `coach_reply.ready` | The coach answered a member's message: `data.job` without its result; `GET /v1/jobs/{jobId}` for both messages |\n| `coach_change.ready` | A workout update the member applied from the coach is rebuilt and checked; the change is in `data.job.result` |\n| `voice.ready` | One of your own voices is ready for members: `data.voice` |\n| `voice.failed` | A voice's recording couldn't be used: `data.voice.failureReason` |\n| `webhook.test` | Only the console's \"Send a test event\" |\n\nMore events come with later features; ignore types you don't know.\n\nEach delivery is a `POST` with this JSON body, and these headers:\n\n```json\n{\"id\": \"evt_\u2026\", \"type\": \"plan.ready\", \"createdAt\": \"2026-11-23T09:41:07Z\", \"env\": \"test\", \"data\": { \u2026 }}\n```\n\n```http\nBudy-Signature: t=1730200000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd\nBudy-Event-Id: evt_\u2026\nBudy-Event-Type: plan.ready\nBudy-Delivery-Id: \u2026\nBudy-Delivery-Attempt: 1\n```\n\n**Check the signature** before you trust a delivery. `v1` is HMAC-SHA256, keyed with your endpoint's signing secret (the whole `whsec_\u2026` string, shown once in the console), over the timestamp `t`, a dot and the raw body exactly as received. Accept the delivery when one `v1` matches and `t` is within five minutes of your clock. While you rotate a secret, deliveries carry one `v1` per secret that still signs.\n\n```python\nimport hashlib, hmac, time\n\ndef is_from_budy(header: str, raw_body: bytes, secret: str) -> bool:\n    parts = [part.split(\"=\", 1) for part in header.split(\",\") if \"=\" in part]\n    stamp = next((value for key, value in parts if key == \"t\"), \"\")\n    if not stamp.isdigit() or abs(time.time() - int(stamp)) > 300:\n        return False\n    expected = hmac.new(secret.encode(), f\"{stamp}.\".encode() + raw_body, hashlib.sha256).hexdigest()\n    return any(hmac.compare_digest(expected, value) for key, value in parts if key == \"v1\")\n```\n\n- **Repeats and order.** The same event may arrive more than once: drop repeats by `Budy-Event-Id`. Events may also arrive out of order: go by `createdAt` and the IDs in `data`, not by when they arrived.\n- **Retries.** Answer `2xx` within 10 seconds. Anything else is tried again after about 1 minute, 5 minutes, 30 minutes, 2 hours, 5 hours and 10 hours, with a last try when 24 hours are up. Every try is logged in the console, where you can resend a delivery or send a test event.\n- **Addresses.** Endpoints must be public `https` addresses. Budy refuses private, loopback and cloud metadata addresses, checks the address again at each delivery, and follows no redirects.\n\n# Request logs\n\nWe keep a log of your calls in your own database, and your console shows them: the time, method, route, status, how long it took, the error code, the request ID, which key or member made it. Never a body, a query or a header. Test and live calls are logged apart. Calls whose key isn't yours, or isn't a key at all, can't be tied to you and aren't in your logs. They're kept for 30 days from go-live, when your console's `retentionDays` reads 30; while it reads null, nothing is deleted.\n\n# Versioning\n\n`/v1` keeps its shape. New fields and new routes may appear, so ignore fields you don't know; nothing is renamed or removed. Anything that would break your app comes as `/v2`, with six months of overlap and a dated changelog.\n\n`GET /v1/features` tells your app which features your plan includes, with quality levels and limits, so it can hide what's off.\n\n# Meals and nutrition\n\nWith Nutrition in your plan, you ask Budy for a member's meals and get back its recommendations: meal plans, ideas for their next meal, and calories from a meal photo. No workout plan is needed. The AI picks the day's meals from Budy's recipes, and Budy only scales their servings, between 0.5 and 1.5, to reach the calories. Each recommendation carries its whole recipe: there's no route to list, search or read recipes. Meal plans and ideas are built to the member's daily targets, which come from the first of these they have:\n\n1. Your own numbers, with `PUT \u2026/nutrition-preferences`: `dailyCalories` and `proteinGrams`, with `carbGrams` and `fatGrams` if you have them.\n2. The option they picked for a workout plan, if they have one. `GET \u2026/plan` shows them as `nutrition`.\n3. What the AI sets from their profile, for which it needs their `goal`, `sex`, `birthYear` (or `birthDate`), `heightCm` and `weightKg`. It sets them again when those change, and uses none of the member's quota.\n\nTell Budy what the member eats with `PUT /v1/members/{memberId}/nutrition-preferences`, or in `PUT /v1/members/{memberId}` with everything else, in their own words. Only the fields you send change, and null clears one. `GET \u2026/nutrition-preferences` reads them back. These are the same preferences Budy's own app asks for:\n\n| Field | What it is |\n|---|---|\n| `dietType` | Their diet, such as \"vegetarian\" or \"halal\" |\n| `allergens` | Food allergies (a list) |\n| `dietaryRestrictions` | Other restrictions (a list) |\n| `specificIngredientsExclude` | Foods they won't eat (a list) |\n| `specificIngredientsInclude` | Foods they want more of (a list) |\n| `cuisinePreferences` | Cuisines they like (a list) |\n| `crossCulturalWillingness` | Whether they're open to other cuisines (`true` unless you say otherwise) |\n| `spiceLevel` | Such as `mild`, `medium`, `hot` or `extra_hot` |\n| `currentLocation`, `birthLocation` | Where they live and where they grew up |\n| `mealTimingPreferences` | Their meal times, such as `{\"breakfast\": \"08:00\", \"dinner\": \"19:30\"}` |\n| `nutritionCoachingPreferences` | `mealSuggestionMode`: `user_led` or `coach_suggested` |\n\nMeal plans leave out recipes that hold the member's allergies or foods to avoid, and meal ideas are chosen with them too.\n\n- `POST /v1/members/{memberId}/meal-plans` makes today's plan in the member's time zone (a job, about a minute): `{\"guidance\": \"eating out tonight\"}`, all optional. Who the member is (`goal`, `sex`, `birthYear`, `heightCm`, `weightKg` and the like) can come with it, and is saved to their profile. One a day: asking again the same day answers that day's job. Then `GET /v1/members/{memberId}/meal-plans/{day}`, with the job's `result.date`, has each meal's time, reason and nutrition, its recipe with ingredients, steps and pictures, and up to two alternatives.\n- `POST /v1/members/{memberId}/meal-ideas` suggests what to eat next (a job, seconds): `{\"guidance\": \"something light\", \"notRecipeIds\": [\"\u2026\"]}`, all optional. Each uses one of the member's `mealPlans` for the day. Then `GET /v1/jobs/{jobId}` has the recipe with its ingredients, steps and pictures, its nutrition and the reason. To ask for something else, send the `recipeId` you got in `notRecipeIds`.\n- `POST /v1/members/{memberId}/meal-photos` estimates calories and macros from a photo (a job, seconds; with `mealPhotos`). Send the photo as the body, a JPEG, PNG or WebP picture with its `Content-Type`, within 1 MB: Budy reads photos at 512 px, so resize first. One at a time per member; each uses one of the member's `mealPhotos` for the day once it's read. Budy keeps the photo only until it's read, then removes it; the estimate stays with the job.\n\nRecipe pictures are signed links that expire within hours: read the plan, or the meal idea's job, again for fresh ones. Webhooks (`meal_plan.ready`, `meal_idea.ready`, `meal_photo.ready`) carry IDs and numbers, never links: `meal_idea.ready` only names the recipe and `meal_photo.ready` carries no estimate, so read those with `GET /v1/jobs/{jobId}`. `GET /v1/members/{memberId}/quota` shows what's left today.\n\nErrors: `400 profile_incomplete` (nothing sets the member's targets yet: `details.missing` names what the AI needs), `409 meal_photo_in_progress`, `415 photo_wrong_type`, `404 meal_plan_not_found`, and `429 daily_limit_reached` with `Retry-After`.\n\n# Member tiers\n\nHow much each member can use is yours to set, on your console's **Member limits** page: workout plans a day, workout updates, meal ideas, meal photos, coach chats, gear photos, and sheet and lab report reads. Those numbers go to every member you don't put on a tier.\n\nTo sell different amounts, make your own tiers there (Free, Plus, Premium...): each tier includes some of the features your plan has, with the limit per member you want (or your plan's own). Voice is in a tier or not. Then put each member on one from your server, when you create them or later:\n\n```json\nPUT /v1/members/fm-8812\n{\"tier\": \"plus\"}\n```\n\nThe member gets that tier at once: their `features` and `quota` show it, and a route for a feature their tier leaves out answers `403 feature_not_in_tier`. `\"tier\": null` puts them back on your default tier, which is every feature in your plan at your plan's limits; that's also what members you never put on a tier get. Leaving `tier` out of a `PUT` keeps the one they're on. A tier you haven't made is `400 unknown_tier`. You can't delete a tier while members are on it: move them first.\n","version":"v1"},"paths":{"/members/{member_id}":{"put":{"tags":["Members"],"summary":"Create or update a member","description":"A secret key creates or updates any member. A member token, as `me`, changes that member's own\nprofile; `active` and `tier` stay with your server.","operationId":"put_member_members__member_id__put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MemberPut"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberWithQuota"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberWithQuota"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Members"],"summary":"Get a member","operationId":"get_member_members__member_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberWithQuota"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Members"],"summary":"Erase a member","operationId":"delete_member_members__member_id__delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members":{"get":{"tags":["Members"],"summary":"List members","operationId":"list_members_members_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cursor"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"description":"Only the member Budy signs in with this email","title":"Email"},"description":"Only the member Budy signs in with this email"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/export":{"get":{"tags":["Members"],"summary":"Export a member's data","description":"All Budy holds on the member, as one JSON document, for a person's request for their data.\nYour uploads aren't in it: `jobs` names the ones each read used.","operationId":"export_member_members__member_id__export_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"All Budy holds on the member","content":{"application/json":{}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/tokens":{"post":{"tags":["Members"],"summary":"Get a member token","operationId":"create_member_token_members__member_id__tokens_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberTokenOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/plan-options":{"post":{"tags":["Workout"],"summary":"Three plan options (job, 2-4 minutes)","description":"From the member's profile (PUT /v1/members/{memberId}); fields sent here are saved to it first.\n\nWhile one is running for the member, the same job comes back.","operationId":"plan_options_members__member_id__plan_options_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PlanOptionsRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/plans":{"post":{"tags":["Workout"],"summary":"Build the member's plan (job, 1-11 minutes)","description":"Who the member is and how they train can come with it, saved first. With an `option`, from the member's\nlatest plan options, or plan options Budy makes first if they have none. With no `option`, Budy makes them\nfirst and builds BALANCED, so no call to plan options is needed. The AI designs one week of the phase and how\nmuch to do in each of its weeks. Later phases and the next plan follow by themselves.","operationId":"build_plan_members__member_id__plans_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PlanRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/plan":{"get":{"tags":["Workout"],"summary":"The member's plan","operationId":"get_plan_members__member_id__plan_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plan"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/today":{"get":{"tags":["Workout"],"summary":"Today's workout","operationId":"get_today_members__member_id__today_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"IANA; defaults to the member's timeZone, then UTC","title":"Timezone"},"description":"IANA; defaults to the member's timeZone, then UTC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Today"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/workouts/{workout_id}":{"get":{"tags":["Workout"],"summary":"One workout","operationId":"get_workout_members__member_id__workouts__workout_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Workout"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/workouts/{workout_id}/complete":{"post":{"tags":["Workout"],"summary":"Log a workout","description":"Sets, reps, weights, effort and notes. The next phase is built from what was logged.","operationId":"complete_workout_members__member_id__workouts__workout_id__complete_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CompleteWorkoutRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutOutcome"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/workouts/{workout_id}/skip":{"post":{"tags":["Workout"],"summary":"Skip a workout","description":"Past the week's skips the workout stays in the plan (saved false).","operationId":"skip_workout_members__member_id__workouts__workout_id__skip_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SkipWorkoutRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutOutcome"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/swaps":{"post":{"tags":["Workout"],"summary":"Swap an exercise","description":"One of the AI's alternatives in one workout; free, no AI run. The planned exercise's ID goes back.","operationId":"swap_exercise_members__member_id__swaps_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SwapRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Swap"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/regenerations":{"post":{"tags":["Workout"],"summary":"Rebuild a phase's unfinished workouts (job, one workout update)","description":"Budy's own regeneration, all optional: the current phase unless you name one, harder or easier, what the\nmember wants changed, the exercises that don't suit them, and any of their details, saved first. Finished\nand skipped workouts stay. Uses one workout update; a failed one gives it back.","operationId":"regenerate_phase_members__member_id__regenerations_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RegenerationRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/adjustments":{"post":{"tags":["Workout"],"summary":"Change upcoming workouts from feedback (job, one workout update)","description":"The rest of the phase, changed for the member's words on some exercises, or for how workout 1\nor 2 of the phase felt. Uses one workout update; a failed one gives it back.","operationId":"adjust_phase_members__member_id__adjustments_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdjustmentRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/quota":{"get":{"tags":["Workout"],"summary":"What the member has left","operationId":"get_quota_members__member_id__quota_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberQuota"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/jobs/{job_id}":{"get":{"tags":["Jobs"],"summary":"A job's status and result","operationId":"get_job_jobs__job_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/features":{"get":{"tags":["Features"],"summary":"The partner's features","operationId":"get_features_features_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Features"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/exercises/imports":{"post":{"tags":["Library imports"],"summary":"Start an import","description":"A new import, receiving its file; one import receives, checks or applies at a time.","operationId":"start_import_exercises_imports_post","security":[{"PartnerCredential":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImportStart"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImport"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Library imports"],"summary":"List imports","operationId":"list_imports_exercises_imports_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImportList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/imports/{import_id}/source":{"put":{"tags":["Library imports"],"summary":"Send the import's file","description":"The file as the body, UTF-8, typed as its format. The check starts by itself: GET the import\nuntil it's checked (or failed). Nothing in the library changes yet.","operationId":"put_import_source_exercises_imports__import_id__source_put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"string","title":"Import Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImport"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"text/csv":{},"application/x-ndjson":{}}}}},"/exercises/imports/{import_id}/apply":{"post":{"tags":["Library imports"],"summary":"Apply a checked import","description":"Write the check's creates and updates (and mirror's hides), in the worker; rows with errors are\nskipped. If the library changed since the check, it's checked again first.","operationId":"apply_import_exercises_imports__import_id__apply_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"string","title":"Import Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImport"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/imports/{import_id}/cancel":{"post":{"tags":["Library imports"],"summary":"Cancel an import","operationId":"cancel_import_exercises_imports__import_id__cancel_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"string","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImport"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/imports/{import_id}":{"get":{"tags":["Library imports"],"summary":"Get an import","operationId":"get_import_exercises_imports__import_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"string","title":"Import Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImport"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/imports/{import_id}/rows":{"get":{"tags":["Library imports"],"summary":"The import's rows","operationId":"import_rows_exercises_imports__import_id__rows_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"string","title":"Import Id"}},{"name":"outcome","in":"query","required":false,"schema":{"anyOf":[{"enum":["create","update","unchanged","hide","error"],"type":"string"},{"type":"null"}],"title":"Outcome"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryImportRows"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/imports/{import_id}/report.csv":{"get":{"tags":["Library imports"],"summary":"The rows with errors, plus an error column","operationId":"import_report_exercises_imports__import_id__report_csv_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"import_id","in":"path","required":true,"schema":{"type":"string","title":"Import Id"}}],"responses":{"200":{"description":"The report","content":{"text/csv":{}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/search":{"get":{"tags":["Library"],"summary":"Search what plans pick from","description":"The search plan generation uses: your library (with `budyCatalogue`, Budy's names too), best first.","operationId":"search_exercises_exercises_search_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Exercise-name and equipment words","title":"Q"},"description":"Exercise-name and equipment words"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogueMatches"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/schema":{"get":{"tags":["Library"],"summary":"The library's fields and file formats","description":"Every field of an exercise in the form's order with its limits and options, the IDs routes\nkeep, the CSV's rules, and the import limits (on /v1, files up to the front door's 1 MB).","operationId":"exercise_schema_exercises_schema_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/exercises/export":{"get":{"tags":["Library"],"summary":"Export the library","description":"Every exercise (or only the hidden or shown ones), oldest first, in an import's columns.","operationId":"export_exercises_exercises_export_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"enum":["csv","ndjson"],"type":"string","description":"csv, or ndjson (PUT's body plus id a line)","default":"csv","title":"Format"},"description":"csv, or ndjson (PUT's body plus id a line)"},{"name":"hidden","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"true: hidden ones only; false: shown ones only","title":"Hidden"},"description":"true: hidden ones only; false: shown ones only"}],"responses":{"200":{"description":"The file","content":{"text/csv":{},"application/x-ndjson":{}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises/batch":{"post":{"tags":["Library"],"summary":"Add or replace up to 100 exercises","description":"Each exercise as PUT takes it, plus its id, checked on its own: the ones that fit are written\ntogether, in one change for the search, and each answer says created, replaced, unchanged or\nerror (with the field and why).","operationId":"batch_exercises_exercises_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExerciseBatch"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExerciseBatchOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/exercises/{exercise_ref}":{"put":{"tags":["Library"],"summary":"Add or replace an exercise","operationId":"put_exercise_exercises__exercise_ref__put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"exercise_ref","in":"path","required":true,"schema":{"type":"string","title":"Exercise Ref"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExercisePut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryExercise"}}}},"201":{"description":"Added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryExercise"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Library"],"summary":"Change an exercise","operationId":"patch_exercise_exercises__exercise_ref__patch","security":[{"PartnerCredential":[]}],"parameters":[{"name":"exercise_ref","in":"path","required":true,"schema":{"type":"string","title":"Exercise Ref"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExercisePatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryExercise"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Library"],"summary":"Get an exercise","operationId":"get_exercise_exercises__exercise_ref__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"exercise_ref","in":"path","required":true,"schema":{"type":"string","title":"Exercise Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryExercise"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exercises":{"get":{"tags":["Library"],"summary":"List the library","operationId":"list_exercises_exercises_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cursor"}},{"name":"hidden","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"true: hidden ones only; false: visible ones only","title":"Hidden"},"description":"true: hidden ones only; false: visible ones only"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LibraryExerciseList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/coaching-rules":{"get":{"tags":["Coaching rules"],"summary":"List the coaching rules","operationId":"list_rules_coaching_rules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingRules"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/coaching-rules/{rule_id}":{"put":{"tags":["Coaching rules"],"summary":"Add or change a coaching rule","operationId":"put_rule_coaching_rules__rule_id__put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingRulePut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingRuleOut"}}}},"201":{"description":"Added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingRuleOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Coaching rules"],"summary":"Get a coaching rule","operationId":"get_rule_coaching_rules__rule_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingRule"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Coaching rules"],"summary":"Remove a coaching rule","operationId":"delete_rule_coaching_rules__rule_id__delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","title":"Rule Id"}}],"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/coaching-profile":{"get":{"tags":["Coaching profile"],"summary":"Get the coaching profile","operationId":"get_profile_coaching_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingProfileOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]},"put":{"tags":["Coaching profile"],"summary":"Change the coaching profile","operationId":"put_profile_coaching_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingProfilePut"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingProfileOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/members/{member_id}/equipment-scans":{"post":{"tags":["Equipment scans"],"summary":"Name the gear in each photo, every piece (job, seconds)","description":"Each photo is matched against your equipment: `items` are the pieces, each `matched` or `choose`.","operationId":"equipment_scan_members__member_id__equipment_scans_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EquipmentScanRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/body-scan-reads":{"post":{"tags":["Body scans"],"summary":"Read an InBody (or similar) sheet (job, seconds)","description":"The values as printed, in kg, L and kcal, for the member to check before saving them.","operationId":"body_scan_read_members__member_id__body_scan_reads_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SheetReadRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/body-scans":{"post":{"tags":["Body scans"],"summary":"Save the values the member checked","description":"One scan a calendar month; the same date again replaces its values.\n\nThe newest reaches the member's plans and supplement assessments.","operationId":"save_body_scan_members__member_id__body_scans_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyScanSaveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyScans"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Body scans"],"summary":"The member's scans","operationId":"get_body_scans_members__member_id__body_scans_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"description":"The member's IANA zone (else theirs, else UTC)","title":"Timezone"},"description":"The member's IANA zone (else theirs, else UTC)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BodyScans"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/progress-photo-insights":{"post":{"tags":["Body scans"],"summary":"The body summary plans read, from progress photos (job, seconds)","description":"Each angle is read once; the summary then reaches the member's plans (asking is the member's opt-in).","operationId":"progress_photo_insight_members__member_id__progress_photo_insights_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressPhotoInsightRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/blood-test-reads":{"post":{"tags":["Supplements"],"summary":"Read a blood test report's 9 markers (job, seconds)","description":"The markers as printed, for the member to check before saving them.","operationId":"blood_test_read_members__member_id__blood_test_reads_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SheetReadRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/blood-tests":{"post":{"tags":["Supplements"],"summary":"Save the markers the member checked: the biological age","description":"With all 9 markers, the biological age (PhenoAge); one such test a calendar month.","operationId":"save_blood_test_members__member_id__blood_tests_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BloodTestSaveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BloodTests"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Supplements"],"summary":"The newest test and every biological age","operationId":"get_blood_tests_members__member_id__blood_tests_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"description":"The member's IANA zone (else theirs, else UTC)","title":"Timezone"},"description":"The member's IANA zone (else theirs, else UTC)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BloodTests"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/supplement-assessments":{"post":{"tags":["Supplements"],"summary":"This month's supplement assessment (job, up to 2 minutes)","description":"One a calendar month (UTC). Health answers sent here are saved first.","operationId":"supplement_assessment_members__member_id__supplement_assessments_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SupplementAssessmentRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Supplements"],"summary":"The member's assessments, newest month first","operationId":"get_supplement_assessments_members__member_id__supplement_assessments_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplementAssessments"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/nutrition-preferences":{"get":{"tags":["Nutrition"],"summary":"What the member eats","operationId":"get_nutrition_preferences_members__member_id__nutrition_preferences_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NutritionPreferences"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Nutrition"],"summary":"Set what the member eats","description":"Only the fields sent change; null clears one. Meal plans and ideas read them from then on.","operationId":"put_nutrition_preferences_members__member_id__nutrition_preferences_put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NutritionPreferencesPut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NutritionPreferences"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/meal-plans":{"post":{"tags":["Nutrition"],"summary":"Today's meal plan (job, about a minute)","description":"For the member's local day. One a day: asking again the same day answers that day's job.","operationId":"start_meal_plan_members__member_id__meal_plans_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MealPlanRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/meal-plans/{day}":{"get":{"tags":["Nutrition"],"summary":"A day's meal plan","description":"``day`` is the member's local day (YYYY-MM-DD), as the meal plan job's result names it.","operationId":"get_meal_plan_members__member_id__meal_plans__day__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"day","in":"path","required":true,"schema":{"type":"string","format":"date","title":"Day"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealPlan"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/meal-ideas":{"post":{"tags":["Nutrition"],"summary":"What to eat next (job, seconds)","description":"Uses one of the day's mealPlans runs. While one is running for the member, the same job comes back.","operationId":"start_meal_idea_members__member_id__meal_ideas_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MealIdeaRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/meal-photos":{"post":{"tags":["Nutrition"],"summary":"Calories and macros from a photo (job, seconds)","description":"The photo as the body: a JPEG, PNG or WebP picture typed as one, within the 1 MB a request takes\n(Budy reads it at 512 px, so resize first). One of the day's mealPhotos is spent when it's read.\nOne at a time per member (409 meal_photo_in_progress). The photo is kept only until its job finishes.","operationId":"start_meal_photo_members__member_id__meal_photos_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"image/jpeg":{},"image/png":{},"image/webp":{}}}}},"/members/{member_id}/coach/messages":{"post":{"tags":["Coach"],"summary":"Send the member's message to the coach (job, seconds)","description":"The reply comes as the job's result, with the member's message and any change cards. A new chat\nuses one of the member's chats for the day; follow-ups inside it, and answers to the coach's own\nquestion, are free. One reply at a time per member (409 coach_reply_in_progress).","operationId":"send_message_members__member_id__coach_messages_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachMessageRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Coach"],"summary":"The member's chat","description":"The latest messages, oldest first within the page; next gives the ones before them. Change cards\nshow each change as it is now.","operationId":"list_messages_members__member_id__coach_messages_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"description":"next from the previous page: older messages","title":"Cursor"},"description":"next from the previous page: older messages"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":50,"minimum":1},{"type":"null"}],"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachMessages"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Coach"],"summary":"Clear the member's chat","description":"Deletes every message; the changes the coach made stay listed.","operationId":"clear_messages_members__member_id__coach_messages_delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Cleared"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/coach/quota":{"get":{"tags":["Coach"],"summary":"Coach chats left today","operationId":"coach_quota_members__member_id__coach_quota_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"IANA; defaults to the member's timeZone, then UTC","title":"Timezone"},"description":"IANA; defaults to the member's timeZone, then UTC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachQuota"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/coach/changes":{"get":{"tags":["Coach"],"summary":"Changes the coach made","description":"Newest first, with their status and undo; proposals nobody answered are left out.","operationId":"list_changes_members__member_id__coach_changes_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"IANA; defaults to the member's timeZone, then UTC","title":"Timezone"},"description":"IANA; defaults to the member's timeZone, then UTC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChanges"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/coach/changes/{change_id}":{"get":{"tags":["Coach"],"summary":"One change now","operationId":"get_change_members__member_id__coach_changes__change_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"change_id","in":"path","required":true,"schema":{"type":"string","title":"Change Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"IANA; defaults to the member's timeZone, then UTC","title":"Timezone"},"description":"IANA; defaults to the member's timeZone, then UTC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChange"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/coach/changes/{change_id}/apply":{"post":{"tags":["Coach"],"summary":"Apply a change with the member's choice","description":"Once: a second apply answers the change as it stands. A change whose data moved since comes back\nstale with a fresh proposal in replacement. A workout update answers 202 while the worker rebuilds.","operationId":"apply_change_members__member_id__coach_changes__change_id__apply_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"change_id","in":"path","required":true,"schema":{"type":"string","title":"Change Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"IANA; defaults to the member's timeZone, then UTC","title":"Timezone"},"description":"IANA; defaults to the member's timeZone, then UTC"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyChangeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChange"}}}},"202":{"description":"A workout update: the worker rebuilds (jobId)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChange"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/coach/changes/{change_id}/undo":{"post":{"tags":["Coach"],"summary":"Undo an applied change","description":"Within its undo window (canUndo), and only while what it changed is as it left it (409 undo_not_possible).","operationId":"undo_change_members__member_id__coach_changes__change_id__undo_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"change_id","in":"path","required":true,"schema":{"type":"string","title":"Change Id"}},{"name":"timeZone","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"IANA; defaults to the member's timeZone, then UTC","title":"Timezone"},"description":"IANA; defaults to the member's timeZone, then UTC"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachChange"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voices":{"get":{"tags":["Voice"],"summary":"The voices members can have","description":"Budy's coach voices and your own that are ready to use, waiting or failed (never removed ones).","operationId":"list_voices_voices_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Voices"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/voices/{voice_ref}":{"put":{"tags":["Voice"],"summary":"Add or rename one of your voices","description":"A new voice needs your consent statement: the speaker's name, and confirmed true (you hold their\nwritten consent). Then send its recording.","operationId":"put_voice_voices__voice_ref__put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"voice_ref","in":"path","required":true,"schema":{"type":"string","title":"Voice Ref"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoicePut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerVoice"}}}},"201":{"description":"Added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerVoice"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Voice"],"summary":"One of your voices","operationId":"get_voice_voices__voice_ref__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"voice_ref","in":"path","required":true,"schema":{"type":"string","title":"Voice Ref"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerVoice"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Voice"],"summary":"Stop using one of your voices","description":"Not offered any more; members who had it hear the default coach voice from their next clips.","operationId":"remove_voice_voices__voice_ref__delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"voice_ref","in":"path","required":true,"schema":{"type":"string","title":"Voice Ref"}}],"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voices/{voice_ref}/recording":{"put":{"tags":["Voice"],"summary":"Send a voice's recording","description":"The recording as the body, typed as audio: 10 to 60 seconds of the speaker talking clearly, up to 1 MB.\nIt's prepared by itself: GET the voice until it's ready (voice.ready) or failed (voice.failed).","operationId":"put_recording_voices__voice_ref__recording_put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"voice_ref","in":"path","required":true,"schema":{"type":"string","title":"Voice Ref"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerVoice"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"audio/*":{}}}}},"/members/{member_id}/voice":{"get":{"tags":["Voice"],"summary":"The member's voice","operationId":"get_member_voice_members__member_id__voice_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberVoice"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Voice"],"summary":"Change the member's voice","description":"The first pick is free; then the changes a month your workout quality level allows (429\nvoice_change_limit_reached). A change re-voices the current phase.","operationId":"put_member_voice_members__member_id__voice_put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberVoicePut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberVoice"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/workouts/{workout_id}/voice":{"get":{"tags":["Voice"],"summary":"A workout's voice clips","description":"The intro, each exercise's name, instructions and rest, and the outro, in the member's voice. Until\nthey're ready, the status says why; clips missing or failed are made again.","operationId":"get_workout_voice_members__member_id__workouts__workout_id__voice_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"workout_id","in":"path","required":true,"schema":{"type":"string","title":"Workout Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutVoice"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/media/uploads":{"post":{"tags":["Media"],"summary":"Start an upload","operationId":"start_upload_media_uploads_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUploadStart"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUploadStarted"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/media/{asset_id}/parts":{"post":{"tags":["Media"],"summary":"Sign parts again","operationId":"sign_parts_media__asset_id__parts_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaPartNumbers"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaParts"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/media/{asset_id}/complete":{"post":{"tags":["Media"],"summary":"Complete an upload","operationId":"complete_upload_media__asset_id__complete_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaComplete"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAsset"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/media/{asset_id}/upload":{"delete":{"tags":["Media"],"summary":"Give up an upload","operationId":"abort_upload_media__asset_id__upload_delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAborted"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/media":{"get":{"tags":["Media"],"summary":"List your media","operationId":"list_media_media_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"enum":["video","image"],"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["uploading","processing","ready","failed","deleted"],"type":"string"},{"type":"null"}],"description":"Deleted media shows only when asked for","title":"Status"},"description":"Deleted media shows only when asked for"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/media/usage":{"get":{"tags":["Media"],"summary":"Your media storage","operationId":"media_usage_media_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaUsage"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/media/{asset_id}":{"get":{"tags":["Media"],"summary":"Get an asset","operationId":"get_media_media__asset_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAsset"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Media"],"summary":"Change an asset's title","operationId":"patch_media_media__asset_id__patch","security":[{"PartnerCredential":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaTitle"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAsset"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Media"],"summary":"Delete an asset","operationId":"delete_media_media__asset_id__delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAsset"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/auth/sign-up":{"post":{"tags":["Sign-in"],"summary":"Sign up with email and password","operationId":"sign_up_auth_sign_up_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignUpIn"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedOut"}}}},"201":{"description":"Signed in at once (email verification off)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/email/verify":{"post":{"tags":["Sign-in"],"summary":"Confirm the email with its code","operationId":"verify_email_auth_email_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/email/resend":{"post":{"tags":["Sign-in"],"summary":"Send a new verification code","operationId":"resend_verification_auth_email_resend_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailIn"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/sign-in":{"post":{"tags":["Sign-in"],"summary":"Sign in with email and password","operationId":"sign_in_auth_sign_in_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignInIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/apple":{"post":{"tags":["Sign-in"],"summary":"Sign in with Apple","operationId":"sign_in_with_apple_auth_apple_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppleIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/google":{"post":{"tags":["Sign-in"],"summary":"Sign in with Google","operationId":"sign_in_with_google_auth_google_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/refresh":{"post":{"tags":["Sign-in"],"summary":"Get a new member token","operationId":"refresh_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/sign-out":{"post":{"tags":["Sign-in"],"summary":"Sign out","operationId":"sign_out_auth_sign_out_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SignOutIn"},{"type":"null"}],"title":"Body"}}}},"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/password/forgot":{"post":{"tags":["Sign-in"],"summary":"Email a password reset code","operationId":"forgot_password_auth_password_forgot_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailIn"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/password/reset":{"post":{"tags":["Sign-in"],"summary":"Set a new password with the code","operationId":"reset_password_auth_password_reset_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetIn"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/exchange":{"post":{"tags":["Sign-in"],"summary":"Swap your sign-in service's token for a member token","operationId":"exchange_auth_exchange_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangeIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExchangedOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/app-attest/challenge":{"post":{"tags":["Sign-in"],"summary":"Get a challenge for attesting a key","operationId":"app_attest_challenge_auth_app_attest_challenge_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppAttestChallengeOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/auth/app-attest/keys":{"post":{"tags":["Sign-in"],"summary":"Keep a key Apple attested","operationId":"app_attest_keys_auth_app_attest_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppAttestKeyIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppAttestKeyOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/members/{member_id}/devices":{"post":{"tags":["Notifications"],"summary":"Register a phone for push","operationId":"add_device_members__member_id__devices_post","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceOut"}}}},"200":{"description":"The phone was registered for this member already","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Notifications"],"summary":"List a member's phones","operationId":"get_devices_members__member_id__devices_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/devices/{device_id}":{"delete":{"tags":["Notifications"],"summary":"Remove a phone","operationId":"delete_device_members__member_id__devices__device_id__delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"device_id","in":"path","required":true,"schema":{"type":"string","title":"Device Id"}}],"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/notifications":{"get":{"tags":["Notifications"],"summary":"List what Budy sent a member","operationId":"get_member_notifications_members__member_id__notifications_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryList"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/notifications":{"post":{"tags":["Notifications"],"summary":"Send a message to members","operationId":"send_notification_notifications_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationIn"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationQueuedOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"PartnerCredential":[]}]}},"/notifications/{notification_id}":{"get":{"tags":["Notifications"],"summary":"See how a message went","operationId":"get_notification_notifications__notification_id__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"string","title":"Notification Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationOut"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/data":{"get":{"tags":["App data"],"summary":"The member's documents","operationId":"list_documents_members__member_id__data_get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"1 to 100","default":100,"title":"Limit"},"description":"1 to 100"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The last page's next","title":"Cursor"},"description":"The last page's next"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDataPage"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/members/{member_id}/data/{key}":{"get":{"tags":["App data"],"summary":"One document","operationId":"get_document_members__member_id__data__key__get","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDataDocument"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["App data"],"summary":"Add or replace a document","description":"Up to 64 KB as compact JSON, 200 documents a member. With If-Match, only the version named.","operationId":"put_document_members__member_id__data__key__put","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Change only this version: an ETag, or * for any","title":"If-Match"},"description":"Change only this version: an ETag, or * for any"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDataPut"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDataDocument"}}}},"201":{"description":"Added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppDataDocument"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"idempotency_in_progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"idempotency_key_reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["App data"],"summary":"Remove a document","operationId":"delete_document_members__member_id__data__key__delete","security":[{"PartnerCredential":[]}],"parameters":[{"name":"member_id","in":"path","required":true,"schema":{"type":"string","title":"Member Id"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}},{"name":"If-Match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Change only this version: an ETag, or * for any","title":"If-Match"},"description":"Change only this version: an ETag, or * for any"}],"responses":{"204":{"description":"Successful Response"},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"invalid_credentials or token_expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"forbidden, feature_not_enabled or tenant_suspended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found, member_not_found, exercise_not_found, rule_not_found or media_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited, with Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"AcceptedOut":{"properties":{"accepted":{"type":"boolean","title":"Accepted","description":"Done: if the email has an account, its email is on its way","default":true}},"type":"object","title":"AcceptedOut"},"AdjustmentRequest":{"properties":{"feedback":{"anyOf":[{"items":{"$ref":"#/components/schemas/FeedbackItem"},"type":"array","maxItems":20,"minItems":1},{"type":"null"}],"title":"Feedback"},"calibration":{"anyOf":[{"$ref":"#/components/schemas/CalibrationIn"},{"type":"null"}]},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language"}},"additionalProperties":false,"type":"object","title":"AdjustmentRequest","description":"POST \u2026/adjustments: change the rest of the phase from feedback (one workout update).\n\nEither feedback on exercises, or how workout 1 or 2 of the phase felt."},"AppAttestChallengeOut":{"properties":{"challenge":{"type":"string","title":"Challenge","description":"Attest your key over its SHA-256 within expiresIn seconds; it works once"},"expiresIn":{"type":"integer","title":"Expiresin"}},"type":"object","required":["challenge","expiresIn"],"title":"AppAttestChallengeOut"},"AppAttestKeyIn":{"properties":{"keyId":{"type":"string","maxLength":100,"title":"Keyid","description":"The key ID DCAppAttestService.generateKey gave your app"},"attestation":{"type":"string","maxLength":32768,"title":"Attestation","description":"The attestation object attestKey gave your app, base64"},"challenge":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$","title":"Challenge","description":"From /v1/auth/app-attest/challenge; your app attests the key over its SHA-256"}},"additionalProperties":false,"type":"object","required":["keyId","attestation","challenge"],"title":"AppAttestKeyIn"},"AppAttestKeyOut":{"properties":{"keyId":{"type":"string","title":"Keyid","description":"Send it as X-Budy-App-Attest-Key-Id with each assertion"},"environment":{"type":"string","title":"Environment","description":"production, or development (test keys only)"}},"type":"object","required":["keyId","environment"],"title":"AppAttestKeyOut"},"AppDataDocument":{"properties":{"key":{"type":"string","title":"Key"},"value":{"title":"Value"},"etag":{"type":"string","title":"Etag","description":"Also the ETag header; send it as If-Match to change only this version"},"sizeBytes":{"type":"integer","title":"Sizebytes"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat"}},"type":"object","required":["key","value","etag","sizeBytes","createdAt","updatedAt"],"title":"AppDataDocument"},"AppDataPage":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AppDataDocument"},"type":"array","title":"Data","description":"Oldest first"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next"}},"type":"object","required":["data"],"title":"AppDataPage"},"AppDataPut":{"properties":{"value":{"title":"Value","description":"Any JSON but null, up to 64 KB as compact JSON"}},"additionalProperties":false,"type":"object","required":["value"],"title":"AppDataPut"},"AppleIn":{"properties":{"identityToken":{"type":"string","maxLength":8192,"title":"Identitytoken","description":"The identity token Sign in with Apple gave your app"},"firstName":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Firstname","description":"Apple sends the name only the first time"},"lastName":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Lastname"}},"additionalProperties":false,"type":"object","required":["identityToken"],"title":"AppleIn"},"ApplyChangeRequest":{"properties":{"choice":{"type":"string","maxLength":32,"minLength":1,"title":"Choice","description":"One of the change's choices[].id, or decline"}},"additionalProperties":false,"type":"object","required":["choice"],"title":"ApplyChangeRequest"},"BiologicalAge":{"properties":{"testDate":{"type":"string","format":"date","title":"Testdate"},"biologicalAge":{"type":"integer","title":"Biologicalage"},"under":{"type":"boolean","title":"Under","default":false}},"type":"object","required":["testDate","biologicalAge"],"title":"BiologicalAge"},"BloodMarkerIn":{"properties":{"key":{"type":"string","enum":["albumin","creatinine","glucose","crp","lymphocytePercent","mcv","rdw","alkalinePhosphatase","wbc"],"title":"Key"},"value":{"type":"number","title":"Value"},"unit":{"type":"string","maxLength":40,"minLength":1,"title":"Unit"},"qualifier":{"anyOf":[{"type":"string","enum":["<",">"]},{"type":"null"}],"title":"Qualifier"}},"additionalProperties":false,"type":"object","required":["key","value","unit"],"title":"BloodMarkerIn"},"BloodMarkerSaved":{"properties":{"key":{"type":"string","title":"Key"},"value":{"type":"number","title":"Value"},"unit":{"type":"string","title":"Unit"},"qualifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qualifier"}},"type":"object","required":["key","value","unit"],"title":"BloodMarkerSaved"},"BloodOtherIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"value":{"type":"number","title":"Value"},"unit":{"type":"string","maxLength":40,"minLength":1,"title":"Unit"},"referenceRange":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Referencerange"},"qualifier":{"anyOf":[{"type":"string","enum":["<",">"]},{"type":"null"}],"title":"Qualifier"}},"additionalProperties":false,"type":"object","required":["name","value","unit"],"title":"BloodOtherIn"},"BloodTestLatest":{"properties":{"testDate":{"type":"string","format":"date","title":"Testdate"},"status":{"type":"string","title":"Status","description":"ready, missing (a marker short) or retest (CRP 10 mg/L or more)"},"biologicalAge":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Biologicalage","description":"PhenoAge to a whole year; 20 when under is true"},"under":{"type":"boolean","title":"Under","default":false},"age":{"type":"integer","title":"Age","description":"The member's age on the test date"},"missing":{"items":{"type":"string"},"type":"array","title":"Missing"},"markers":{"items":{"$ref":"#/components/schemas/BloodMarkerSaved"},"type":"array","title":"Markers"}},"type":"object","required":["testDate","status","age"],"title":"BloodTestLatest"},"BloodTestSaveRequest":{"properties":{"testDate":{"type":"string","format":"date","title":"Testdate"},"markers":{"items":{"$ref":"#/components/schemas/BloodMarkerIn"},"type":"array","maxItems":9,"title":"Markers"},"other":{"items":{"$ref":"#/components/schemas/BloodOtherIn"},"type":"array","maxItems":40,"title":"Other"},"timeZone":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Timezone","description":"The member's IANA zone: the calendar the month's limits count in (else the member's timeZone, else UTC)"}},"additionalProperties":false,"type":"object","required":["testDate"],"title":"BloodTestSaveRequest","description":"The numbers the member checked."},"BloodTests":{"properties":{"latest":{"anyOf":[{"$ref":"#/components/schemas/BloodTestLatest"},{"type":"null"}]},"readings":{"items":{"$ref":"#/components/schemas/BiologicalAge"},"type":"array","title":"Readings","description":"Every biological age, oldest first"},"nextTestFrom":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Nexttestfrom","description":"While this month's test with a biological age is in"},"nextReadFrom":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Nextreadfrom","description":"While this month's reads are used"}},"type":"object","title":"BloodTests"},"BodyScanItem":{"properties":{"scanDate":{"type":"string","format":"date","title":"Scandate"},"values":{"additionalProperties":{"type":"number"},"type":"object","title":"Values"},"source":{"type":"string","title":"Source"}},"type":"object","required":["scanDate","values","source"],"title":"BodyScanItem"},"BodyScanSaveRequest":{"properties":{"scanDate":{"type":"string","format":"date","title":"Scandate"},"values":{"$ref":"#/components/schemas/BodyScanValuesIn"},"source":{"type":"string","enum":["read","typed"],"title":"Source","default":"typed"},"timeZone":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Timezone","description":"The member's IANA zone: the calendar the month's limits count in (else the member's timeZone, else UTC)"}},"additionalProperties":false,"type":"object","required":["scanDate","values"],"title":"BodyScanSaveRequest","description":"The values the member checked (a reading, or typed)."},"BodyScanValuesIn":{"properties":{"weightKg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weightkg"},"skeletalMuscleMassKg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Skeletalmusclemasskg"},"bodyFatMassKg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Bodyfatmasskg"},"bodyMassIndex":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Bodymassindex"},"percentBodyFat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Percentbodyfat"},"visceralFatLevel":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Visceralfatlevel"},"totalBodyWaterLiters":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Totalbodywaterliters"},"leanBodyMassKg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Leanbodymasskg"},"basalMetabolicRateKcal":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Basalmetabolicratekcal"}},"additionalProperties":false,"type":"object","title":"BodyScanValuesIn","description":"A scan's values in kg, L, kcal, %; each optional, one at least."},"BodyScans":{"properties":{"scans":{"items":{"$ref":"#/components/schemas/BodyScanItem"},"type":"array","title":"Scans","description":"Newest scan date first"},"compareFrom":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Comparefrom","description":"The scan the newest compares with: 28+ days older"},"nextScanFrom":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Nextscanfrom","description":"While this month's scan is in"},"nextReadFrom":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Nextreadfrom","description":"While this month's reads are used"}},"type":"object","required":["scans"],"title":"BodyScans"},"CalibrationIn":{"properties":{"workoutId":{"type":"string","maxLength":64,"minLength":1,"title":"Workoutid","description":"Workout 1 or 2 of the phase, finished"},"feel":{"type":"string","enum":["easy","hard"],"title":"Feel"}},"additionalProperties":false,"type":"object","required":["workoutId","feel"],"title":"CalibrationIn"},"CatalogueMatch":{"properties":{"budyId":{"type":"string","title":"Budyid","description":"Budy's ID for the exercise, as plans and workouts name it"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"Your ID, for an exercise from your library"},"name":{"type":"string","title":"Name"},"equipment":{"items":{"type":"string"},"type":"array","title":"Equipment"},"optionalEquipment":{"items":{"type":"string"},"type":"array","title":"Optionalequipment"},"source":{"type":"string","enum":["library","budy"],"title":"Source","description":"library: yours; budy: a name from Budy's catalogue, which has no media for partners"}},"type":"object","required":["budyId","name","equipment","optionalEquipment","source"],"title":"CatalogueMatch"},"CatalogueMatches":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CatalogueMatch"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"CatalogueMatches"},"Choice":{"properties":{"id":{"type":"string","title":"Id"},"primary":{"type":"boolean","title":"Primary","default":false}},"type":"object","required":["id"],"title":"Choice"},"ClarifyOption":{"properties":{"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","title":"ClarifyOption"},"Cleared":{"properties":{"deleted":{"type":"integer","title":"Deleted"}},"type":"object","required":["deleted"],"title":"Cleared"},"CoachCard":{"properties":{"type":{"type":"string","title":"Type","description":"change, or clarify (a question the coach asked, answered with replyTo)"},"change":{"anyOf":[{"$ref":"#/components/schemas/CoachChange"},{"type":"null"}]},"question":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Question"},"options":{"anyOf":[{"items":{"$ref":"#/components/schemas/ClarifyOption"},"type":"array"},{"type":"null"}],"title":"Options"},"answered":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Answered"}},"type":"object","required":["type"],"title":"CoachCard"},"CoachChange":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","title":"Kind","description":"workout_update, swap, rest_today, skip or exercise_note"},"title":{"type":"string","title":"Title","description":"The coach's name for it, in the member's language"},"status":{"type":"string","title":"Status","description":"proposed, applying, applied, partial, failed, undone, expired, stale or declined"},"scope":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Scope"},"rows":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Rows","description":"What changes: field codes, before and after"},"costs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Costs","description":"What it uses: codes with their numbers"},"choices":{"items":{"$ref":"#/components/schemas/Choice"},"type":"array","title":"Choices"},"blocked":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Blocked","description":"Why it can't be applied now, with a code"},"note":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Note"},"choice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Choice"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result","description":"The server's checks once applied (or undone)"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"canUndo":{"type":"boolean","title":"Canundo","default":false},"jobId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jobid","description":"A workout update's job, while and after the worker rebuilds"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"expiresAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expiresat"},"appliedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Appliedat"},"undoUntil":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Undountil"},"undoneAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Undoneat"},"replacement":{"anyOf":[{"$ref":"#/components/schemas/CoachChange"},{"type":"null"}],"description":"When the member's data moved since: a fresh proposal in its place (this one is stale)"}},"type":"object","required":["id","kind","title","status"],"title":"CoachChange","description":"A change the coach proposed, with the member's choice, what came of it and its undo."},"CoachChanges":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CoachChange"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"CoachChanges"},"CoachMessage":{"properties":{"id":{"type":"string","title":"Id"},"role":{"type":"string","title":"Role","description":"member or coach"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"The member's words, or the coach's one-line answer"},"steps":{"items":{"type":"string"},"type":"array","title":"Steps"},"basedOn":{"items":{"type":"string"},"type":"array","title":"Basedon","description":"Facts from the member's own data"},"quickReplies":{"items":{"type":"string"},"type":"array","title":"Quickreplies"},"replyTo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replyto"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind","description":"answer, clarify or safety (coach messages)"},"cards":{"items":{"$ref":"#/components/schemas/CoachCard"},"type":"array","title":"Cards"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"}},"type":"object","required":["id","role"],"title":"CoachMessage"},"CoachMessageRequest":{"properties":{"text":{"type":"string","maxLength":2000,"minLength":1,"title":"Text","description":"In the member's words"},"replyTo":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Replyto","description":"The coach message this answers, when the coach asked a question (a clarify card): free"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA; defaults to the member's timeZone, then UTC. The day's chats follow it"}},"additionalProperties":false,"type":"object","required":["text"],"title":"CoachMessageRequest","description":"The member's message to the coach."},"CoachMessages":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CoachMessage"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next","description":"Older messages: pass back as cursor"}},"type":"object","required":["data"],"title":"CoachMessages"},"CoachQuota":{"properties":{"remaining":{"type":"integer","title":"Remaining","description":"Chats left today; follow-ups inside an open chat are free"},"dailyLimit":{"type":"integer","title":"Dailylimit"},"resetsAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resetsat","description":"The member's next midnight"},"chatOpenUntil":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Chatopenuntil"}},"type":"object","required":["remaining","dailyLimit"],"title":"CoachQuota"},"CoachingProfileFields":{"properties":{"coachName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coachname"},"voice":{"anyOf":[{"type":"string","enum":["supportive","motivational","direct","analytical","funny"]},{"type":"null"}],"title":"Voice"},"exerciseSource":{"type":"string","enum":["mixed","library_first","library_only"],"title":"Exercisesource","default":"mixed"}},"type":"object","title":"CoachingProfileFields"},"CoachingProfileOut":{"properties":{"version":{"type":"integer","title":"Version","description":"Goes up by one with every change; 0: the defaults, before the first"},"profile":{"$ref":"#/components/schemas/CoachingProfileFields"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["version","profile"],"title":"CoachingProfileOut"},"CoachingProfilePut":{"properties":{"coachName":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Coachname","description":"What your coach is called; null: no name, in neutral wording (never Budy)"},"voice":{"anyOf":[{"type":"string","enum":["supportive","motivational","direct","analytical","funny"]},{"type":"null"}],"title":"Voice","description":"The coach's tone; null: Budy's default tone"},"exerciseSource":{"anyOf":[{"type":"string","enum":["mixed","library_first","library_only"]},{"type":"null"}],"title":"Exercisesource","description":"What the exercise search shows the AI: mixed (default), library_first or library_only"},"expectVersion":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Expectversion","description":"The version your change starts from: if someone saved since, 409 profile_changed"}},"additionalProperties":false,"type":"object","title":"CoachingProfilePut","description":"PUT /v1/coaching-profile: the fields sent replace the saved ones (null clears one); the rest stay."},"CoachingRule":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the rule"},"text":{"type":"string","title":"Text"},"features":{"items":{"type":"string","enum":["plan_options","plan_continuation","weekly_workout","phase_edit","meal_plan","meal_suggestion","meal_photo","coach","supplement","equipment_identify","body_scan","body_photos","blood_test","workout_import"]},"type":"array","title":"Features","description":"Which AI runs read it"},"enabled":{"type":"boolean","title":"Enabled","description":"false: kept, but no AI run reads it"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat"}},"type":"object","required":["id","text","features","enabled","createdAt","updatedAt"],"title":"CoachingRule"},"CoachingRuleOut":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the rule"},"text":{"type":"string","title":"Text"},"features":{"items":{"type":"string","enum":["plan_options","plan_continuation","weekly_workout","phase_edit","meal_plan","meal_suggestion","meal_photo","coach","supplement","equipment_identify","body_scan","body_photos","blood_test","workout_import"]},"type":"array","title":"Features","description":"Which AI runs read it"},"enabled":{"type":"boolean","title":"Enabled","description":"false: kept, but no AI run reads it"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat"},"version":{"type":"integer","title":"Version","description":"The version of your whole set of rules after this change"}},"type":"object","required":["id","text","features","enabled","createdAt","updatedAt","version"],"title":"CoachingRuleOut"},"CoachingRulePut":{"properties":{"text":{"type":"string","maxLength":2000,"minLength":1,"title":"Text","description":"One guideline in plain words, e.g. 'Members over 60 never do box jumps'"},"features":{"anyOf":[{"items":{"type":"string","enum":["plan_options","plan_continuation","weekly_workout","phase_edit","meal_plan","meal_suggestion","meal_photo","coach","supplement","equipment_identify","body_scan","body_photos","blood_test","workout_import"]},"type":"array","maxItems":14,"minItems":1},{"type":"null"}],"title":"Features","description":"Which AI runs read it: plan_options, plan_continuation (the next plan's options), weekly_workout (each phase's workouts), phase_edit, meal_plan, meal_suggestion, meal_photo, coach (the coach's answers), supplement, equipment_identify, body_scan, body_photos, blood_test, workout_import. Left out: the rule's own (a new rule: plan_options, plan_continuation, weekly_workout, phase_edit and coach)."},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled","description":"false keeps the rule but no AI run reads it. Left out: the rule's own (a new rule: on)."}},"additionalProperties":false,"type":"object","required":["text"],"title":"CoachingRulePut","description":"PUT /v1/coaching-rules/{ruleId}."},"CoachingRules":{"properties":{"version":{"type":"integer","title":"Version","description":"Goes up by one with every change; 0 before the first, with the ready-made rules"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"},"data":{"items":{"$ref":"#/components/schemas/CoachingRule"},"type":"array","title":"Data"}},"type":"object","required":["version","data"],"title":"CoachingRules"},"CompleteWorkoutRequest":{"properties":{"startedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Startedat"},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completedat","description":"Defaults to now; never later than now"},"durationSeconds":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Durationseconds"},"effort":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Effort","description":"How hard it felt, 1 to 10"},"enjoyment":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Enjoyment"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes"},"caloriesBurned":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":0.0},{"type":"null"}],"title":"Caloriesburned"},"sets":{"anyOf":[{"items":{"$ref":"#/components/schemas/LoggedSetIn"},"type":"array","maxItems":500},{"type":"null"}],"title":"Sets"}},"additionalProperties":false,"type":"object","title":"CompleteWorkoutRequest","description":"POST \u2026/workouts/{workoutId}/complete. Sets sent but none done saves nothing."},"ConsentRecord":{"properties":{"speakerName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Speakername"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"confirmedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Confirmedat"}},"type":"object","title":"ConsentRecord"},"CurrentSupplementDetail":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"amount":{"anyOf":[{"type":"number","maximum":100000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Amount"},"unit":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"title":"Unit"},"frequency":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Frequency"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CurrentSupplementDetail"},"CurrentSupplements":{"properties":{"status":{"$ref":"#/components/schemas/HealthAnswerStatus","description":"NONE, PROVIDED or UNKNOWN"},"details":{"anyOf":[{"items":{"$ref":"#/components/schemas/CurrentSupplementDetail"},"type":"array","maxItems":30},{"type":"null"}],"title":"Details"}},"additionalProperties":false,"type":"object","required":["status"],"title":"CurrentSupplements"},"DeliveryList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DeliveryOut"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next","description":"Pass as cursor for the next page; null on the last"}},"type":"object","required":["data"],"title":"DeliveryList"},"DeliveryOut":{"properties":{"id":{"type":"string","title":"Id"},"notificationId":{"type":"string","title":"Notificationid"},"channel":{"type":"string","title":"Channel"},"source":{"type":"string","title":"Source","description":"message (yours), event (one of Budy's you turned on) or account (sign-in)"},"template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template"},"status":{"type":"string","title":"Status","description":"queued, sent, skipped, not_delivered, paused or failed"},"attempts":{"type":"integer","title":"Attempts"},"devices":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices"},"delivered":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Delivered"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"sentAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sentat"}},"type":"object","required":["id","notificationId","channel","source","status","attempts","createdAt"],"title":"DeliveryOut"},"DeviceIn":{"properties":{"platform":{"type":"string","enum":["ios","android"],"title":"Platform"},"token":{"type":"string","maxLength":512,"minLength":8,"title":"Token","description":"The APNs device token or FCM registration token"},"environment":{"type":"string","enum":["production","sandbox"],"title":"Environment","description":"sandbox for an iOS build from Xcode (APNs' development gateway)","default":"production"},"locale":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Locale","description":"The phone's language, like de or pt-BR"}},"additionalProperties":false,"type":"object","required":["platform","token"],"title":"DeviceIn"},"DeviceList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DeviceOut"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"DeviceList"},"DeviceOut":{"properties":{"id":{"type":"string","title":"Id"},"platform":{"type":"string","title":"Platform"},"environment":{"type":"string","title":"Environment"},"locale":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locale"},"tokenEnding":{"type":"string","title":"Tokenending","description":"The token's last 6 characters; the token is never shown again"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"updatedAt":{"type":"string","format":"date-time","title":"Updatedat"}},"type":"object","required":["id","platform","environment","tokenEnding","createdAt","updatedAt"],"title":"DeviceOut"},"EmailIn":{"properties":{"email":{"type":"string","maxLength":320,"title":"Email","description":"The member's email"}},"additionalProperties":false,"type":"object","required":["email"],"title":"EmailIn"},"EquipmentScanRequest":{"properties":{"photos":{"items":{"type":"string"},"type":"array","maxItems":10,"minItems":1,"title":"Photos","description":"Your uploads (pictures), one place's photos"},"place":{"anyOf":[{"$ref":"#/components/schemas/ScanPlace"},{"type":"null"}]},"mode":{"type":"string","enum":["scan","single"],"title":"Mode","description":"scan: the gear at a place; single: one item the member adds (a name is suggested)","default":"scan"}},"additionalProperties":false,"type":"object","required":["photos"],"title":"EquipmentScanRequest"},"ExchangeIn":{"properties":{"token":{"type":"string","maxLength":16384,"title":"Token","description":"An ID token from your own sign-in service (Firebase Auth, Auth0, ...)"}},"additionalProperties":false,"type":"object","required":["token"],"title":"ExchangeIn"},"ExchangedOut":{"properties":{"token":{"type":"string","title":"Token","description":"The member token: Authorization: Bearer \u2026 on the member's calls"},"tokenType":{"type":"string","title":"Tokentype","default":"Bearer"},"expiresAt":{"type":"string","format":"date-time","title":"Expiresat"},"expiresIn":{"type":"integer","title":"Expiresin","description":"Seconds until it expires; then exchange a fresh token again"},"memberId":{"type":"string","title":"Memberid","description":"The member's ID, the same for the same person each time"},"newMember":{"type":"boolean","title":"Newmember","description":"This exchange made the member","default":false}},"type":"object","required":["token","expiresAt","expiresIn","memberId"],"title":"ExchangedOut"},"ExerciseBatch":{"properties":{"exercises":{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":100,"minItems":1,"title":"Exercises","description":"Each as ExerciseBatchItem: PUT's body plus id"}},"additionalProperties":false,"type":"object","required":["exercises"],"title":"ExerciseBatch","description":"POST /v1/exercises/batch: up to 100 exercises, each PUT's body plus its id. Each is checked\non its own: the ones that fit are written, in one change for the search."},"ExerciseBatchError":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field"}},"type":"object","required":["code","message"],"title":"ExerciseBatchError"},"ExerciseBatchOut":{"properties":{"results":{"items":{"$ref":"#/components/schemas/ExerciseBatchResult"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"ExerciseBatchOut"},"ExerciseBatchResult":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"status":{"type":"string","enum":["created","replaced","unchanged","error"],"title":"Status"},"error":{"anyOf":[{"$ref":"#/components/schemas/ExerciseBatchError"},{"type":"null"}]}},"type":"object","required":["status"],"title":"ExerciseBatchResult"},"ExerciseClips":{"properties":{"exerciseId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exerciseid"},"nameUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nameurl"},"instructionUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructionurl"},"restUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resturl","description":"Between sets"}},"type":"object","title":"ExerciseClips"},"ExerciseMedia":{"properties":{"url":{"type":"string","title":"Url"},"type":{"type":"string","title":"Type","description":"video, image or other"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"}},"type":"object","required":["url","type"],"title":"ExerciseMedia"},"ExercisePatch":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"equipment":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"Equipment"},"measurement":{"anyOf":[{"type":"string","enum":["reps","time"]},{"type":"null"}],"title":"Measurement","description":"How plans measure it: reps, or time for holds and intervals such as a plank"},"perSide":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Perside","description":"Sets are done on each side, e.g. a lunge; plans say so"},"requiresWeight":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Requiresweight","description":"Sets ask the member for the weight used"},"notes":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Notes"},"instructions":{"anyOf":[{"items":{"type":"string","maxLength":300},"type":"array","maxItems":12},{"type":"null"}],"title":"Instructions","description":"Steps shown to members, in order. Display only: the AI and the search never read them"},"safetyTips":{"anyOf":[{"items":{"type":"string","maxLength":300},"type":"array","maxItems":8},{"type":"null"}],"title":"Safetytips","description":"Safety tips shown to members. Display only"},"commonMistakes":{"anyOf":[{"items":{"type":"string","maxLength":300},"type":"array","maxItems":8},{"type":"null"}],"title":"Commonmistakes","description":"Common mistakes shown to members. Display only"},"tags":{"anyOf":[{"items":{"type":"string","maxLength":50},"type":"array","maxItems":20},{"type":"null"}],"title":"Tags","description":"Your own labels, for finding exercises; the AI and the search never read them"},"media":{"anyOf":[{"items":{"$ref":"#/components/schemas/MediaLink"},"type":"array","maxItems":10},{"type":"null"}],"title":"Media"},"hidden":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hidden"}},"additionalProperties":false,"type":"object","title":"ExercisePatch","description":"PATCH /v1/exercises/{exerciseRef}: only the fields sent change, e.g. {\"hidden\": true}.\n\nnull clears a text or a list; for measurement, perSide, requiresWeight and hidden it changes nothing."},"ExercisePut":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"What your members see; the AI reads it"},"equipment":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Equipment","description":"Equipment in your own words, e.g. 'Slider discs'. Empty for bodyweight. The AI reads it"},"measurement":{"type":"string","enum":["reps","time"],"title":"Measurement","description":"How plans measure it: reps, or time for holds and intervals such as a plank","default":"reps"},"perSide":{"type":"boolean","title":"Perside","description":"Sets are done on each side, e.g. a lunge; plans say so","default":false},"requiresWeight":{"type":"boolean","title":"Requiresweight","description":"Sets ask the member for the weight used","default":false},"notes":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Notes","description":"Your own notes; kept for you"},"instructions":{"items":{"type":"string","maxLength":300},"type":"array","maxItems":12,"title":"Instructions","description":"Steps shown to members, in order. Display only: the AI and the search never read them"},"safetyTips":{"items":{"type":"string","maxLength":300},"type":"array","maxItems":8,"title":"Safetytips","description":"Safety tips shown to members. Display only"},"commonMistakes":{"items":{"type":"string","maxLength":300},"type":"array","maxItems":8,"title":"Commonmistakes","description":"Common mistakes shown to members. Display only"},"tags":{"items":{"type":"string","maxLength":50},"type":"array","maxItems":20,"title":"Tags","description":"Your own labels, for finding exercises; the AI and the search never read them"},"media":{"items":{"$ref":"#/components/schemas/MediaLink"},"type":"array","maxItems":10,"title":"Media","description":"Links to your own media"},"hidden":{"type":"boolean","title":"Hidden","description":"Hidden exercises leave search and new plans; workouts that have one keep it","default":false}},"additionalProperties":false,"type":"object","required":["name"],"title":"ExercisePut","description":"PUT /v1/exercises/{exerciseRef}: the whole exercise; fields left out take their defaults."},"ExerciseRef":{"properties":{"exerciseId":{"type":"string","title":"Exerciseid"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"equipment":{"items":{"type":"string"},"type":"array","title":"Equipment"},"media":{"items":{"$ref":"#/components/schemas/ExerciseMedia"},"type":"array","title":"Media","description":"Your own links, for your exercises"},"library":{"anyOf":[{"$ref":"#/components/schemas/LibraryDetails"},{"type":"null"}],"description":"For an exercise from your library; null otherwise"}},"type":"object","required":["exerciseId"],"title":"ExerciseRef"},"FeatureEntry":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"quality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quality"},"limitPerMember":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limitpermember"},"limitPeriod":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Limitperiod"}},"type":"object","required":["enabled"],"title":"FeatureEntry"},"Features":{"properties":{"package":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package","description":"The package preset, if the partner is on one"},"env":{"type":"string","title":"Env"},"features":{"additionalProperties":{"$ref":"#/components/schemas/FeatureEntry"},"type":"object","title":"Features"}},"type":"object","required":["env","features"],"title":"Features"},"FeedbackItem":{"properties":{"exerciseId":{"type":"string","maxLength":64,"minLength":1,"title":"Exerciseid"},"words":{"type":"string","maxLength":1000,"minLength":1,"title":"Words","description":"Why it doesn't suit the member, in their words"},"workoutId":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Workoutid"}},"additionalProperties":false,"type":"object","required":["exerciseId","words"],"title":"FeedbackItem"},"GoogleIn":{"properties":{"idToken":{"type":"string","maxLength":8192,"title":"Idtoken","description":"The ID token Google sign-in gave your app"}},"additionalProperties":false,"type":"object","required":["idToken"],"title":"GoogleIn"},"HealthAnswerStatus":{"type":"string","enum":["NONE","PROVIDED","UNKNOWN"],"title":"HealthAnswerStatus","description":"Whether optional structured details are absent, provided, or unknown."},"HealthAnswers":{"properties":{"medicines":{"anyOf":[{"$ref":"#/components/schemas/Medicines"},{"type":"null"}]},"currentSupplements":{"anyOf":[{"$ref":"#/components/schemas/CurrentSupplements"},{"type":"null"}]},"pregnancyStatus":{"anyOf":[{"$ref":"#/components/schemas/PregnancyStatus"},{"type":"null"}]},"diagnosedDeficiencies":{"anyOf":[{"items":{"type":"string","maxLength":160,"minLength":1},"type":"array","maxItems":20},{"type":"null"}],"title":"Diagnoseddeficiencies"},"reviewed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Reviewed","description":"The member reviewed these answers just now"},"medicalDisclaimerAccepted":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Medicaldisclaimeraccepted"},"aiHealthDataConsentAccepted":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Aihealthdataconsentaccepted"}},"additionalProperties":false,"type":"object","title":"HealthAnswers","description":"What the assessment reads beyond the member's profile, kept with it. Fields sent replace the\nstored ones; the rest stay. The member accepted the disclaimer and the AI health-data consent in your app."},"Job":{"properties":{"id":{"type":"string","title":"Id"},"type":{"type":"string","title":"Type","description":"plan_options, plan, adjustment, regeneration, meal_plan, meal_idea, meal_photo, coach_reply or coach_change; a reader's: equipment_scan, body_scan_read, progress_photo_insight, blood_test_read or supplement_assessment"},"status":{"type":"string","title":"Status","description":"running, succeeded or failed"},"memberId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Memberid"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"},"finishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finishedat"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result","description":"Once succeeded; its shape follows the type"},"error":{"anyOf":[{"$ref":"#/components/schemas/JobError"},{"type":"null"}],"description":"Once failed"}},"type":"object","required":["id","type","status","createdAt"],"title":"Job"},"JobError":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"JobError"},"LibraryDetails":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the exercise"},"instructions":{"items":{"type":"string"},"type":"array","title":"Instructions"},"safetyTips":{"items":{"type":"string"},"type":"array","title":"Safetytips"},"commonMistakes":{"items":{"type":"string"},"type":"array","title":"Commonmistakes"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"}},"type":"object","required":["id"],"title":"LibraryDetails","description":"One of the partner's own exercises: what members are shown with it, from the library."},"LibraryExercise":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the exercise"},"budyId":{"type":"string","title":"Budyid","description":"Budy's ID for the exercise, as plans and workouts name it"},"name":{"type":"string","title":"Name"},"equipment":{"items":{"type":"string"},"type":"array","title":"Equipment"},"measurement":{"type":"string","enum":["reps","time"],"title":"Measurement"},"perSide":{"type":"boolean","title":"Perside"},"requiresWeight":{"type":"boolean","title":"Requiresweight"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"instructions":{"items":{"type":"string"},"type":"array","title":"Instructions"},"safetyTips":{"items":{"type":"string"},"type":"array","title":"Safetytips"},"commonMistakes":{"items":{"type":"string"},"type":"array","title":"Commonmistakes"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"media":{"items":{"$ref":"#/components/schemas/MediaLink"},"type":"array","title":"Media"},"hidden":{"type":"boolean","title":"Hidden"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["id","budyId","name","equipment","measurement","perSide","requiresWeight","instructions","safetyTips","commonMistakes","tags","media","hidden"],"title":"LibraryExercise"},"LibraryExerciseList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/LibraryExercise"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next","description":"Pass as cursor for the next page; null on the last"}},"type":"object","required":["data"],"title":"LibraryExerciseList"},"LibraryImport":{"properties":{"id":{"type":"string","title":"Id"},"env":{"type":"string","title":"Env"},"format":{"type":"string","title":"Format"},"mode":{"type":"string","title":"Mode"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"sizeBytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sizebytes"},"status":{"type":"string","enum":["receiving","checking","checked","applying","applied","failed","cancelled","expired"],"title":"Status"},"counts":{"anyOf":[{"$ref":"#/components/schemas/LibraryImportCounts"},{"type":"null"}],"description":"The check's outcomes"},"applied":{"anyOf":[{"$ref":"#/components/schemas/LibraryImportApplied"},{"type":"null"}],"description":"What apply did"},"errors":{"items":{"$ref":"#/components/schemas/LibraryImportRowError"},"type":"array","title":"Errors","description":"The first 50 row errors"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","description":"Columns or keys left out"},"error":{"anyOf":[{"$ref":"#/components/schemas/LibraryImportFailure"},{"type":"null"}],"description":"Why the whole import failed"},"createdBy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdby"},"createdByName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdbyname"},"createdByEmail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Createdbyemail"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"checkedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Checkedat"},"appliedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Appliedat"},"expiresAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expiresat"}},"type":"object","required":["id","env","format","mode","status"],"title":"LibraryImport"},"LibraryImportApplied":{"properties":{"created":{"type":"integer","title":"Created"},"updated":{"type":"integer","title":"Updated"},"unchanged":{"type":"integer","title":"Unchanged"},"skipped":{"type":"integer","title":"Skipped","description":"Rows that no longer passed the checks when applied"},"hidden":{"type":"integer","title":"Hidden"}},"type":"object","required":["created","updated","unchanged","skipped","hidden"],"title":"LibraryImportApplied"},"LibraryImportCounts":{"properties":{"rows":{"type":"integer","title":"Rows"},"create":{"type":"integer","title":"Create"},"update":{"type":"integer","title":"Update"},"unchanged":{"type":"integer","title":"Unchanged"},"hide":{"type":"integer","title":"Hide","description":"Shown exercises missing from the file, which mirror hides"},"error":{"type":"integer","title":"Error"}},"type":"object","required":["rows","create","update","unchanged","hide","error"],"title":"LibraryImportCounts"},"LibraryImportFailure":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"LibraryImportFailure"},"LibraryImportList":{"properties":{"env":{"type":"string","title":"Env"},"data":{"items":{"$ref":"#/components/schemas/LibraryImport"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next","description":"Pass as cursor for the next page; null on the last"}},"type":"object","required":["env","data"],"title":"LibraryImportList"},"LibraryImportRow":{"properties":{"row":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Row","description":"The spreadsheet row or the line; null for a hide"},"outcome":{"type":"string","enum":["create","update","unchanged","hide","error"],"title":"Outcome"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"changes":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Changes","description":"Updates only: {\"<field>\": {\"from\": \u2026, \"to\": \u2026}}"},"errors":{"items":{"$ref":"#/components/schemas/LibraryImportRowCellError"},"type":"array","title":"Errors"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result","description":"What apply did: created, updated, unchanged, skipped"}},"type":"object","required":["outcome"],"title":"LibraryImportRow"},"LibraryImportRowCellError":{"properties":{"column":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Column"},"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"LibraryImportRowCellError"},"LibraryImportRowError":{"properties":{"row":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Row","description":"As a spreadsheet numbers it (the header is 1), or the line"},"column":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Column"},"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"}},"type":"object","required":["code","message"],"title":"LibraryImportRowError"},"LibraryImportRows":{"properties":{"data":{"items":{"$ref":"#/components/schemas/LibraryImportRow"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next"}},"type":"object","required":["data"],"title":"LibraryImportRows"},"LibraryImportStart":{"properties":{"format":{"type":"string","enum":["csv","ndjson"],"title":"Format"},"mode":{"type":"string","enum":["upsert","create_only","mirror"],"title":"Mode","description":"upsert adds and changes; create_only only adds; mirror also hides what the file leaves out","default":"upsert"},"filename":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Filename","description":"Shown with the import"},"sizeBytes":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Sizebytes","description":"The file's size, to refuse one too big early"}},"additionalProperties":false,"type":"object","required":["format"],"title":"LibraryImportStart","description":"POST \u2026/imports: a new import, receiving its file (PUT \u2026/imports/{importId}/source)."},"LoggedSetIn":{"properties":{"exerciseId":{"type":"string","maxLength":64,"minLength":1,"title":"Exerciseid","description":"The exercise done (a swap's, if swapped)"},"setNumber":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Setnumber"},"reps":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":0.0},{"type":"null"}],"title":"Reps"},"weightKg":{"anyOf":[{"type":"number","maximum":1000.0,"minimum":0.0},{"type":"null"}],"title":"Weightkg"},"durationSeconds":{"anyOf":[{"type":"integer","maximum":21600.0,"minimum":0.0},{"type":"null"}],"title":"Durationseconds"},"distanceMeters":{"anyOf":[{"type":"number","maximum":1000000.0,"minimum":0.0},{"type":"null"}],"title":"Distancemeters"},"rpe":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Rpe"},"restSeconds":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":0.0},{"type":"null"}],"title":"Restseconds"},"completed":{"type":"boolean","title":"Completed","default":true},"skipped":{"type":"boolean","title":"Skipped","default":false},"notes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Notes"}},"additionalProperties":false,"type":"object","required":["exerciseId","setNumber"],"title":"LoggedSetIn"},"LoggedSetOut":{"properties":{"exerciseId":{"type":"string","title":"Exerciseid"},"setNumber":{"type":"integer","title":"Setnumber"},"reps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reps"},"weightKg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weightkg"},"durationSeconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Durationseconds"},"distanceMeters":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distancemeters"},"rpe":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rpe"},"completed":{"type":"boolean","title":"Completed"},"skipped":{"type":"boolean","title":"Skipped"}},"type":"object","required":["exerciseId","setNumber","completed","skipped"],"title":"LoggedSetOut"},"Meal":{"properties":{"mealId":{"type":"string","title":"Mealid"},"slot":{"type":"string","title":"Slot","description":"BREAKFAST, MORNING_SNACK, LUNCH, AFTERNOON_SNACK, DINNER, EVENING_SNACK, PRE_WORKOUT or POST_WORKOUT"},"time":{"type":"string","title":"Time","description":"When to eat it, HH:MM in the plan's time zone"},"servings":{"type":"number","title":"Servings"},"why":{"type":"string","title":"Why"},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"recipe":{"$ref":"#/components/schemas/Recipe"},"alternatives":{"items":{"$ref":"#/components/schemas/MealAlternative"},"type":"array","title":"Alternatives","description":"Up to two, each safe for the member and within the day's calories"}},"type":"object","required":["mealId","slot","time","servings","why","nutrition","recipe"],"title":"Meal"},"MealAlternative":{"properties":{"servings":{"type":"number","title":"Servings"},"why":{"type":"string","title":"Why"},"nutrition":{"$ref":"#/components/schemas/Nutrition"},"recipe":{"$ref":"#/components/schemas/Recipe"}},"type":"object","required":["servings","why","nutrition","recipe"],"title":"MealAlternative"},"MealIdeaRequest":{"properties":{"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"guidance":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Guidance","description":"What the member fancies, in their words"},"notRecipeIds":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Notrecipeids","description":"Recipes the member doesn't want this time"}},"additionalProperties":false,"type":"object","title":"MealIdeaRequest","description":"POST /v1/members/{memberId}/meal-ideas: what to eat next."},"MealPlan":{"properties":{"mealPlanId":{"type":"string","title":"Mealplanid"},"date":{"type":"string","title":"Date","description":"The member's local day, YYYY-MM-DD"},"timeZone":{"type":"string","title":"Timezone"},"targets":{"$ref":"#/components/schemas/Nutrition"},"totals":{"$ref":"#/components/schemas/Nutrition"},"meals":{"items":{"$ref":"#/components/schemas/Meal"},"type":"array","title":"Meals"}},"type":"object","required":["mealPlanId","date","timeZone","targets","totals","meals"],"title":"MealPlan"},"MealPlanRequest":{"properties":{"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"guidance":{"anyOf":[{"type":"string","maxLength":500,"minLength":1},{"type":"null"}],"title":"Guidance","description":"What the member wants today, in their words (eating out tonight, high protein)"}},"additionalProperties":false,"type":"object","title":"MealPlanRequest","description":"POST /v1/members/{memberId}/meal-plans: today's meal plan, in the member's time zone."},"MediaAborted":{"properties":{"aborted":{"type":"boolean","title":"Aborted"}},"type":"object","required":["aborted"],"title":"MediaAborted"},"MediaAsset":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","enum":["video","image"],"title":"Kind"},"status":{"type":"string","enum":["uploading","processing","ready","failed","deleted"],"title":"Status"},"filename":{"type":"string","title":"Filename"},"contentType":{"type":"string","title":"Contenttype"},"sizeBytes":{"type":"integer","title":"Sizebytes","description":"The upload's size"},"storedBytes":{"type":"integer","title":"Storedbytes","description":"What it takes of your storage: the upload plus its versions"},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Durationseconds"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Ready only: the 720p video or the 1280 px picture, signed"},"posterUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Posterurl","description":"Ready only: the poster, or the 640 px picture"},"variants":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Variants","description":"Ready only: every version, signed: 720p, 480p and poster, or 1280, 640 and 320"},"urlsExpireAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Urlsexpireat","description":"The links work until then (12 hours or more)"},"usedBy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Usedby","description":"How many exercises use it, in both envs"},"error":{"anyOf":[{"$ref":"#/components/schemas/MediaAssetError"},{"type":"null"}]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["id","kind","status","filename","contentType","sizeBytes","storedBytes"],"title":"MediaAsset"},"MediaAssetError":{"properties":{"code":{"type":"string","title":"Code","description":"not_media, unreadable, no_video, too_long, frame_too_large, too_many_pixels, upload_expired or processing_failed"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"MediaAssetError"},"MediaComplete":{"properties":{"parts":{"items":{"$ref":"#/components/schemas/MediaPartTag"},"type":"array","maxItems":10000,"minItems":1,"title":"Parts"}},"additionalProperties":false,"type":"object","required":["parts"],"title":"MediaComplete","description":"POST /media/{assetId}/complete: every part, with the ETag its PUT answered."},"MediaLink":{"properties":{"assetId":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Assetid","description":"An upload's ID (POST /v1/media/uploads), in place of url"},"url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Url","description":"A public https link to your own video or image; for an upload, the signed link reads give"},"posterUrl":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Posterurl","description":"Read only: an upload's poster"},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Durationseconds","description":"Read only: an uploaded video's length"},"width":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Width","description":"Read only"},"height":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Height","description":"Read only"},"status":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Status","description":"Read only: an upload's status (processing, ready, failed, deleted)"},"type":{"type":"string","enum":["video","image","other"],"title":"Type","default":"video"},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title"}},"additionalProperties":false,"type":"object","title":"MediaLink","description":"A media item: a link to your own media (url), or media you uploaded to Budy (assetId).\n\nReads of an uploaded item add a signed url and posterUrl, good for at least 12 hours, with\ndurationSeconds, width, height and status. Those are read only: sent back, they're ignored."},"MediaList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/MediaAsset"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next","description":"Pass as cursor for the next page; null on the last"}},"type":"object","required":["data"],"title":"MediaList"},"MediaPartLink":{"properties":{"number":{"type":"integer","title":"Number"},"url":{"type":"string","title":"Url","description":"PUT the part's bytes here, and keep the ETag header of the answer"}},"type":"object","required":["number","url"],"title":"MediaPartLink"},"MediaPartNumbers":{"properties":{"numbers":{"items":{"type":"integer"},"type":"array","maxItems":10000,"minItems":1,"title":"Numbers"}},"additionalProperties":false,"type":"object","required":["numbers"],"title":"MediaPartNumbers","description":"POST /media/{assetId}/parts: parts to sign again, after their links expired."},"MediaPartTag":{"properties":{"number":{"type":"integer","maximum":10000.0,"minimum":1.0,"title":"Number"},"etag":{"type":"string","maxLength":200,"minLength":1,"title":"Etag","description":"The ETag header S3 answered the part's PUT with"}},"additionalProperties":false,"type":"object","required":["number","etag"],"title":"MediaPartTag"},"MediaParts":{"properties":{"parts":{"items":{"$ref":"#/components/schemas/MediaPartLink"},"type":"array","title":"Parts"},"expiresAt":{"type":"string","format":"date-time","title":"Expiresat"}},"type":"object","required":["parts","expiresAt"],"title":"MediaParts"},"MediaTitle":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title","description":"null or empty clears it"}},"additionalProperties":false,"type":"object","title":"MediaTitle"},"MediaUpload":{"properties":{"uploadId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Uploadid"},"partSize":{"type":"integer","title":"Partsize","description":"Every part but the last is exactly this size (8 MiB)"},"parts":{"items":{"$ref":"#/components/schemas/MediaPartLink"},"type":"array","title":"Parts"},"expiresAt":{"type":"string","format":"date-time","title":"Expiresat"}},"type":"object","required":["partSize","parts","expiresAt"],"title":"MediaUpload"},"MediaUploadStart":{"properties":{"filename":{"type":"string","maxLength":1024,"minLength":1,"title":"Filename","description":"Kept to its last 255 characters"},"contentType":{"type":"string","maxLength":100,"minLength":1,"title":"Contenttype","description":"video/mp4, video/quicktime or video/webm (up to 500 MB, 3 minutes and 4K); image/jpeg, image/png, image/webp or image/heic (up to 20 MB)"},"sizeBytes":{"type":"integer","minimum":1.0,"title":"Sizebytes","description":"The file's exact size; the parts must add up to it"},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title"}},"additionalProperties":false,"type":"object","required":["filename","contentType","sizeBytes"],"title":"MediaUploadStart","description":"POST /media/uploads: the file to come, as the browser or your server knows it."},"MediaUploadStarted":{"properties":{"asset":{"$ref":"#/components/schemas/MediaAsset"},"upload":{"$ref":"#/components/schemas/MediaUpload"}},"type":"object","required":["asset","upload"],"title":"MediaUploadStarted"},"MediaUsage":{"properties":{"bytes":{"type":"integer","title":"Bytes","description":"Everything stored for you, deleted media's files too until they're purged; uploads in progress at their size"},"deletedBytes":{"type":"integer","title":"Deletedbytes","description":"Of bytes, deleted media's files, waiting for the purge"},"quotaBytes":{"type":"integer","title":"Quotabytes","description":"Storage included in your plan"},"assets":{"type":"integer","title":"Assets"},"overage":{"type":"boolean","title":"Overage","description":"Whether uploads may go past quotaBytes, billed at cost"},"purgeDays":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Purgedays","description":"Deleted media's files go this many days after the delete; null: not scheduled yet"}},"type":"object","required":["bytes","deletedBytes","quotaBytes","assets","overage"],"title":"MediaUsage"},"MedicationDetail":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"dose":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Dose"},"frequency":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Frequency"},"reason":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","required":["name"],"title":"MedicationDetail"},"Medicines":{"properties":{"status":{"$ref":"#/components/schemas/HealthAnswerStatus","description":"NONE, PROVIDED or UNKNOWN"},"details":{"anyOf":[{"items":{"$ref":"#/components/schemas/MedicationDetail"},"type":"array","maxItems":30},{"type":"null"}],"title":"Details"}},"additionalProperties":false,"type":"object","required":["status"],"title":"Medicines"},"Member":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the member"},"budyId":{"type":"string","title":"Budyid","description":"Budy's ID for the member, the member token's sub"},"env":{"type":"string","title":"Env","description":"live or test, from the key"},"active":{"type":"boolean","title":"Active"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier","description":"The member tier they're on; null: your default tier"},"features":{"items":{"type":"string"},"type":"array","title":"Features","description":"The features the member can use (their tier's)"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["id","budyId","env","active","features"],"title":"Member"},"MemberList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Member"},"type":"array","title":"Data"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next","description":"Pass as cursor for the next page; null on the last"}},"type":"object","required":["data"],"title":"MemberList"},"MemberProfile":{"properties":{"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"experience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Experience","description":"beginner, novice, intermediate, advanced or expert"},"days":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":7,"minItems":1},{"type":"null"}],"title":"Days","description":"Training days, MON to SUN"},"daysPerWeek":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":1.0},{"type":"null"}],"title":"Daysperweek","description":"When the member hasn't picked days"},"minutesPerSession":{"anyOf":[{"type":"integer","maximum":180.0,"minimum":15.0},{"type":"null"}],"title":"Minutespersession"},"places":{"anyOf":[{"items":{"$ref":"#/components/schemas/Place"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Places","description":"One or two"}},"additionalProperties":false,"type":"object","title":"MemberProfile","description":"What the plan is built from. Every field is optional on its own; a plan needs goal, days, places and body data.\n\nFood preferences aren't kept here: they're Budy's own nutrition preferences (nutrition_schemas.py)."},"MemberPut":{"properties":{"currentLocation":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Currentlocation"},"birthLocation":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Birthlocation"},"dietType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Diettype","description":"vegetarian, vegan, pescatarian, etc."},"spiceLevel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Spicelevel","description":"mild, medium, hot, extra_hot"},"crossCulturalWillingness":{"type":"boolean","title":"Crossculturalwillingness","description":"Willing to try cuisines from other cultures","default":true},"cuisinePreferences":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Cuisinepreferences"},"allergens":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allergens"},"dietaryRestrictions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Dietaryrestrictions"},"specificIngredientsInclude":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specificingredientsinclude"},"specificIngredientsExclude":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specificingredientsexclude"},"mealTimingPreferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Mealtimingpreferences"},"nutritionCoachingPreferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Nutritioncoachingpreferences"},"dailyCalories":{"anyOf":[{"type":"integer","maximum":15000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Dailycalories","description":"Your own daily calorie target for meal plans; send proteinGrams with it"},"proteinGrams":{"anyOf":[{"type":"integer","maximum":2000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Proteingrams","description":"Your own daily protein target"},"carbGrams":{"anyOf":[{"type":"integer","maximum":3000.0,"minimum":0.0},{"type":"null"}],"title":"Carbgrams","description":"Your own daily carbohydrate target"},"fatGrams":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":0.0},{"type":"null"}],"title":"Fatgrams","description":"Your own daily fat target"},"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"experience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Experience","description":"beginner, novice, intermediate, advanced or expert"},"days":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":7,"minItems":1},{"type":"null"}],"title":"Days","description":"Training days, MON to SUN"},"daysPerWeek":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":1.0},{"type":"null"}],"title":"Daysperweek","description":"When the member hasn't picked days"},"minutesPerSession":{"anyOf":[{"type":"integer","maximum":180.0,"minimum":15.0},{"type":"null"}],"title":"Minutespersession"},"places":{"anyOf":[{"items":{"$ref":"#/components/schemas/Place"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Places","description":"One or two"},"active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Active","description":"Whether the member may use Budy's features. New members are active unless this says false."},"tier":{"anyOf":[{"type":"string","maxLength":40,"minLength":1},{"type":"null"}],"title":"Tier","description":"The key of one of your member tiers (made in your console), whose features and limits the member gets; null puts them on your default tier, everything your plan has. Not sent: unchanged."}},"additionalProperties":false,"type":"object","title":"MemberPut","description":"PUT /v1/members/{memberId}: everything about a member in one call, all optional: whether they're active,\ntheir tier, what they eat (the same fields and the same place as PUT \u2026/nutrition-preferences) and their profile (workout_schemas.py).\n\nProfile fields sent replace the stored ones (null clears one); fields not\nsent stay as they were."},"MemberQuota":{"properties":{"workoutUpdates":{"anyOf":[{"$ref":"#/components/schemas/QuotaEntry"},{"type":"null"}]},"mealPlans":{"anyOf":[{"$ref":"#/components/schemas/QuotaEntry"},{"type":"null"}]},"mealPhotos":{"anyOf":[{"$ref":"#/components/schemas/QuotaEntry"},{"type":"null"}]},"equipmentScan":{"anyOf":[{"$ref":"#/components/schemas/QuotaEntry"},{"type":"null"}],"description":"Photos today (UTC)"},"bodyScans":{"anyOf":[{"$ref":"#/components/schemas/QuotaEntry"},{"type":"null"}],"description":"InBody sheet reads this month"},"supplements":{"anyOf":[{"$ref":"#/components/schemas/QuotaEntry"},{"type":"null"}],"description":"Blood test reads this month"}},"type":"object","title":"MemberQuota"},"MemberTokenOut":{"properties":{"token":{"type":"string","title":"Token"},"tokenType":{"type":"string","title":"Tokentype","default":"Bearer"},"expiresAt":{"type":"string","format":"date-time","title":"Expiresat"},"expiresIn":{"type":"integer","title":"Expiresin","description":"Seconds until the token expires"},"memberId":{"type":"string","title":"Memberid"}},"type":"object","required":["token","expiresAt","expiresIn","memberId"],"title":"MemberTokenOut"},"MemberVoice":{"properties":{"voiceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voiceid"},"voiceName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voicename"},"enabled":{"type":"boolean","title":"Enabled"},"changes":{"$ref":"#/components/schemas/VoiceChanges"}},"type":"object","required":["enabled","changes"],"title":"MemberVoice"},"MemberVoicePut":{"properties":{"voiceId":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voiceid","description":"A voiceId from GET /v1/voices"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled","description":"false: the member's workouts don't speak"}},"additionalProperties":false,"type":"object","title":"MemberVoicePut"},"MemberWithQuota":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the member"},"budyId":{"type":"string","title":"Budyid","description":"Budy's ID for the member, the member token's sub"},"env":{"type":"string","title":"Env","description":"live or test, from the key"},"active":{"type":"boolean","title":"Active"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier","description":"The member tier they're on; null: your default tier"},"features":{"items":{"type":"string"},"type":"array","title":"Features","description":"The features the member can use (their tier's)"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"},"quota":{"$ref":"#/components/schemas/MemberQuota"},"profile":{"anyOf":[{"$ref":"#/components/schemas/MemberProfile"},{"type":"null"}],"description":"What the plan is built from, as sent"}},"type":"object","required":["id","budyId","env","active","features","quota"],"title":"MemberWithQuota"},"NotificationIn":{"properties":{"members":{"items":{"type":"string"},"type":"array","maxItems":500,"minItems":1,"title":"Members","description":"Your member IDs, up to 500"},"channels":{"items":{"type":"string","enum":["push","email"]},"type":"array","maxItems":2,"minItems":1,"title":"Channels"},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title","description":"The push title or email subject"},"body":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Body"},"template":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Template","description":"Instead of title and body: one of your templates, like custom.welcome"},"variables":{"additionalProperties":{"type":"string"},"type":"object","title":"Variables","description":"{name} values for the words, 20 at most"},"data":{"additionalProperties":{"type":"string"},"type":"object","title":"Data","description":"Sent with the push for your app, 4 KB at most"},"collapseKey":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Collapsekey","description":"A newer push with the same key replaces it"}},"additionalProperties":false,"type":"object","required":["members"],"title":"NotificationIn"},"NotificationOut":{"properties":{"id":{"type":"string","title":"Id"},"deliveries":{"additionalProperties":{"additionalProperties":{"type":"integer"},"type":"object"},"type":"object","title":"Deliveries","description":"Counts by channel, then status"}},"type":"object","required":["id","deliveries"],"title":"NotificationOut"},"NotificationQueuedOut":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"The notification's ID: GET /v1/notifications/{id} says how it went"},"queued":{"type":"integer","title":"Queued","description":"Deliveries queued: members found times channels"},"unknownMembers":{"items":{"type":"string"},"type":"array","title":"Unknownmembers","description":"Member IDs that aren't yours"}},"type":"object","required":["id","queued"],"title":"NotificationQueuedOut"},"Nutrition":{"properties":{"calories":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Calories"},"proteinGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Proteingrams"},"carbGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Carbgrams"},"fatGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fatgrams"}},"type":"object","title":"Nutrition"},"NutritionPreferences":{"properties":{"currentLocation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currentlocation"},"birthLocation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Birthlocation"},"dietType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Diettype"},"spiceLevel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Spicelevel"},"crossCulturalWillingness":{"type":"boolean","title":"Crossculturalwillingness","default":true},"cuisinePreferences":{"items":{"type":"string"},"type":"array","title":"Cuisinepreferences"},"allergens":{"items":{"type":"string"},"type":"array","title":"Allergens"},"dietaryRestrictions":{"items":{"type":"string"},"type":"array","title":"Dietaryrestrictions"},"specificIngredientsInclude":{"items":{"type":"string"},"type":"array","title":"Specificingredientsinclude"},"specificIngredientsExclude":{"items":{"type":"string"},"type":"array","title":"Specificingredientsexclude"},"mealTimingPreferences":{"additionalProperties":true,"type":"object","title":"Mealtimingpreferences"},"nutritionCoachingPreferences":{"additionalProperties":true,"type":"object","title":"Nutritioncoachingpreferences"},"dailyCalories":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dailycalories"},"proteinGrams":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Proteingrams"},"carbGrams":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Carbgrams"},"fatGrams":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fatgrams"}},"type":"object","title":"NutritionPreferences","description":"The member's food preferences, as Budy's app reads them, with your own daily targets."},"NutritionPreferencesPut":{"properties":{"currentLocation":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Currentlocation"},"birthLocation":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Birthlocation"},"dietType":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Diettype","description":"vegetarian, vegan, pescatarian, etc."},"spiceLevel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Spicelevel","description":"mild, medium, hot, extra_hot"},"crossCulturalWillingness":{"type":"boolean","title":"Crossculturalwillingness","description":"Willing to try cuisines from other cultures","default":true},"cuisinePreferences":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Cuisinepreferences"},"allergens":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allergens"},"dietaryRestrictions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Dietaryrestrictions"},"specificIngredientsInclude":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specificingredientsinclude"},"specificIngredientsExclude":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specificingredientsexclude"},"mealTimingPreferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Mealtimingpreferences"},"nutritionCoachingPreferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Nutritioncoachingpreferences"},"dailyCalories":{"anyOf":[{"type":"integer","maximum":15000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Dailycalories","description":"Your own daily calorie target for meal plans; send proteinGrams with it"},"proteinGrams":{"anyOf":[{"type":"integer","maximum":2000.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Proteingrams","description":"Your own daily protein target"},"carbGrams":{"anyOf":[{"type":"integer","maximum":3000.0,"minimum":0.0},{"type":"null"}],"title":"Carbgrams","description":"Your own daily carbohydrate target"},"fatGrams":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":0.0},{"type":"null"}],"title":"Fatgrams","description":"Your own daily fat target"}},"additionalProperties":false,"type":"object","title":"NutritionPreferencesPut","description":"PUT /v1/members/{memberId}/nutrition-preferences: what the member eats, as Budy's app asks it.\n\nFields sent replace the stored ones (null clears one); fields not sent stay as they were."},"PartnerVoice":{"properties":{"id":{"type":"string","title":"Id","description":"Your ID for the voice"},"voiceId":{"type":"string","title":"Voiceid","description":"What a member's voiceId is set to"},"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status","description":"waiting (no recording yet), processing, ready or failed"},"failureReason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failurereason","description":"too_short, too_quiet or server_error"},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Durationseconds"},"previewUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Previewurl","description":"A short line in the voice, for an hour (ready voices)"},"consent":{"$ref":"#/components/schemas/ConsentRecord"},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Createdat"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["id","voiceId","name","status","consent"],"title":"PartnerVoice"},"PasswordResetIn":{"properties":{"email":{"type":"string","maxLength":320,"title":"Email","description":"The member's email"},"code":{"type":"string","pattern":"^\\d{6}$","title":"Code","description":"The 6-digit code from the email"},"newPassword":{"type":"string","maxLength":128,"minLength":8,"title":"Newpassword"}},"additionalProperties":false,"type":"object","required":["email","code","newPassword"],"title":"PasswordResetIn"},"Place":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name","description":"The member's name for it, e.g. Home"},"kind":{"type":"string","enum":["home","gym","outdoor"],"title":"Kind"},"equipment":{"items":{"type":"string"},"type":"array","maxItems":100,"title":"Equipment","description":"What is there, as the member says it (Dumbbells 2-10 kg, Mat). A chair, a doorway, stairs and a table always count at home."}},"additionalProperties":false,"type":"object","required":["name","kind"],"title":"Place","description":"Somewhere the member trains, with the equipment there in the member's own words."},"Plan":{"properties":{"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"weeks":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weeks"},"currentWeek":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Currentweek"},"startDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Startdate"},"endDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enddate"},"phases":{"items":{"$ref":"#/components/schemas/PlanPhase"},"type":"array","title":"Phases"},"schedule":{"items":{"$ref":"#/components/schemas/PlanWeek"},"type":"array","title":"Schedule","description":"The weeks built so far"},"coaching":{"anyOf":[{"$ref":"#/components/schemas/PlanCoaching"},{"type":"null"}],"description":"Which of your coaching text shaped the plan"},"nutrition":{"anyOf":[{"$ref":"#/components/schemas/PlanNutrition"},{"type":"null"}],"description":"Daily calorie and macro targets, with mealPlans"}},"type":"object","required":["id","status","phases","schedule"],"title":"Plan"},"PlanCoaching":{"properties":{"rulesVersion":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rulesversion","description":"The version of your coaching rules the latest phase build or edit read; null if unknown"},"profileVersion":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Profileversion","description":"Your coaching profile's, once there is one"}},"type":"object","title":"PlanCoaching"},"PlanNutrition":{"properties":{"dailyCalories":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dailycalories"},"proteinGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Proteingrams"},"carbGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Carbgrams"},"fatGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fatgrams"}},"type":"object","title":"PlanNutrition","description":"The plan's daily targets, from the option the member picked."},"PlanOptionsRequest":{"properties":{"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"experience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Experience","description":"beginner, novice, intermediate, advanced or expert"},"days":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":7,"minItems":1},{"type":"null"}],"title":"Days","description":"Training days, MON to SUN"},"daysPerWeek":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":1.0},{"type":"null"}],"title":"Daysperweek","description":"When the member hasn't picked days"},"minutesPerSession":{"anyOf":[{"type":"integer","maximum":180.0,"minimum":15.0},{"type":"null"}],"title":"Minutespersession"},"places":{"anyOf":[{"items":{"$ref":"#/components/schemas/Place"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Places","description":"One or two"}},"additionalProperties":false,"type":"object","title":"PlanOptionsRequest","description":"POST \u2026/plan-options: optional changes to the member's profile, saved, then used."},"PlanPhase":{"properties":{"number":{"type":"integer","title":"Number"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"focus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Focus"},"startWeek":{"type":"integer","title":"Startweek"},"endWeek":{"type":"integer","title":"Endweek"},"status":{"type":"string","title":"Status","description":"ready, building, waiting or failed"}},"type":"object","required":["number","startWeek","endWeek","status"],"title":"PlanPhase"},"PlanRequest":{"properties":{"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"experience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Experience","description":"beginner, novice, intermediate, advanced or expert"},"days":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":7,"minItems":1},{"type":"null"}],"title":"Days","description":"Training days, MON to SUN"},"daysPerWeek":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":1.0},{"type":"null"}],"title":"Daysperweek","description":"When the member hasn't picked days"},"minutesPerSession":{"anyOf":[{"type":"integer","maximum":180.0,"minimum":15.0},{"type":"null"}],"title":"Minutespersession"},"places":{"anyOf":[{"items":{"$ref":"#/components/schemas/Place"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Places","description":"One or two"},"option":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Option","description":"AGGRESSIVE, BALANCED or RELAXED; BALANCED if you don't name one"}},"additionalProperties":false,"type":"object","title":"PlanRequest","description":"POST \u2026/plans: the member's plan. Who they are and how they train can come with it, saved first.\n\nWith no plan options to build from, or no option named, Budy makes them first and builds one by itself."},"PlanWeek":{"properties":{"week":{"type":"integer","title":"Week"},"workouts":{"items":{"$ref":"#/components/schemas/WorkoutSummary"},"type":"array","title":"Workouts"}},"type":"object","required":["week","workouts"],"title":"PlanWeek"},"PlannedSetOut":{"properties":{"setNumber":{"type":"integer","title":"Setnumber"},"reps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reps"},"repRangeMin":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reprangemin"},"repRangeMax":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reprangemax"},"weightKg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weightkg"},"durationSeconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Durationseconds"},"distanceMeters":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distancemeters"},"restSeconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Restseconds"},"perSide":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Perside"},"tempo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tempo"},"intensity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Intensity"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["setNumber"],"title":"PlannedSetOut"},"PregnancyStatus":{"type":"string","enum":["NOT_APPLICABLE","NOT_PREGNANT","TRYING_TO_CONCEIVE","PREGNANT","BREASTFEEDING","UNKNOWN"],"title":"PregnancyStatus"},"PresetVoice":{"properties":{"voiceId":{"type":"string","title":"Voiceid"},"name":{"type":"string","title":"Name"},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"previewUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Previewurl"}},"type":"object","required":["voiceId","name"],"title":"PresetVoice"},"ProgressPhotoIn":{"properties":{"angle":{"type":"string","enum":["FRONT","SIDE_LEFT","SIDE_RIGHT","BACK"],"title":"Angle"},"assetId":{"type":"string","maxLength":40,"minLength":1,"title":"Assetid","description":"One of your uploads (POST /v1/media/uploads), a picture"}},"additionalProperties":false,"type":"object","required":["angle","assetId"],"title":"ProgressPhotoIn"},"ProgressPhotoInsightRequest":{"properties":{"photos":{"items":{"$ref":"#/components/schemas/ProgressPhotoIn"},"type":"array","maxItems":4,"minItems":1,"title":"Photos"}},"additionalProperties":false,"type":"object","required":["photos"],"title":"ProgressPhotoInsightRequest"},"QuotaEntry":{"properties":{"used":{"type":"integer","title":"Used"},"limit":{"type":"integer","title":"Limit"},"remaining":{"type":"integer","title":"Remaining"},"resetsAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resetsat"}},"type":"object","required":["used","limit","remaining"],"title":"QuotaEntry"},"Recipe":{"properties":{"recipeId":{"type":"string","title":"Recipeid"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"servings":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Servings"},"servingSize":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Servingsize"},"prepMinutes":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prepminutes"},"nutritionPerServing":{"$ref":"#/components/schemas/RecipeNutrition"},"ingredients":{"items":{"type":"string"},"type":"array","title":"Ingredients"},"steps":{"items":{"type":"string"},"type":"array","title":"Steps"},"imageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Imageurl","description":"Signed; expires within hours: read the plan or the job again"},"largeImageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Largeimageurl"}},"type":"object","required":["recipeId","nutritionPerServing"],"title":"Recipe"},"RecipeNutrition":{"properties":{"calories":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Calories"},"proteinGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Proteingrams"},"carbGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Carbgrams"},"fatGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fatgrams"},"fiberGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Fibergrams"},"sugarGrams":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sugargrams"},"sodiumMg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Sodiummg"}},"type":"object","title":"RecipeNutrition"},"RefreshIn":{"properties":{"refreshToken":{"type":"string","maxLength":200,"title":"Refreshtoken"}},"additionalProperties":false,"type":"object","required":["refreshToken"],"title":"RefreshIn"},"RegenerationRequest":{"properties":{"goal":{"anyOf":[{"type":"string","maxLength":160,"minLength":1},{"type":"null"}],"title":"Goal","description":"In the member's words"},"sex":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Sex"},"birthYear":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1900.0},{"type":"null"}],"title":"Birthyear"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Birthdate"},"heightCm":{"anyOf":[{"type":"number","maximum":300.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Heightcm"},"weightKg":{"anyOf":[{"type":"number","maximum":700.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Weightkg"},"limits":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Limits","description":"Health limits and injuries, in their words"},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Notes","description":"Anything else the member said"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language","description":"e.g. en, es-ES"},"units":{"anyOf":[{"type":"string","enum":["metric","imperial"]},{"type":"null"}],"title":"Units"},"timeZone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone","description":"IANA, e.g. Europe/Madrid"},"experience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Experience","description":"beginner, novice, intermediate, advanced or expert"},"days":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":7,"minItems":1},{"type":"null"}],"title":"Days","description":"Training days, MON to SUN"},"daysPerWeek":{"anyOf":[{"type":"integer","maximum":7.0,"minimum":1.0},{"type":"null"}],"title":"Daysperweek","description":"When the member hasn't picked days"},"minutesPerSession":{"anyOf":[{"type":"integer","maximum":180.0,"minimum":15.0},{"type":"null"}],"title":"Minutespersession"},"places":{"anyOf":[{"items":{"$ref":"#/components/schemas/Place"},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Places","description":"One or two"},"phase":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Phase","description":"The phase to rebuild; the current one if you don't name one"},"difficulty":{"anyOf":[{"type":"string","enum":["harder","easier"]},{"type":"null"}],"title":"Difficulty","description":"Which way to take it, this once"},"words":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Words","description":"What the member wants changed, in their words"},"exerciseIds":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Exerciseids","description":"The exerciseIds, from their workouts, of exercises that don't suit them"},"calibrationContext":{"anyOf":[{"type":"string","maxLength":2400},{"type":"null"}],"title":"Calibrationcontext","description":"How the member's recent workouts really went, for this rebuild only"}},"additionalProperties":false,"type":"object","title":"RegenerationRequest","description":"POST \u2026/regenerations: rebuild the unfinished workouts of a phase (one workout update).\n\nAll optional. The member's details can come with it, saved first; the rebuild reads them as they are now."},"ScanPlace":{"properties":{"kind":{"anyOf":[{"type":"string","enum":["home","gym","outdoor"]},{"type":"null"}],"title":"Kind"},"name":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Name","description":"The member's name for it, e.g. Hotel"}},"additionalProperties":false,"type":"object","title":"ScanPlace","description":"Where the photo was taken: a hint for the AI, never a reason to say no."},"SessionOut":{"properties":{"token":{"type":"string","title":"Token","description":"The member token: Authorization: Bearer \u2026 on the member's calls"},"tokenType":{"type":"string","title":"Tokentype","default":"Bearer"},"expiresAt":{"type":"string","format":"date-time","title":"Expiresat"},"expiresIn":{"type":"integer","title":"Expiresin","description":"Seconds until the member token expires"},"refreshToken":{"type":"string","title":"Refreshtoken","description":"Gets the next member token; replaced each time it is used"},"refreshExpiresAt":{"type":"string","format":"date-time","title":"Refreshexpiresat","description":"When the session ends if it isn't used"},"sessionId":{"type":"string","title":"Sessionid"},"memberId":{"type":"string","title":"Memberid","description":"The member's ID, for your server and the console"},"newMember":{"type":"boolean","title":"Newmember","description":"This sign-in made the account","default":false}},"type":"object","required":["token","expiresAt","expiresIn","refreshToken","refreshExpiresAt","sessionId","memberId"],"title":"SessionOut"},"SheetReadRequest":{"properties":{"pages":{"items":{"type":"string"},"type":"array","maxItems":4,"minItems":1,"title":"Pages","description":"Your uploads, page 1 first"},"timeZone":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Timezone","description":"The member's IANA zone: the calendar the month's limits count in (else the member's timeZone, else UTC)"}},"additionalProperties":false,"type":"object","required":["pages"],"title":"SheetReadRequest","description":"1 to 4 pages of one sheet or report, as pictures (a PDF's pages as pictures)."},"SignInIn":{"properties":{"email":{"type":"string","maxLength":320,"title":"Email","description":"The member's email"},"password":{"type":"string","maxLength":128,"title":"Password"}},"additionalProperties":false,"type":"object","required":["email","password"],"title":"SignInIn"},"SignOutIn":{"properties":{"refreshToken":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Refreshtoken","description":"With your app's publishable key: the session to sign out"},"everywhere":{"type":"boolean","title":"Everywhere","description":"Sign out every phone and end every member token","default":false}},"additionalProperties":false,"type":"object","title":"SignOutIn"},"SignUpIn":{"properties":{"email":{"type":"string","maxLength":320,"title":"Email","description":"The member's email"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"},"name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Name","description":"The member's name, as they'd like to be called"}},"additionalProperties":false,"type":"object","required":["email","password"],"title":"SignUpIn"},"SkipWorkoutRequest":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","title":"SkipWorkoutRequest"},"SupplementAssessment":{"properties":{"id":{"type":"string","title":"Id"},"status":{"type":"string","title":"Status"},"periodStart":{"type":"string","format":"date","title":"Periodstart"},"periodEnd":{"type":"string","format":"date","title":"Periodend"},"safetyMode":{"type":"string","title":"Safetymode"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result","description":"The guidance, as Budy's app shows it"},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completedat"},"createdAt":{"type":"string","format":"date-time","title":"Createdat"}},"type":"object","required":["id","status","periodStart","periodEnd","safetyMode","createdAt"],"title":"SupplementAssessment","description":"A supplement_assessment job's result: this calendar month's (UTC) assessment."},"SupplementAssessmentRequest":{"properties":{"health":{"anyOf":[{"$ref":"#/components/schemas/HealthAnswers"},{"type":"null"}]},"includeBodyScan":{"type":"boolean","title":"Includebodyscan","description":"The member's newest saved body scan goes in too","default":false}},"additionalProperties":false,"type":"object","title":"SupplementAssessmentRequest"},"SupplementAssessments":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SupplementAssessment"},"type":"array","title":"Data","description":"Newest month first"}},"type":"object","required":["data"],"title":"SupplementAssessments"},"Swap":{"properties":{"workoutId":{"type":"string","title":"Workoutid"},"exerciseId":{"type":"string","title":"Exerciseid"},"alternativeExerciseId":{"type":"string","title":"Alternativeexerciseid"},"swapped":{"type":"boolean","title":"Swapped","description":"False when back to the planned exercise"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updatedat"}},"type":"object","required":["workoutId","exerciseId","alternativeExerciseId","swapped"],"title":"Swap"},"SwapRequest":{"properties":{"workoutId":{"type":"string","maxLength":64,"minLength":1,"title":"Workoutid"},"exerciseId":{"type":"string","maxLength":64,"minLength":1,"title":"Exerciseid","description":"The planned exercise"},"alternativeExerciseId":{"type":"string","maxLength":64,"minLength":1,"title":"Alternativeexerciseid"}},"additionalProperties":false,"type":"object","required":["workoutId","exerciseId","alternativeExerciseId"],"title":"SwapRequest","description":"POST \u2026/swaps: do one of the AI's alternatives instead of a planned exercise, in one workout.\n\nalternativeExerciseId equal to exerciseId goes back to the planned one."},"Today":{"properties":{"date":{"type":"string","title":"Date"},"timeZone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"restDay":{"type":"boolean","title":"Restday","description":"No workout today; workout is then the next one, if any"},"completedToday":{"type":"boolean","title":"Completedtoday"},"allDone":{"type":"boolean","title":"Alldone","description":"Every workout of the plan is done"},"workout":{"anyOf":[{"$ref":"#/components/schemas/Workout"},{"type":"null"}]},"nextWorkoutDate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextworkoutdate"},"missedWorkout":{"type":"boolean","title":"Missedworkout","description":"A training day passed with no workout: for two days after it, never on a training day","default":false},"longBreak":{"type":"boolean","title":"Longbreak","description":"A training day was missed and nothing done for 14 days","default":false},"recovery":{"anyOf":[{"$ref":"#/components/schemas/TodayRecovery"},{"type":"null"}],"description":"While either of those holds: the way back"},"weeklyReset":{"anyOf":[{"$ref":"#/components/schemas/TodayWeeklyReset"},{"type":"null"}],"description":"The member's next move, and the week's focus"},"nextPlan":{"anyOf":[{"$ref":"#/components/schemas/TodayNextPlan"},{"type":"null"}],"description":"Set once the next plan is on its way"}},"type":"object","required":["date","restDay","completedToday","allDone"],"title":"Today"},"TodayNextMove":{"properties":{"type":{"type":"string","title":"Type","description":"start_due_workout, start_recovery_workout, view_next_week or on_track"},"label":{"type":"string","title":"Label","description":"A short line in English: show it, or your own for this type"}},"type":"object","required":["type","label"],"title":"TodayNextMove"},"TodayNextPlan":{"properties":{"status":{"type":"string","title":"Status","description":"preparing, generating_plan, refreshing, ready, activated, blocked or failed"},"planId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Planid","description":"The next plan, once it's ready"}},"type":"object","required":["status"],"title":"TodayNextPlan"},"TodayRecovery":{"properties":{"workoutId":{"type":"string","title":"Workoutid","description":"The workout that gets the member back on track"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"missedSince":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Missedsince","description":"The last training day missed"}},"type":"object","required":["workoutId"],"title":"TodayRecovery"},"TodayWeeklyReset":{"properties":{"nextMove":{"$ref":"#/components/schemas/TodayNextMove"},"focus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Focus","description":"A headline for the week, in English"}},"type":"object","required":["nextMove"],"title":"TodayWeeklyReset"},"VerifyEmailIn":{"properties":{"email":{"type":"string","maxLength":320,"title":"Email","description":"The member's email"},"code":{"type":"string","pattern":"^\\d{6}$","title":"Code","description":"The 6-digit code from the email"},"password":{"type":"string","maxLength":128,"title":"Password","description":"The password the member signed up with"}},"additionalProperties":false,"type":"object","required":["email","code","password"],"title":"VerifyEmailIn"},"VoiceChanges":{"properties":{"firstChoiceFree":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Firstchoicefree"},"used":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Used"},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit","description":"Changes a month after the first pick; null: not counted"},"remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining"},"resetsAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resetsat"}},"type":"object","title":"VoiceChanges"},"VoiceConsent":{"properties":{"speakerName":{"type":"string","maxLength":80,"minLength":1,"title":"Speakername","description":"Whose voice it is"},"confirmed":{"type":"boolean","const":true,"title":"Confirmed","description":"true: you hold the speaker's written consent"}},"additionalProperties":false,"type":"object","required":["speakerName","confirmed"],"title":"VoiceConsent","description":"Your statement that you hold the speaker's written consent (partner-api.md#voice has its words)."},"VoicePut":{"properties":{"name":{"type":"string","maxLength":60,"minLength":1,"title":"Name","description":"What members see in the voice picker"},"consent":{"anyOf":[{"$ref":"#/components/schemas/VoiceConsent"},{"type":"null"}],"description":"Needed to add a voice; left out on a rename"}},"additionalProperties":false,"type":"object","required":["name"],"title":"VoicePut"},"Voices":{"properties":{"presets":{"items":{"$ref":"#/components/schemas/PresetVoice"},"type":"array","title":"Presets","description":"Budy's coach voices"},"data":{"items":{"$ref":"#/components/schemas/PartnerVoice"},"type":"array","title":"Data","description":"Your own voices"},"defaultVoiceId":{"type":"string","title":"Defaultvoiceid"}},"type":"object","required":["presets","data","defaultVoiceId"],"title":"Voices"},"Workout":{"properties":{"id":{"type":"string","title":"Id"},"planId":{"type":"string","title":"Planid"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"focus":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Focus"},"week":{"type":"integer","title":"Week"},"phase":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Phase"},"day":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Day","description":"MON to SUN"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date","description":"The scheduled day, YYYY-MM-DD"},"status":{"type":"string","title":"Status","description":"pending, completed, skipped or missed"},"minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minutes"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"startedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Startedat"},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completedat"},"exercises":{"items":{"$ref":"#/components/schemas/WorkoutExercise"},"type":"array","title":"Exercises"},"loggedSets":{"items":{"$ref":"#/components/schemas/LoggedSetOut"},"type":"array","title":"Loggedsets"}},"type":"object","required":["id","planId","week","status","exercises"],"title":"Workout"},"WorkoutExercise":{"properties":{"id":{"type":"string","title":"Id","description":"This exercise's place in the workout"},"exerciseId":{"type":"string","title":"Exerciseid"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"equipment":{"items":{"type":"string"},"type":"array","title":"Equipment"},"media":{"items":{"$ref":"#/components/schemas/ExerciseMedia"},"type":"array","title":"Media","description":"Your own links, for your exercises"},"library":{"anyOf":[{"$ref":"#/components/schemas/LibraryDetails"},{"type":"null"}],"description":"For an exercise from your library; null otherwise"},"order":{"type":"integer","title":"Order"},"section":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Section","description":"warmup, main or cooldown"},"instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions"},"restSeconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Restseconds"},"supersetWith":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Supersetwith","description":"The exerciseId it is paired with"},"sets":{"items":{"$ref":"#/components/schemas/PlannedSetOut"},"type":"array","title":"Sets"},"alternatives":{"items":{"$ref":"#/components/schemas/ExerciseRef"},"type":"array","title":"Alternatives","description":"The AI's alternatives; POST \u2026/swaps picks one"},"swappedTo":{"anyOf":[{"$ref":"#/components/schemas/ExerciseRef"},{"type":"null"}],"description":"The member's swap in this workout"}},"type":"object","required":["id","exerciseId","order","sets","alternatives"],"title":"WorkoutExercise"},"WorkoutOutcome":{"properties":{"workoutId":{"type":"string","title":"Workoutid"},"outcome":{"type":"string","title":"Outcome","description":"completed or skipped"},"status":{"type":"string","title":"Status","description":"The workout's status now"},"saved":{"type":"boolean","title":"Saved","description":"False when no set was done (nothing is saved) or the skip was refused"},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completedat"},"skipsLeftThisWeek":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Skipsleftthisweek"},"planFinished":{"type":"boolean","title":"Planfinished","default":false}},"type":"object","required":["workoutId","outcome","status","saved"],"title":"WorkoutOutcome"},"WorkoutSummary":{"properties":{"id":{"type":"string","title":"Id"},"week":{"type":"integer","title":"Week"},"day":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Day"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minutes"}},"type":"object","required":["id","week","status"],"title":"WorkoutSummary"},"WorkoutVoice":{"properties":{"workoutId":{"type":"string","title":"Workoutid"},"status":{"type":"string","title":"Status","description":"ready, pending, generating, failed (being made again) or off (member's choice)"},"voiceId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voiceid"},"introUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Introurl"},"outroUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outrourl"},"exercises":{"items":{"$ref":"#/components/schemas/ExerciseClips"},"type":"array","title":"Exercises","description":"In the workout's order, once ready"},"estimatedReadyAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Estimatedreadyat"}},"type":"object","required":["workoutId","status"],"title":"WorkoutVoice"},"Error":{"title":"Error","type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string","description":"Stable, snake_case, e.g. member_not_found"},"message":{"type":"string"},"requestId":{"type":"string","description":"Also in the X-Request-Id header"}}}}}},"securitySchemes":{"PartnerCredential":{"type":"http","description":"A secret key (bdy_live_\u2026, bdy_test_\u2026) from your server, or a member token from your app; on the sign-in routes (/v1/auth/\u2026), your app's publishable key (bdy_pk_live_\u2026, bdy_pk_test_\u2026)","scheme":"bearer"}}},"servers":[{"url":"https://partners.budy.fit/v1"}],"tags":[{"name":"Members","description":"Your members: create, read, erase, and member tokens for your app."},{"name":"Features","description":"What your plan includes, so your app can hide what's off."},{"name":"Nutrition","description":"A member's meals, recommended by Budy's AI: meal plans and meal ideas with their whole recipes, and calories from a meal photo."},{"name":"Library","description":"Your own exercises, and the search plans pick from."},{"name":"Library imports","description":"A file of exercises, checked first, then applied when you say."},{"name":"Coaching rules","description":"Your guidance in plain words, read by the AI as input."},{"name":"Coaching profile","description":"Your coach's name, voice, and where its exercises come from."},{"name":"Sign-in","description":"Budy signs your members in for your app: email and password, Apple, Google."},{"name":"Notifications","description":"Push and email to your members, in your app's name."}]}