API Reference

CoachLayer API v1.0.0 · OpenAPI 3.1 · Base URL https://coachlayer.justzon.com. Sandbox keys (cl_test_) run in test mode; live keys open with the paid tiers.

Quickstart

Three calls from zero to coaching. Create an account to mint a sandbox key from the dashboard (300 free credits/month, hard stop, no card), or do it straight from the terminal:

# 1. mint a sandbox key (shown once, stored hashed)
curl https://coachlayer.justzon.com/v1/signup \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Fitness",
  "email": "dev@acme.fit"
}'

# 2. your first coaching call
curl https://coachlayer.justzon.com/v1/brief \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "biometrics": {
    "sleep_score": 82,
    "hrv_value": 68,
    "resting_heart_rate": 52,
    "subjective_readiness": 4
  },
  "schedule": {
    "has_workout": true,
    "workout_name": "Push Day A",
    "is_heavy": true
  },
  "user_profile": {
    "age": 31,
    "weight_kg": 78,
    "height_cm": 181,
    "gender": "male"
  },
  "lang": "en"
}'

# 3. see what it cost
curl https://coachlayer.justzon.com/v1/usage -H "Authorization: Bearer $COACHLAYER_API_KEY"

Authentication

Every call (except /health) is authenticated with a Bearer API key: Authorization: Bearer cl_test_…. Test keys (cl_test_) are the only kind that exist in the prototype; live keys (cl_live_) are structurally blocked until launch. Keys are stored hashed and shown once at mint time; revoke and re-mint at will.

Credits & tiers

Every endpoint costs a fixed number of credits per call; heavier reasoning costs more. Two endpoints carry a length surcharge. Credits reset monthly with your tier; overage is billed per credit on production tiers.

EndpointRouteCreditsSurcharge
Coach Chat/v1/chat2 / messagenone
Readiness Brief (SITREP)/v1/brief3 / briefnone
Coach Insight/v1/coach-insight3 / insightnone
Analyze Workout/v1/workout-analysis6 / analysisnone
Adaptive Program/v1/adaptive-session8 / day rewritenone
Weekly Report/v1/weekly-report12 / reportnone
Form Check/v1/form-check25 / clip+25 per extra 30 seconds beyond 30
Magic Import/v1/import40 / import+20 per extra 12 weeks beyond 12
TierPriceCredits/moOveragerpmNotes
Sandbox$0/mo300hard stop10No card required
Build$39/mo2,500$0.025/cr30No form_check. Email support
Launch$99/mo7,000$0.022/cr60Webhooks, usage dashboard
Growth recommended$299/mo24,000$0.018/cr300Analytics, priority support
Scale$999/mo95,000$0.014/cr1000White-label, SSO, DPA
EnterpriseCustom250,000Custom2000Annual, committed discounts, fine-tunes on your data, dedicated infra

Estimate a real workload with the pricing calculator.

Errors

One envelope everywhere: {"error": {"type", "code", "message", "request_id"}}:

TypeStatusMeaning
authentication_error401Missing, malformed or revoked API key.
invalid_request_error400Body fails validation; the message names the field.
billing_error402 / 403credit_limit_exhausted (Sandbox hard stop) or endpoint_not_in_tier (e.g. Form Check on Build).
rate_limit_error429Tier rpm exceeded; Retry-After header tells you when to retry.
upstream_error502Model upstream failed. You were not charged.
capacity_error503free_tier_paused (shared free-sandbox budget exhausted for the month, paid tiers unaffected) or gateway_unavailable (transient backend outage, retry shortly).

Failed calls are never charged. A 502 from the model upstream logs telemetry for our reliability tracking but bills 0 credits.

Metering headers & rate limits

Every metered response tells you what it cost:

HeaderMeaning
X-Credits-ChargedCredits charged for this call, length surcharges included.
X-Credits-OveragePortion of the charge billed as overage (0 while inside the allowance).
X-Credits-RemainingIncluded credits remaining in the current billing period.
X-Request-IdCorrelation id, echoed in error envelopes and the usage ledger.

Rate limits are per-tier requests-per-minute over a fixed 60-second window; a 429 carries Retry-After in seconds.

LLM-readable docs & MCP

Your coding agent can read this API natively:

  • llms.txt: the index, per the llms.txt standard.
  • llms-full.txt: the whole reference in one markdown file. Paste it into any LLM's context.
  • openapi.yaml: the machine-readable OpenAPI 3.1 contract.
  • MCP server: the gateway ships a Model Context Protocol server exposing all 10 tools (stdio transport). Point Claude Code / Claude Desktop at it:
{
  "mcpServers": {
    "coachlayer": {
      "command": "npm",
      "args": ["run", "-s", "mcp", "--prefix", "/path/to/coachlayer"],
      "env": {
        "COACHLAYER_API_KEY": "cl_test_…",
        "COACHLAYER_BASE_URL": "https://coachlayer.justzon.com"
      }
    }
  }
}

Then ask your agent things like “run a form check on this clip” or “how many credits did we burn this week?”. The tools map 1:1 onto the endpoints below.

Guides & comparisons

Before you wire it in: what it costs, how it fits your stack, and how it compares with building it yourself.

Intelligence endpoints

POST /v1/chat

2 credits / message

Coach chat (2 credits/message)

Request fields

FieldTypeDescription
messages requiredarray of objectConversation so far; the last entry must be role "user". Trimmed to the last 12.
workout_contextobjectLive workout state that grounds the reply.
langstringISO 639-1 Default: "en".

Example request

curl https://coachlayer.justzon.com/v1/chat \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "messages": [
    {
      "role": "user",
      "content": "Bench felt heavy at 80kg for 3x8. Should I go up next session?"
    }
  ],
  "workout_context": {
    "workout_name": "Push Day A",
    "completed_sets_summary": "Bench 3x8 @ 80kg, OHP 3x10 @ 40kg",
    "active_exercise_name": "Bench Press",
    "primary_goal": "strength"
  },
  "lang": "en"
}'

Example response

{
  "reply": "Nice work on the bench sets. Given 3x8 at 80kg felt solid, load 82.5kg for your next set and keep the same rep target. Stop one rep shy of failure."
}

POST /v1/brief

3 credits / brief

Daily readiness brief, aka SITREP (3 credits)

Request fields

FieldTypeDescription
biometrics requiredobject
schedule requiredobject
completed_todayobject
user_profileobject
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/brief \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "biometrics": {
    "sleep_score": 82,
    "hrv_value": 68,
    "resting_heart_rate": 52,
    "subjective_readiness": 4
  },
  "schedule": {
    "has_workout": true,
    "workout_name": "Push Day A",
    "is_heavy": true
  },
  "user_profile": {
    "age": 31,
    "weight_kg": 78,
    "height_cm": 181,
    "gender": "male"
  },
  "lang": "en"
}'

Example response

{
  "title": "Primed for Push Day",
  "short_recommendation": "Green light: train as planned.",
  "status": "normal",
  "message": "Sleep score 82 and HRV trending up: recovery is on your side today. Your push session is a go at full intensity. Cap the last pressing movement two reps shy of failure to bank tomorrow."
}

POST /v1/coach-insight

3 credits / insight

Coach-facing athlete insight (3 credits)

Same input contract as /v1/brief, framed for the coach reviewing an athlete.

Request fields

FieldTypeDescription
biometrics requiredobject
schedule requiredobject
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/coach-insight \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "biometrics": {
    "sleep_score": 64,
    "hrv_value": 51,
    "resting_heart_rate": 58
  },
  "schedule": {
    "has_workout": true,
    "workout_name": "Pull Day B"
  },
  "lang": "en"
}'

Example response

{
  "title": "Adherence is the story this week",
  "short_recommendation": "Flag the missed pull sessions before they become a pattern.",
  "status": "normal",
  "message": "This athlete hit 3 of 5 planned sessions and skipped both pull days. Volume on push muscles is 40% above their 30-day average; worth rebalancing next week before elbow niggles show up."
}

POST /v1/workout-analysis

6 credits / analysis

Post-workout analysis (6 credits)

Request fields

FieldTypeDescription
workout requiredobjectThe completed session: name, exercises[] (name, muscle_group, tracking_type, sets[] with weight_kg/reps/rpe/distance_meters/duration_seconds), duration_seconds, notes, debrief_tags/debrief_note, average_bpm, total_distance_meters. Optional session_type override.
historyarray of objectPrior sessions (date, name, total_volume_kg, exercises[]); enables PR detection and e1RM deltas (needs >= 2 prior data points per lift).
athleteobjectage, weight_kg, goal, experience (beginner|intermediate|advanced), sessions_completed, streak_days, days_since_last_session.
coach_directivesstringFree-text instructions from the athlete's human coach, applied by the analysis.
warning_countsobject7-day repeat-warning counts (low_sleep, low_readiness, pace_fade, sessions_in_window); dampens or escalates repeated warnings.
optionsobjectprogressive_overload: boolean (default false). True emits per-exercise load prescriptions.
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/workout-analysis \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "workout": {
    "name": "Lower A",
    "duration_seconds": 3600,
    "exercises": [
      {
        "name": "Back Squat",
        "muscle_group": "quads",
        "tracking_type": "weight_reps",
        "sets": [
          {
            "weight_kg": 100,
            "reps": 5,
            "rpe": 8
          },
          {
            "weight_kg": 100,
            "reps": 5,
            "rpe": 8.5
          }
        ]
      }
    ]
  },
  "history": [
    {
      "date": "2026-08-28",
      "name": "Lower A",
      "total_volume_kg": 5200
    }
  ],
  "athlete": {
    "age": 31,
    "weight_kg": 78,
    "goal": "strength",
    "experience": "intermediate",
    "sessions_completed": 142,
    "streak_days": 12
  },
  "options": {
    "progressive_overload": false
  },
  "lang": "en"
}'

Example response

{
  "headline": "Strong session with a pacing caveat",
  "rating": 8,
  "key_insights": [
    {
      "type": "volume",
      "label": "Total volume",
      "metric": "+12% vs last legs day",
      "tone": "positive"
    },
    {
      "type": "pacing",
      "label": "Rest drift",
      "metric": "rests grew 45s by the final block",
      "tone": "warning"
    }
  ],
  "next_step": "Keep the added back-squat set; tighten rests to 2:30 on accessories.",
  "summary": "Volume progression is on track and bar speed held up across the top sets. The only leak is pacing: the back half of the session drifted long, which mutes the conditioning stimulus.",
  "strengths": [
    "Progressive overload on squat",
    "Consistent depth across all sets"
  ],
  "improvements": [
    "Rest discipline on accessories"
  ],
  "session_type": "strength",
  "schema_version": 2
}

POST /v1/adaptive-session

8 credits / day rewrite

Adaptive session synthesis (8 credits)

Request fields

FieldTypeDescription
duration_minutes required15 | 30 | 45 | 60 | 90
equipment_preset required"full_gym" | "home_gym" | "hotel" | "custom"
allowed_equipmentarray of string
signalsobjectRecovery + load signals (ACWR per muscle, 7/30-day volume, sleep, HRV, soreness…).
personal_recordsarray of object
goalstring | null
notesstring | null
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/adaptive-session \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "duration_minutes": 45,
  "equipment_preset": "full_gym",
  "signals": {
    "sleep_hours": 7.5,
    "hrv_trend": "up",
    "soreness": {
      "hamstrings": 6
    }
  },
  "personal_records": [
    {
      "exercise_name": "Back Squat",
      "e1rm": 140
    }
  ],
  "goal": "strength",
  "lang": "en"
}'

Example response

{
  "session_name": "Adaptive Lower Body (45 min)",
  "reasoning": "ACWR shows quads fresh but hamstrings near the top of their band; the session biases hinge volume down and keeps squat intensity, matching the 45-minute cap.",
  "estimated_volume_kg": 6450,
  "estimated_duration_minutes": 44,
  "exercises": [
    {
      "library_exercise_name": "Back Squat",
      "order_index": 1,
      "block_label": "A",
      "target_sets": 4,
      "target_reps": 6,
      "target_weight_kg": 100,
      "rest_seconds": 180,
      "notes": "Top set at RPE 8.",
      "tracking_type": "weight_reps"
    },
    {
      "library_exercise_name": "Romanian Deadlift",
      "order_index": 2,
      "block_label": "B",
      "target_sets": 3,
      "target_reps": 8,
      "target_weight_kg": 80,
      "rest_seconds": 150,
      "notes": "Reduced a set vs plan: hamstring ACWR 1.28.",
      "tracking_type": "weight_reps"
    }
  ]
}

POST /v1/weekly-report

12 credits / report

Weekly training report (12 credits)

Request fields

FieldTypeDescription
week requiredobjectAggregates of the week under review (start_date, end_date, total_volume_kg, total_duration_seconds, session_count, avg_rpe, total_distance_meters).
previous_weekobjectSame aggregates for the prior week; enables trends (deltas are computed server-side and clamped).
goalobjectcategory: endurance|strength|crossfit|hypertrophy|weight_loss|general; focus: free text.
movementsarray of objectPer-lift context (name, top_set, e1rm_kg, previous_e1rm_kg, sets_done, target_sets); this is what turns narration into coaching.
sessionsarray of objectSession summaries of the week (date, name, volume_kg, distance_meters, duration_seconds, avg_rpe).
wellnessobjectdaily: array of {date, sleep_hours, sleep_quality, stress_level, soreness_level, energy_level}.
nutritionarray of objectDaily macros ({date, kcal, protein_g, carb_g, fat_g}).
check_inobjectWeekly check-in (date, weight_kg, notes, qa[]).
previous_directivesarray of objectPrior weeks' directives ({week_start_date, focus_area, directive}); prevents repetition.
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/weekly-report \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "week": {
    "start_date": "2026-08-31",
    "end_date": "2026-09-06",
    "total_volume_kg": 42300,
    "total_duration_seconds": 14400,
    "session_count": 4,
    "avg_rpe": 7.6
  },
  "previous_week": {
    "start_date": "2026-08-24",
    "end_date": "2026-08-30",
    "total_volume_kg": 38800,
    "session_count": 4,
    "avg_rpe": 7.3
  },
  "goal": {
    "category": "strength",
    "focus": "squat 1RM"
  },
  "movements": [
    {
      "name": "Back Squat",
      "top_set": "120kg x 5",
      "e1rm_kg": 140,
      "previous_e1rm_kg": 136,
      "sets_done": 12,
      "target_sets": 12
    }
  ],
  "lang": "en"
}'

Example response

{
  "rank": "A",
  "headline": "Best training week in a month",
  "summary": "4 of 4 planned sessions completed, volume up 9% on rising intensity, and sleep held above 7h every night. One watch-out: Friday soreness spiked after the deadlift PR.",
  "metrics": {
    "volume": {
      "value": "42,300 kg",
      "trend": "up",
      "diff_percent": 9
    },
    "intensity": {
      "value": "7.6",
      "trend": "up",
      "diff_percent": 4,
      "unit": "RPE"
    },
    "consistency": {
      "value": "100%",
      "trend": "flat",
      "diff_percent": 0
    }
  },
  "focus_area": "Recovery",
  "coach_directive": "Hold volume next week and bank the adaptation: no new PR attempts before Thursday.",
  "next_week_plan": [
    {
      "title": "Deload hinge pattern",
      "detail": "RDLs at 80% of this week’s load."
    },
    {
      "title": "Keep squat intensity",
      "detail": "Same top-set weight, one fewer back-off set."
    }
  ],
  "wins": [
    "Deadlift PR 180kg",
    "Perfect session adherence"
  ]
}

POST /v1/form-check

25 credits / clip · +25 per extra 30 seconds

Video form check (25 credits ≤30s, +25 per extra 30s)

Request fields

FieldTypeDescription
video_url requiredstring
video_secondsnumberClip length; drives the length surcharge. Clips are analyzed at pinned low media resolution.
exercise_namestring | null
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/form-check \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "video_url": "https://cdn.example.com/clips/squat-topset.mp4",
  "video_seconds": 24,
  "exercise_name": "Back Squat",
  "lang": "en"
}'

Example response

{
  "score": 78,
  "strengths": [
    "Consistent bar path",
    "Solid brace at setup"
  ],
  "improvements": [
    "Knees cave slightly on reps 4-5",
    "Depth just above parallel under fatigue"
  ],
  "recommendations": [
    "Add a 2-second pause squat set at 60% to groove depth.",
    "Cue \"knees out\" on the final reps or drop 5% load."
  ],
  "detected_exercise": "Back Squat",
  "low_confidence": false
}

POST /v1/import

40 credits / import · +20 per extra 12 weeks

Magic Import: parse a program from text/file (40 credits up to 12 weeks, +20 per extra 12)

Request fields

FieldTypeDescription
text_contentstringRaw program text (one of text_content / file_url / file_base64 required).
file_urlstringPDF/image/markdown source.
file_base64stringInline file content
file_mime_typestringMIME type of file_base64 (application/pdf
program_weeksnumberDeclared length; drives the length surcharge.
import_type"full_program" | "routine" | "nutrition_import"Default: "full_program".
langstringDefault: "en".

Example request

curl https://coachlayer.justzon.com/v1/import \
  -H "Authorization: Bearer $COACHLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "text_content": "Week 1\nDay 1: Squat 5x5 @ 75%, RDL 3x8, Plank 3x60s\nDay 2: Bench 5x5 @ 77.5%…",
  "program_weeks": 8,
  "import_type": "full_program",
  "lang": "en"
}'

Example response

{
  "message": "Program parsed and structured successfully.",
  "import_type": "full_program",
  "is_finished": true,
  "imported_data": {
    "type": "full_program",
    "weeks_count": 8,
    "workouts_count": 32,
    "program_json": {
      "name": "Intermediate Strength Block",
      "weeks": 8,
      "days_per_week": 4,
      "sample_day": {
        "name": "Day 1: Squat focus",
        "exercises": [
          {
            "name": "Back Squat",
            "sets": 5,
            "reps": 5,
            "intensity": "75-82% 1RM"
          }
        ]
      }
    }
  }
}

Platform endpoints

POST /v1/signup

free · public

Self-serve sandbox signup (no auth, no card)

Request fields

FieldTypeDescription
name requiredstringAccount or project name (1-120 characters).
email requiredstringContact address for the account.

Example request

curl https://coachlayer.justzon.com/v1/signup \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Fitness",
  "email": "dev@acme.fit"
}'

Example response

{
  "tenant_id": "ten_9f2c",
  "name": "Acme Fitness",
  "tier": "sandbox",
  "api_key": "cl_test_k3H…",
  "note": "Store this key now: it is shown once and kept only as a hash. Sandbox is test-mode only."
}

GET /v1/me

free · authenticated

Current key's tenant, tier and limits

Example request

curl https://coachlayer.justzon.com/v1/me \
  -H "Authorization: Bearer $COACHLAYER_API_KEY"

Example response

{
  "tenant_id": "ten_9f2c",
  "name": "Acme Fitness",
  "tier": "growth",
  "monthly_credits": 24000,
  "rpm": 300,
  "blocked_endpoints": []
}

GET /v1/usage

free · authenticated

Current billing period usage

Example request

curl https://coachlayer.justzon.com/v1/usage \
  -H "Authorization: Bearer $COACHLAYER_API_KEY"

Example response

{
  "period": "2026-09",
  "tier": "growth",
  "credits_included": 24000,
  "credits_used": 1240,
  "credits_remaining": 22760,
  "by_endpoint": {
    "chat": {
      "calls": 310,
      "credits": 620,
      "tokens_in": 868000,
      "tokens_out": 198400
    },
    "weekly_report": {
      "calls": 40,
      "credits": 480,
      "tokens_in": 392000,
      "tokens_out": 108000
    }
  }
}

GET /health

free · public

Liveness (public)