Acta Fit
By Jacob Bergam
Overview
Acta Fit is a strength and conditioning log for iPhone and Apple Watch. Connect it to ask about your own training data in plain language. What you can ask: - Your recent workouts: dates, exercises, sets, reps, loads and volume. - Progress on any lift: top sets and estimated one-rep-max trends over time. - Training stats for the week, month or year: workout count, sets, volume and weeks active. - Heart rate and power for any session, including per-set and per-interval breakdowns, time in zone and normalized power, whenever your Apple Watch or another Apple Health source recorded them. - Your plans, saved workout templates and training maxes. What it can propose: - A training plan, a single workout, or a new exercise. Proposals land in the Acta Fit app, where you review and accept or dismiss them. Nothing in your log changes until you accept. Requirements: the Acta Fit iPhone app with an account and AI sync turned on. Weights are shown in your own unit.
Tools
create_training_plan
ChatGPTweight (in weights_unit, the user's own unit) or percentageOfMax (resolved against the user's training max at review time), never both; (4) pick progressionAlgorithmRaw deliberately: linear5x5 for 5×5-style linear progression, gzclp for GZCLP, none for a manual plan. When a template re-uses the name of one the user already has, include every exercise, every warm-up set (setTypeRaw: 'warmup') and every superset grouping (supersetGroup) from the saved version: the server compares the two and rejects a proposal that leaves any out, listing what is missing; only when the user explicitly asked for a slimmer version, resubmit with confirm_omissions: true. Days reference templates by exact name from this proposal's templates array; a day without templateName is a rest day (weekday 1 = Sunday). An identical resubmit returns the existing pending proposal; pass replaces_id to revise one of your own pending proposals. The user's inbox holds at most 5 pending proposals. When it is full the call files nothing and returns error pending_limit_reached with the pending proposals (id, title, oldest first): don't stop at telling the user the inbox is full; offer to replace the pending proposal most like this one (or else the oldest), naming it by title, and only if they agree, call again with the same arguments plus replaces_id set to its id. The replaced proposal stays in the inbox history. Hard safety limits are enforced server-side and cannot be overridden: a proposal that exceeds them (sets per exercise or week, training days, load above the user's recent best or training max, back-to-back heavy leg days, and the like) is rejected with error hard_limit_violation and a list of violations, each with the field path, the limit and a suggested fix; apply every fix and resubmit.create_workout_template
ChatGPTweight (in weights_unit, the user's unit) or percentageOfMax, never both; and when the name matches a template the user already has, include every exercise, warm-up set (setTypeRaw: 'warmup') and superset grouping (supersetGroup) from the saved version, because the server rejects a proposal that leaves any out and lists what is missing; confirm_omissions: true only when the user explicitly asked for a slimmer version. An identical resubmit returns the existing pending proposal; pass replaces_id to revise one of your own pending proposals. The user's inbox holds at most 5 pending proposals. When it is full the call files nothing and returns error pending_limit_reached with the pending proposals (id, title, oldest first): don't stop at telling the user the inbox is full; offer to replace the pending proposal most like this one (or else the oldest), naming it by title, and only if they agree, call again with the same arguments plus replaces_id set to its id. The replaced proposal stays in the inbox history. Poll get_plan_inbox for the outcome. Hard safety limits are enforced server-side and cannot be overridden: a proposal that exceeds them (sets per exercise or week, training days, load above the user's recent best or training max, back-to-back heavy leg days, and the like) is rejected with error hard_limit_violation and a list of violations, each with the field path, the limit and a suggested fix; apply every fix and resubmit.get_exercise_history
ChatGPTget_plan
ChatGPTget_plan_inbox
ChatGPTformat tells them apart: track.plan.v1 = plan, track.workout.v1 = single workout): pending (awaiting the user's in-app review), imported (accepted — a plan is then readable via get_plan, a workout via get_workout_templates, after the next sync), failed/dismissed (status_detail says why), superseded, expired. List mode returns metadata only; pass proposal_id with include_payload for one full proposal.get_profile
ChatGPTget_training_maxes
ChatGPTget_training_stats
ChatGPTget_workout
ChatGPTnotes when written (their own account of the session — weigh it above the numbers), every exercise and set (weights in the user's unit per weights_unit/key suffix, warmup/working type and completion flagged per set), effort score, heart-rate summary (avg/max/min bpm and time_in_zone when recorded), benchmark scores. Health-imported cardio sessions may also carry distance, elevation, power, speed, cadence, and start-of-workout weather — present only when available, in the user's unit per weights_unit/distance_unit and the matching key suffix (_km/_mi, _m/_ft, _kmh/_mph, _c/_f). A streams block means a heart-rate and/or power sample stream exists: use get_workout_metrics for per-set and per-interval heart rate and power, totals (work in kJ, normalized power), and the raw series.get_workout_metrics
ChatGPTheart_rate: avg/max/min bpm, time_in_zone; power: avg/max/min W, normalized_w, work_kj) and a segments timeline that splits the session into work and rest blocks from the rest timer, labelling each work block with the logged exercise + set (set_alignment says how reliable that labelling is) and giving that block's own avg/max/min heart rate and power plus work_kj — this is the per-set / per-interval breakdown. Everything is computed from the full sample streams; set include_series true to also get the raw series as [seconds_from_start, value] pairs (bucket-averaged to max_points). notes explains any missing data: a session without a heart-rate source has heart_rate null, and power is only ever present when the workout's Apple Health source wrote a power series (Apple Watch rides and runs do; Peloton and Strava imports generally do not), so most strength sessions and many imported rides have power null while their heart rate is complete. Weights on set labels are in the user's unit (weights_unit).get_workout_templates
ChatGPTlist_workouts
ChatGPTavg_heart_rate when a heart-rate source covered the session, effort_score when the user rated the session, and notes when the user wrote any). effort_score is the user's own session RPE on a 0–10 scale (CR-10) — scan it across sessions for fatigue and readiness trends; a session without the key simply wasn't rated. notes are the user's OWN WORDS about that session (pain, what they skipped and why, energy) — read them before judging a session by its numbers, and carry their implications into any plan you propose. Volume counts completed non-warmup sets; completed_sets includes warmups. All weights are in the USER'S OWN unit — the response's weights_unit field and _kg/_lb key suffixes say which; use their unit in every reply. Dates are ISO-8601 UTC. Use get_workout with a returned session_key for full sets. Archived sessions are excluded unless include_archived is true.ping
ChatGPTCapabilities
Example Prompts
Click any prompt to copy it.






