# App Integration Guide

Screen-by-screen mapping of every app page to its sTvOS backend API calls.

This document maps every screen in the app to the sTvOS backend API endpoints it should call. Use it as a reference when building or migrating an app on the platform.


# Conventions

Headers required on every client-scoped request:

Header Value
X-API-Key Universal key or per-client fytos_... key
Authorization Bearer <accessToken> (when noted as "bearer required")
Content-Type application/json

Response envelope: All responses return { success: true, data: ... } on success and { error, code, details } on failure.

Feature gating: The enabledFeatures array from /auth/me or /app/config determines which sections of the app to show. Check with features.includes('feature_key').

Feature Key Unlocks
classes On-demand video classes, class browsing
live_classes Scheduled live streaming classes
workout_builder AI workout generation, workout player
nutrition Nutrition tracking, food scanning, meal plans
coach_connect Trainer browsing, booking sessions
ai_coach AI coaching (Hume voice/chat)

# 1. Auth and Onboarding

# Login

   
Purpose Email/password authentication
API Call POST /auth/login
Body { email, password }
Auth API key only (no bearer)
Response { user, tokens: { accessToken, refreshToken, expiresIn }, client? }
Notes In universal key mode, response includes client object with branding. Store tokens securely (expo-secure-store). Navigate to main app on success, register or forgot on failure.

# Register

   
Purpose Create new account
API Call POST /auth/register
Body { email, password, name, voucherCode?, sessionId? }
Auth API key only
Response { user, tokens } (201)
Error Codes USER_EXISTS, VOUCHER_REQUIRED, INVALID_VOUCHER, NO_DEFAULT_CLIENT
Notes Pass voucherCode if user arrived via voucher/deep link. Pass sessionId from onboarding to link pending profile data. Show voucher branding from validateVoucher data if available.

# ForgotPass

   
Purpose Request password reset email
API Call POST /auth/forgot-password
Body { email }
Auth API key only
Status NOT YET IMPLEMENTED -- needs backend endpoint

# VoucherEntry

   
Purpose Manually enter a voucher code
API Call GET /app/join/:code
Auth Public (no key needed)
Response { valid, client: { id, name, logo, splashScreen, enabledFeatures }, error? }
Notes On success, navigate to JoinScreen passing the voucher code and client data.

# JoinScreen

   
Purpose Post-voucher welcome with client branding
API Call GET /app/join/:voucherCode (on mount, to refresh/validate)
Auth Public
Notes Display client.logo, client.splashScreen, client.name. Route to register (pre-filling voucher code) or login.

# ProfileSetup (Onboarding Wizard)

   
Purpose Multi-step profile setup before/after registration
API Calls  
Step Endpoint Details
Save profile data per step POST /onboarding/profile Body: { sessionId, step, data: { ... } }. Returns sessionId on first call.
Get coach recommendations POST /onboarding/recommend-coaches Body: { sessionId }. Returns ranked coaches.
Select a coach POST /onboarding/select-coach Body: { sessionId, coachId }
Generate workout plan (final) POST /users/me/workout-plan Bearer required. After registration.
   
Auth Onboarding endpoints: API key only. Workout plan: bearer required.
Notes Steps cover: gender, weight/height, birthday, diet/meals (if nutrition), activity level (if workout_builder), workout days, training location, goal, preferred classes. On finish, call POST /auth/register with sessionId to link profile, then generate workout plan if workout_builder enabled.

# 2. Profile and Settings

# Profile

   
Purpose Profile hub with avatar, name, links to sub-pages
API Calls  
Action Endpoint Details
Load profile GET /auth/me Bearer required. Returns user + client.
Upload photo POST /auth/profile-photo NOT YET IMPLEMENTED
Delete account DELETE /users/me Bearer required.
Logout POST /auth/logout Bearer required. Discard tokens client-side.

# ManageProfile

   
Purpose Edit fitness preferences
API Calls GET /auth/me (load), PUT /users/me (save)
Auth Bearer required
Editable Fields name, gender, birthday, weight, height, activityLevel, workoutDays, goal, diet, meals, preferredClasses
Notes After saving workout-related fields, offer "Rebuild Workout" which calls POST /users/me/workout-plan.

# Settings

   
Purpose Language and theme toggle
API Calls None -- local preferences only (AsyncStorage / context)

# Terms (Privacy Policy)

   
Purpose Render privacy policy HTML
API Call GET /app/strings
Auth API key required
Response { data: [{ st_privacypolicy: "<html>..." }] }
Notes Render the st_privacypolicy value in a WebView or HTML renderer.

# About

   
Purpose Render about us HTML
API Call GET /app/strings
Auth API key required
Response { data: [{ st_aboutus: "<html>..." }] }
Notes Render the st_aboutus value. Same endpoint as Terms -- fetch once and cache.

# 3. Workout System

# Home

   
Purpose Main dashboard with conditional sections
API Calls Child components make their own calls (see below). Gate sections with hasFeature().
Key Sections Today's workout (workout_builder), latest classes (classes), goals, levels, exercises, diets (nutrition).
Section Endpoint
Today's workout GET /users/me/daily-plan?date=YYYY-MM-DD (bearer)
Latest classes GET /content/classes?limit=6&sort=newest or GET /classes?limit=6
Discover/featured GET /content/discover (bearer)

# Workouts

   
Purpose Paginated workout list
API Call GET /content/classes?page=1&limit=8&sort=newest or GET /classes?limit=8&page=1
Auth API key (+ bearer for content routes)
Notes Navigate to workoutdetails on tap, goals/levels/searchworkout from header buttons.

# WorkoutDetails

   
Purpose Single workout with day schedule
API Calls  
Action Endpoint
Load workout GET /content/classes/:id or GET /classes/:id
Load day detail GET /users/me/workout-plan/day/:dayId (bearer)
Bookmark Local only (AsyncStorage)
Add workout to plan Navigate to WorkoutLoading with { workoutId }

# WorkoutLoading

   
Purpose Loading screen during AI plan creation
API Call POST /users/me/workout-plan
Body { workoutId? } (optional, to base plan on a specific workout)
Auth Bearer required
Fallback poll GET /sessions/history?active=true
Notes Navigate to home on success. Show error with retry on failure.

# MyWorkouts (Progress Dashboard)

   
Purpose Stats, charts, recent workout history
API Call GET /progress?period=week or GET /progress?period=month
Auth Bearer required
Notes The /progress endpoint returns streak, charts, and recent workout logs. Period param: day, week, month, year.

# SingleDay

   
Purpose Single workout day with exercise list
API Calls  
Action Endpoint
Load day GET /users/me/workout-plan/day/:dayId (bearer)
Update exercise status POST /progress/workout (bearer)
Reset day DELETE /users/me/workout-plan + recreate, or custom reset logic

# Timer (Active Workout)

   
Purpose Active workout execution with sets/reps
API Calls  
Action Endpoint
Load timer data GET /users/me/workout-plan/day/:dayId (bearer)
Log set progress POST /progress/workout (bearer)
Complete workout POST /progress/workout with full exercise log (bearer)
   
Notes Keep screen awake. Post workout log with exercises, sets, weights, reps, duration, perceived exertion.

# Completed

   
Purpose Post-workout summary
API Call No new call needed -- use data from Timer completion response
Notes Shows exercises completed, duration, calories. "Back to Home" button.

# SearchWorkout

   
Purpose Search workouts by query
API Call GET /content/search?q=<query>&page=1&limit=8 or GET /classes?search=<query>&page=1&limit=8
Auth API key (+ bearer for content routes)

# WorkoutsFav

   
Purpose Favorited/bookmarked workouts
API Calls Local only (AsyncStorage). Load IDs from storage, then fetch details per ID if needed via GET /classes/:id.

# Player (Video)

   
Purpose Full-screen video player
API Calls None to backend. Fetch Vimeo HLS config directly from Vimeo CDN.
Notes Receives { url } from navigation params.

# 4. Exercises

# Exercises

   
Purpose Exercise library grouped by body part
API Call GET /classes/categories?type=bodypart
Auth API key

# ExerciseDetails

   
Purpose Single exercise with video, reps, sets, instructions
API Call GET /classes/:id
Auth API key

# SingleMuscle

   
Purpose Exercises filtered by muscle group
API Call GET /classes?muscle=<id>&page=1&limit=16
Auth API key

# SingleEquipment

   
Purpose Exercises filtered by equipment
API Call GET /classes?equipment=<id>&page=1&limit=16
Auth API key

# Equipments

   
Purpose Equipment list
API Call GET /classes/categories?type=equipment
Auth API key

# 5. Classes

# Classes

   
Purpose Paginated on-demand class list
API Call GET /content/classes?page=1&limit=20 or GET /classes?page=1&limit=20
Auth API key (+ bearer for /content routes)

# ClassDetails

   
Purpose Class detail with preview video, description, coach info
API Call GET /content/classes/:id or GET /classes/:id
Auth API key
Notes Can also use route.params.class if the full object was passed from the list. "Start Class" navigates to classPlayer.

# ClassPlayer

   
Purpose Full-screen class video player with session tracking
API Calls  
Action Endpoint
Get HLS URL Vimeo CDN (direct fetch, no backend call)
Start session POST /sessions/start -- Body: { classId, totalDurationSeconds } (bearer)
Update progress POST /sessions/:id/progress -- Body: { progressSeconds, completionPercentage } (bearer)
Complete session POST /sessions/:id/complete (bearer)
   
Notes Lock to landscape. Track progress periodically (every 10-30s).

# CategoryClasses

   
Purpose Classes filtered by category
API Call GET /content/classes?category=<id>&page=1&limit=20 or GET /classes?category=<id>&page=1

# Categories

   
Purpose Class category list
API Call GET /content/categories or GET /classes/categories

# Coaches

   
Purpose Coach/trainer list
API Call GET /trainers?page=1&limit=10
Auth Bearer required

# CoachDetails

   
Purpose Coach profile with their classes
API Calls GET /trainers/:id and GET /trainers/:id/classes
Auth Bearer required

# 6. Nutrition / Diets

# Diets

   
Purpose Paginated diet/nutrition content list
API Call GET /content/classes?type=nutrition&page=1&limit=6 or GET /classes?type=nutrition&page=1&limit=6
Auth API key

# DietDetails

   
Purpose Diet detail with nutrition info, ingredients
API Call GET /content/classes/:id or GET /classes/:id
Auth API key
Notes Bookmark via AsyncStorage (local).

# DietsFav

   
Purpose Favorited diets
API Calls Local only (AsyncStorage). Fetch details per ID if needed.

# CustomDiets

   
Purpose User's AI-generated or assigned nutrition plans
API Call GET /users/me/nutrition-plan
Auth Bearer required
Notes For week detail: GET /users/me/nutrition-plan/week/:weekId.

# SingleCategory (Diets)

   
Purpose Diets filtered by category
API Call GET /content/classes?type=nutrition&category=<id>&page=1&limit=6

# 7. Blog / Posts

# Blog

   
Purpose Blog hub with featured posts and tags
API Calls Child components make their own calls (see Posts, PostDetails).

# Posts

   
Purpose Paginated post list
API Call GET /content/classes?type=blog&page=1&limit=6 or GET /classes?type=blog&page=1&limit=6
Auth API key

# PostDetails

   
Purpose Single blog post with HTML content
API Call GET /content/classes/:id or GET /classes/:id
Auth API key
Notes Render HTML content in a WebView or HTML renderer.

# SingleTag

   
Purpose Posts filtered by tag
API Call GET /content/classes?type=blog&tag=<id>&page=1

# 8. Store / Products

Products are affiliate items that partners create via the partner portal. Each product belongs to a single client and has a name, description, image, price, and an external buy link.

# Store

   
Purpose Store hub with featured products and product types
API Calls  
Section Endpoint
Featured products GET /products?featured=true&limit=6
Product types GET /products/types
Latest products GET /products?page=1&limit=8&sort=newest
   
Auth API key required

# Products

   
Purpose Paginated product list
API Call GET /products?page=1&limit=8&sort=newest
Auth API key required
Query Params page, limit, productType, featured, search, sort (newest, oldest, price_asc, price_desc, sort_order)
Response { products[], pagination: { page, limit, total, totalPages } }

# ProductDetails

   
Purpose Product detail with buy button
API Call GET /products/:id
Auth API key required
Response Full product object with externalUrl
Notes "Buy Now" opens externalUrl in an external browser. No payment processing in-app.

# SingleType

   
Purpose Products filtered by type
API Call GET /products?productType=<type>&page=1&limit=8
Auth API key required

# 9. Lookup / Filters

# Goals

   
Purpose Workout goal list
API Call GET /classes/categories?type=goal
Auth API key

# Levels

   
Purpose Intensity level list
API Call GET /classes/categories?type=level
Auth API key

# SingleGoal

   
Purpose Workouts filtered by goal
API Call GET /classes?goal=<id>&page=1 or GET /content/classes?goal=<id>&page=1

# SingleLevel

   
Purpose Workouts filtered by level
API Call GET /classes?intensity=<level>&page=1 or GET /content/classes?intensity=<level>&page=1

# 10. Favorites

# Favorites (Tab)

   
Purpose Tabbed container for WorkoutsFav and DietsFav
API Calls None directly -- delegates to child components.

# Missing Features (Backend Work Needed)

The following features are referenced by app screens but do not yet have backend endpoints:

# 1. Forgot Password

   
Screen ForgotPass
Needed Endpoint POST /auth/forgot-password
Body { email }
Behaviour Send password reset email with token link.

# 2. Profile Photo Upload

   
Screen Profile
Needed Endpoint POST /auth/profile-photo or POST /users/me/photo
Body Multipart form with image file
Behaviour Upload and store avatar URL on user record.

# 3. Store / Products -- IMPLEMENTED

Products are now available via /products endpoints (API key required) and managed by partners through GET/POST/PUT/DELETE /partner/products in the partner portal.


# API Call Quick Reference

A flat reference of every backend call used across all screens:

# Public (no auth)

Method Path Used By
GET /app/config App launch
GET /app/join/:code VoucherEntry, JoinScreen

# API Key Only

Method Path Used By
POST /auth/register Register
POST /auth/login Login
POST /auth/refresh Token refresh (auto)
GET /app/strings Terms, About
POST /onboarding/profile ProfileSetup
POST /onboarding/recommend-coaches ProfileSetup
POST /onboarding/select-coach ProfileSetup
GET /classes Workouts, Exercises, Diets, Posts
GET /classes/:id WorkoutDetails, ExerciseDetails, DietDetails, PostDetails
GET /classes/categories Exercises, Equipments, Goals, Levels, Categories
GET /products Store, Products
GET /products/:id ProductDetails
GET /products/types Store (product types)

# Bearer Token Required

Method Path Used By
GET /auth/me Profile, ManageProfile
POST /auth/logout Profile
PUT /users/me ManageProfile
DELETE /users/me Profile (delete account)
GET /content/discover Home
GET /content/classes Classes, Workouts (alternative)
GET /content/classes/:id ClassDetails (alternative)
GET /content/search SearchWorkout
GET /content/categories Categories (alternative)
GET /users/me/daily-plan Home (today's workout)
POST /users/me/workout-plan WorkoutLoading
GET /users/me/workout-plan MyWorkouts
GET /users/me/workout-plan/day/:dayId SingleDay, Timer
GET /users/me/nutrition-plan CustomDiets
GET /progress MyWorkouts
POST /progress/workout SingleDay, Timer
POST /progress/nutrition Nutrition tracking
POST /progress/body-metrics Body metrics logging
POST /progress/water Water intake logging
POST /sessions/start ClassPlayer
POST /sessions/:id/progress ClassPlayer
POST /sessions/:id/complete ClassPlayer
GET /sessions/history MyWorkouts
GET /trainers Coaches
GET /trainers/:id CoachDetails
GET /trainers/:id/classes CoachDetails
GET /trainers/:id/services CoachDetails
GET /trainers/:id/availability Booking
POST /trainers/:id/book Booking
GET /my-bookings/summary Bookings overview
GET /my-bookings/sessions Bookings list
GET /live/schedule Live classes
GET /live/my-schedule My live schedule
POST /live/schedule/:classId Add to schedule
DELETE /live/schedule/:classId Remove from schedule
POST /food-scanner/scan-food Food scanning
POST /ai/generate-workout-plan AI workout
POST /ai/generate-nutrition-plan AI nutrition
POST /ai/generate-class-plan AI class plan

# Notes on /content/* vs /classes/*

The backend exposes two route groups that serve similar content:

Route Group Auth Scoping Best For
/content/* API key + bearer Filtered by client's assigned categories Authenticated browsing (home, discover)
/classes/* API key only Filtered by client's assigned categories Pre-auth browsing, simpler calls

Both return client-scoped content. Use /content/* when the user is logged in (richer features like "continue watching"). Use /classes/* for simpler listing when bearer token is unavailable.


# ImageKit URL Transformations

ImageKit provides real-time image transformations via URL parameters. The mobile app uses these to request properly sized and cropped images from the CDN, avoiding layout issues like cropped heads or poorly framed thumbnails.

# URL Format

ImageKit URLs follow this pattern:

https://ik.imagekit.io/{imagekit_id}/path/to/image.jpg

Transformations are inserted as a path segment using tr: notation:

https://ik.imagekit.io/{imagekit_id}/tr:{transforms}/path/to/image.jpg

The image is transformed on-the-fly by ImageKit's CDN and cached automatically.

# Transformation Parameters

Parameter Description Example
w-{px} Width in pixels w-320
h-{px} Height in pixels h-400
fo-face Focus on detected face(s) when cropping fo-face
fo-auto Auto-detect the most important content area fo-auto
fo-center Focus on the center (default behaviour) fo-center
fo-top Focus on the top of the image fo-top
c-maintain_ratio Crop while maintaining aspect ratio (default) c-maintain_ratio
c-force Force exact dimensions, may distort c-force
c-at_least Output is at least the requested size c-at_least
c-at_max Output is at most the requested size c-at_max
q-{1-100} JPEG/WebP quality q-80

Multiple parameters are comma-separated: tr:w-320,h-400,fo-face

# Common Presets

Person-centric images where you want to preserve the trainer's face:

Original:  https://ik.imagekit.io/fitgram/fytos/classes/image.jpg
Thumbnail: https://ik.imagekit.io/fitgram/tr:w-320,h-400,fo-face/fytos/classes/image.jpg

Large feature images where the subject may not be a person:

https://ik.imagekit.io/fitgram/tr:w-800,h-400,fo-auto/fytos/classes/image.jpg

Small circular avatars:

https://ik.imagekit.io/fitgram/tr:w-80,h-80,fo-face/fytos/trainers/image.png

Category thumbnails where the subject varies:

https://ik.imagekit.io/fitgram/tr:w-280,h-200,fo-auto/fytos/classes/image.jpg

# Client-Side Usage

The app has a utility at src/utils/imagekit.js that appends transforms to ImageKit URLs automatically:

import { ikThumbnail, ikHero, ikAvatar } from '../utils/imagekit';

// Face-focused thumbnail (320x400, fo-face)
<Image source={{ ERROR }} />

// Hero banner (800x400, fo-auto)
<Image source={{ ERROR }} />

// Small avatar (80x80, fo-face)
<Image source={{ ERROR }} />

// Custom transform
import { ikImage } from '../utils/imagekit';
<Image source={{ ERROR }} />

# Backend Considerations

  • If the backend needs to generate pre-transformed URLs (e.g. for push notifications or emails), use the same tr: path segment format described above.
  • ImageKit caches transformed images at the CDN edge. First request transforms on-the-fly; subsequent requests are served from cache.
  • There is no additional cost per unique transformation, but storage of cached variants counts toward the ImageKit plan.