# Customization Parameters

This section describes all available customization parameters that can be passed to the KinesteX SDK to customize the user experience. Parameters are organized by category, with examples showing which have direct SDK support vs. requiring `customParams`.

**Parameter Passing Methods:**
- **Direct SDK Support**: Pass directly to SDK initialization or view creation methods
- **customParams / customParameters**: Additional parameters passed via a custom parameters object
- **HTML/JS postData**: All parameters passed as flat object via postMessage API

## Required Parameters

These parameters are mandatory for successful SDK initialization.

| Parameter | Type | Description |
|-----------|------|-------------|
| userId | string | Unique identifier for the user. Must be at least 2 characters. Used for tracking progress, analytics, and personalization |
| company | string | Company name associated with the API key. Determines theme defaults and content access |
| key | string | API key for authentication. Required for all API calls and content access |

**SDK Support:** All platforms support these as direct parameters.

**Required Parameters Setup**

_Swift (iOS)_
```swift
// Direct SDK support
let kinestex = KinesteXAIKit(
    apiKey: "YOUR_API_KEY",
    companyName: "YOUR_COMPANY",
    userId: "unique-user-id"
)
```

_Kotlin (Android)_
```kotlin
// Direct SDK support
KinesteXSDK.initialize(
    context = this,
    apiKey = "YOUR_API_KEY",
    companyName = "YOUR_COMPANY",
    userId = "unique-user-id"
)
```

_React Native_
```jsx
// Direct support in postData
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'unique-user-id',
  company: 'YOUR_COMPANY',
};
```

_Flutter_
```dart
// Direct SDK support
await KinesteXAIFramework.initialize(
  apiKey: "YOUR_API_KEY",
  companyName: "YOUR_COMPANY",
  userId: "unique-user-id",
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "unique-user-id",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
};
```

_React (TypeScript)_
```tsx
// Direct support in postData
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'unique-user-id',
  company: 'YOUR_COMPANY',
};
```

## User Profile

Parameters that define user characteristics for personalized content and recommendations.

| Parameter | Type | Description | Effect |
|-----------|------|-------------|--------|
| age | number | User's age in years | Affects workout intensity recommendations and exercise selection |
| gender | string | User's gender (male, female, other) | Affects BMI calculations and content personalization |
| height | number | User's height (in cm or inches based on locale) | Used for BMI calculation and exercise calibration |
| weight | number | User's weight (in kg or lbs based on locale) | Used for BMI calculation and calorie estimations |
| fitness_level | string | User's fitness level | Determines workout difficulty and progression |
| lifestyle | string | User's lifestyle type (e.g., sedentary, active) | Affects personalized plan recommendations |
| body_parts | string[] | Target body parts for workouts | Filters and prioritizes exercises targeting specific areas |
| plan_type | string | Type of workout plan | Determines the structure and focus of generated plans |

**SDK Support:** Most platforms have direct support via UserDetails object or postData fields.

**User Profile Configuration**

_Swift (iOS)_
```swift
// Direct SDK support via UserDetails
let user = UserDetails(
    age: 30,
    height: 180,
    weight: 75,
    gender: .Male,
    lifestyle: .Active
)

kinestex.createView(
    user: user,
    // ... other params
)
```

_Kotlin (Android)_
```kotlin
// Direct SDK support via UserDetails
val userDetails = UserDetails(
    age = 30,
    height = 180,
    weight = 75,
    gender = Gender.MALE,
    lifestyle = Lifestyle.ACTIVE
)

KinesteXSDK.createView(
    user = userDetails,
    // ... other params
)
```

_React Native_
```jsx
// Direct support in postData
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  // User profile - direct support
  age: 30,
  height: 180, // cm
  weight: 75, // kg
  gender: 'Male',
  lifestyle: Lifestyle.Active,
};
```

_Flutter_
```dart
// Direct SDK support via UserDetails
final userDetails = UserDetails(
  age: 30,
  height: 180,
  weight: 75,
  gender: Gender.Male,
  lifestyle: Lifestyle.Active,
);

KinesteXAIFramework.createMainView( // or any other create*View method
  user: userDetails,
  // ... other params
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  // User profile
  age: 30,
  height: 180,
  weight: 75,
  gender: "Male",
  lifestyle: "active",
};
```

_React (TypeScript)_
```tsx
// Direct support in postData
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  // User profile - direct support
  age: 30,
  height: 180, // cm
  weight: 75, // kg
  gender: 'Male',
  lifestyle: Lifestyle.Active,
};
```

## Theme & Appearance

Control the visual appearance of the application.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| style | "dark" or "light" | "dark" | Applies style to the UI | Changes the entire UI color scheme to dark or light mode |
| themeName | string | Company name | Custom theme identifier | Loads a specific theme configuration (e.g., branded themes) |

**Note:** Theme can also be set via URL parameter `?style=dark` or `?style=light`

**SDK Support:**
- **Swift:** Direct support via `IStyle` class passed to view creation methods (hex values with #)
- **Flutter:** Direct support via `IStyle` class passed to view creation methods
- **Kotlin:** Direct support via `IStyle` data class passed to view creation methods (hex values without #)
- **React Native/React:** Direct support via `style` object in postData
- **HTML/JS:** Direct in postData object

**Theme Configuration**

_Swift (iOS)_
```swift
// Direct SDK support via IStyle class
let customStyle = IStyle(
    style: "light",
    themeName: "CustomBrand"
)

kinestex.createWorkoutView(
    workout: "Fitness Lite",
    user: user,
    style: customStyle,
    isLoading: $isLoading,
    onMessageReceived: { /* ... */ }
)
```

_Kotlin (Android)_
```kotlin
// Direct SDK support via IStyle class
KinesteXSDK.createWorkoutView(
    context = this,
    workoutName = "Fitness Lite",
    style = IStyle(
        style = "light",
        themeName = "Your Theme Name from Admin Dashboard (default company name)"
    ),
    isLoading = viewModel.isLoading,
    onMessageReceived = { message ->
        handleWebViewMessage(message)
    },
    permissionHandler = this
)
```

_React Native_
```jsx
// Direct support via style object
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  style: {
    style: 'light', // 'dark' or 'light'
    loadingBackgroundColor: 'FFFFFF', // hex without #
  },
  customParameters: {
    themeName: 'CustomBrand', // via customParameters
  },
};
```

_Flutter_
```dart
// Direct SDK support via IStyle class
KinesteXAIFramework.createWorkoutView(
  workoutName: "Fitness Lite",
  isShowKinestex: showKinesteX,
  isLoading: ValueNotifier<bool>(false),
  style: IStyle(
    style: 'light', // 'dark' or 'light'
    themeName: 'CustomBrand',
  ),
  onMessageReceived: (message) {
    handleWebViewMessage(message);
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  style: "light",
  themeName: "CustomBrand",
};
```

_React (TypeScript)_
```tsx
// Direct support via style object
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  style: {
    style: 'light', // 'dark' or 'light'
    loadingBackgroundColor: 'FFFFFF', // hex without #
  },
  customParameters: {
    themeName: 'CustomBrand', // via customParameters
  },
};
```

## Language & Localization

Configure the language for all UI text, voice prompts, and content.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| language | string | "en" | Language code for localization |
| voiceActor | string | - | Specific voice actor for audio feedback |
| content_gender | string | - | Gender preference for content/instructors shown |

**Supported Languages:**

| Code | Language | RTL Support |
|------|----------|-------------|
| en | English | No |
| es | Spanish | No |
| fr | French | No |
| de | German | No |
| nl | Dutch | No |
| it | Italian | No |
| pt | Portuguese | No |
| ru | Russian | No |
| ar | Arabic | Yes |
| he | Hebrew | Yes |
| hi | Hindi | No |
| bn | Bengali | No |
| id | Indonesian | No |
| da | Danish | No |
| el | Greek | No |
| zh | Chinese (Simplified) | No |
| uz | Uzbek | No |

**SDK Support:** Requires customParams on most platforms.

**Language Configuration**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "language": "es",
        "content_gender": "female"
    ],
    // ... other params
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "language" to "es",
        "content_gender" to "female"
    ),
    // ... other params
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    language: 'es',
    content_gender: 'female',
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "language": "es",
    "content_gender": "female",
  },
  // ... other params
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  language: "es",
  content_gender: "female",
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    language: 'es',
    content_gender: 'female',
  },
};
```

## Workout Configuration

Parameters for configuring workout behavior and progression.

| Parameter | Type | Description | Effect |
|-----------|------|-------------|--------|
| planC | string | Plan configuration identifier | Specifies which workout plan to load |
| exercises | string[] | Array of exercise identifiers | Defines the specific exercises to include in a session |
| currentExercise | string | Current exercise identifier | Sets the active exercise for camera component |
| completed_exercises | string[] | Previously completed exercises | Allows resuming a workout from a specific point |
| start_from_exercise | string | Exercise to start from | Skips to a specific exercise in the workout |
| start_from_rest | boolean | Start from rest period | If true, begins at rest screen before the specified exercise |
| resetPlanProgress | boolean | Reset all plan progress | Clears all saved progress for the user's plans |
| on_start_url | string | URL to call on workout start | Webhook URL triggered when workout begins |

**Note:** Exercise IDs can be retrieved from the [Content API](/docs/content-api).

**Workout Configuration**

_Swift (iOS)_
```swift
// Direct support for some, customParams for others
kinestex.createCameraView(
    exercises: ["Squats", "Lunges", "Pushups"], // direct
    currentExercise: $currentExercise, // direct
    customParams: [
        "start_from_exercise": "Lunges",
        "start_from_rest": true,
        "resetPlanProgress": false
    ]
)
```

_Kotlin (Android)_
```kotlin
// Direct support for some, customParams for others
KinesteXSDK.createCameraComponent(
    exercises = listOf("Squats", "Lunges", "Pushups"), // direct
    currentExercise = "Squats", // direct
    customParams = mutableMapOf(
        "start_from_exercise" to "Lunges",
        "start_from_rest" to true
    )
)
```

_React Native_
```jsx
// Direct support in postData
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  // Direct support
  exercises: ['Squats', 'Lunges', 'Pushups'],
  currentExercise: 'Squats',
  // Via customParameters
  customParameters: {
    start_from_exercise: 'Lunges',
    start_from_rest: true,
    resetPlanProgress: false,
  },
};
```

_Flutter_
```dart
// Direct support for some, customParams for others
KinesteXAIFramework.createCameraComponent(
  exercises: ["Squats", "Lunges", "Pushups"], // direct
  currentExercise: "Squats", // direct
  customParams: {
    "start_from_exercise": "Lunges",
    "start_from_rest": true,
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  exercises: ["Squats", "Lunges", "Pushups"],
  currentExercise: "Squats",
  start_from_exercise: "Lunges",
  start_from_rest: true,
  resetPlanProgress: false,
};
```

_React (TypeScript)_
```tsx
// Direct support in postData
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  // Direct support
  exercises: ['Squats', 'Lunges', 'Pushups'],
  currentExercise: 'Squats',
  // Via customParameters
  customParameters: {
    start_from_exercise: 'Lunges',
    start_from_rest: true,
  },
};
```

## Camera & Pose Detection

Fine-tune the camera and pose detection system.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| shouldAskCamera | boolean | true | Prompt for camera permission | Shows camera permission dialog before starting |
| shouldShowCameraSelector | boolean | false | Show camera selection UI | Allows user to choose between available cameras |
| shouldShowOpenCameraSettings | boolean | false | Show settings button | Displays button to open device camera settings |
| cameraId | string | - | Specific camera device ID | Forces use of a specific camera |
| cameraLabel | string | - | Camera label for display | Shows custom label for the selected camera |
| minPoseDetectionConfidence | number | 0.5 | Minimum detection confidence (0-1) | Lower values detect poses more easily but may be less accurate |
| minTrackingConfidence | number | 0.5 | Minimum tracking confidence (0-1) | Affects how persistently poses are tracked between frames |
| minPosePresenceConfidence | number | 0.5 | Minimum presence confidence (0-1) | Threshold for determining if a person is in frame |
| mediapipeModel | "full" "heavy" "light" | "full" | MediaPipe model variant | light: Faster, less accurate. full: Balanced. heavy: Most accurate, slower |
| defaultDelegate | "GPU" "CPU" | Auto | Processing delegate | Forces GPU or CPU processing for pose detection |
| landmarkColor | string | "#14FF00" | Pose landmark color | Changes the color of skeleton overlay (hex color) |
| showSilhouette | boolean | true | Show body silhouette | Displays silhouette guide overlay during exercises |
| includePoseData | boolean | - | Include raw pose data | Sends pose landmark data in postMessage events |
| includePoseBorders | boolean | true | Show pose boundary guides | Displays borders indicating optimal pose positioning |
| includeRealtimeAccuracy | boolean | - | Send real-time accuracy | Broadcasts accuracy scores in real time via postMessage |
| videoFit | "contain" | "cover" | Camera feed display mode | When set to "contain", shows the full camera frame instead of zooming in to fill the area. Useful for maximizing available space for motion tracking |

**Note:** `defaultDelegate` can also be set via URL parameter `?delegate=GPU` or `?delegate=CPU`

**Camera & Pose Detection Settings**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createCameraView(
    exercises: exerciseList,
    currentExercise: $currentExercise,
    customParams: [
        "landmarkColor": "#FF5500",
        "showSilhouette": true,
        "mediapipeModel": "heavy",
        "defaultDelegate": "GPU",
        "includePoseData": true,
        "includeRealtimeAccuracy": true,
        "shouldShowCameraSelector": true,
        "videoFit": "contain" // show full camera frame
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createCameraComponent(
    exercises = exerciseList,
    currentExercise = "Squats",
    customParams = mutableMapOf(
        "landmarkColor" to "#FF5500",
        "showSilhouette" to true,
        "mediapipeModel" to "heavy",
        "defaultDelegate" to "GPU",
        "includePoseData" to true,
        "includeRealtimeAccuracy" to true,
        "videoFit" to "contain" // show full camera frame
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  exercises: ['Squats', 'Lunges'],
  currentExercise: 'Squats',
  customParameters: {
    landmarkColor: '#FF5500',
    showSilhouette: true,
    mediapipeModel: 'heavy',
    defaultDelegate: 'GPU',
    includePoseData: true,
    includeRealtimeAccuracy: true,
    shouldShowCameraSelector: true,
    videoFit: 'contain', // show full camera frame
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createCameraComponent(
  exercises: ["Squats", "Lunges"],
  currentExercise: "Squats",
  customParams: {
    "landmarkColor": "#FF5500",
    "showSilhouette": true,
    "mediapipeModel": "heavy",
    "defaultDelegate": "GPU",
    "includePoseData": true,
    "includeRealtimeAccuracy": true,
    "videoFit": "contain", // show full camera frame
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  exercises: ["Squats", "Lunges"],
  currentExercise: "Squats",
  landmarkColor: "#FF5500",
  showSilhouette: true,
  mediapipeModel: "heavy",
  defaultDelegate: "GPU",
  includePoseData: true,
  includeRealtimeAccuracy: true,
  shouldShowCameraSelector: true,
  videoFit: "contain", // show full camera frame
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  exercises: ['Squats', 'Lunges'],
  currentExercise: 'Squats',
  customParameters: {
    landmarkColor: '#FF5500',
    showSilhouette: true,
    mediapipeModel: 'heavy',
    defaultDelegate: 'GPU',
    includePoseData: true,
    includeRealtimeAccuracy: true,
    videoFit: 'contain', // show full camera frame
  },
};
```

## UI Controls

Control visibility and behavior of UI elements.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| isHideHeaderMain | boolean | false | Hide main header | Removes the top navigation header |
| hideFeelingDialog | boolean | false | Hide feeling dialog | Skips the post-workout feeling prompt |
| hideMusicIcon | boolean | - | Hide music control | Removes the music toggle button |
| hideMistakesFeedback | boolean | - | Hide mistake feedback | Disables on-screen form correction prompts |
| showModalWarmUp | boolean | - | Show warm-up modal | Displays warm-up recommendation before workout |
| showSettings | boolean | - | Show settings button | Displays settings access in the UI |
| isDrawingPose | boolean | - | Enable pose drawing | Activates skeleton visualization on camera feed |
| isOnboarding | boolean | true | Enable onboarding flow | Shows/hides the initial onboarding experience |
| hideCompletionOverlay | boolean | false | Hide workout completion overlay | Skips the workout completion summary screen shown at the end of a workout |
| preventGestureControl | boolean | false | Disable gesture control | Prevents users from pausing and resuming workouts using hand gestures |
| disableGuide | boolean | false | Disable onboarding guide | Suppresses the guide entirely for embedded contexts where onboarding isn't needed |
| disableCookies | boolean | false | Disable all cookies | Automatically declines all cookies, hides the cookie management button and consent link. Useful for GDPR compliance or privacy-sensitive environments |
| hideStatisticsHeader | boolean | false | Hide statistics header | Hides the header on the workout statistics/results screen |
| nativeParentScroll | boolean | false | Native scroll delegation | Delegates scroll behavior of the statistics screen to the native parent container instead of using internal scroll. Enable if your native app manages its own scrolling |
| immediateShowSkip | boolean | false | Instant Skip button | Shows the Skip button on the camera frame-positioning (silhouette) screen immediately with a themed background, instead of fading it in after ~5 seconds. Has no effect if Skip is disabled for the screen |
| hideOtherGender | boolean | false | Hide third gender option | Removes the "I'd rather not say" choice from the plan-onboarding gender step and the AI Trainer profile pickers, leaving only Male / Female. Also accepted as a URL query param |
| exitUrl | string | - | Redirect on exit | For standalone/link integrations with no host app: when the session ends, the browser is redirected to this URL after the exit event is posted. Accepts https:// URLs or app deep links (e.g. `clientapp://home`); script-executing schemes are rejected for security |

**UI Controls Configuration**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "isHideHeaderMain": true,
        "hideFeelingDialog": true,
        "hideMusicIcon": true,
        "hideMistakesFeedback": false,
        "isOnboarding": false,
        "hideCompletionOverlay": true,
        "preventGestureControl": true,
        "disableGuide": true,
        "disableCookies": true,
        "hideStatisticsHeader": false,
        "nativeParentScroll": false
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "isHideHeaderMain" to true,
        "hideFeelingDialog" to true,
        "hideMusicIcon" to true,
        "hideMistakesFeedback" to false,
        "isOnboarding" to false,
        "hideCompletionOverlay" to true,
        "preventGestureControl" to true,
        "disableGuide" to true,
        "disableCookies" to true,
        "hideStatisticsHeader" to false,
        "nativeParentScroll" to false
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    isHideHeaderMain: true,
    hideFeelingDialog: true,
    hideMusicIcon: true,
    hideMistakesFeedback: false,
    isOnboarding: false,
    hideCompletionOverlay: true,
    preventGestureControl: true,
    disableGuide: true,
    disableCookies: true,
    hideStatisticsHeader: false,
    nativeParentScroll: false,
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "isHideHeaderMain": true,
    "hideFeelingDialog": true,
    "hideMusicIcon": true,
    "hideMistakesFeedback": false,
    "isOnboarding": false,
    "hideCompletionOverlay": true,
    "preventGestureControl": true,
    "disableGuide": true,
    "disableCookies": true,
    "hideStatisticsHeader": false,
    "nativeParentScroll": false,
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  isHideHeaderMain: true,
  hideFeelingDialog: true,
  hideMusicIcon: true,
  hideMistakesFeedback: false,
  isOnboarding: false,
  hideCompletionOverlay: true,
  preventGestureControl: true,
  disableGuide: true,
  disableCookies: true,
  hideStatisticsHeader: false,
  nativeParentScroll: false,
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    isHideHeaderMain: true,
    hideFeelingDialog: true,
    hideMusicIcon: true,
    hideMistakesFeedback: false,
    isOnboarding: false,
    hideCompletionOverlay: true,
    preventGestureControl: true,
    disableGuide: true,
    disableCookies: true,
    hideStatisticsHeader: false,
    nativeParentScroll: false,
  },
};
```

## Challenge Mode

Configure challenge-specific parameters for direct challenge launches.

| Parameter | Type | Description | Effect |
|-----------|------|-------------|--------|
| exercise | string | Challenge exercise identifier | Specifies which exercise to use for the challenge |
| countdown | number | Countdown duration in seconds | Sets the preparation countdown before challenge starts |
| reps | number | Target repetition count | Sets the goal number of reps for the challenge |
| gameTotalRounds | number | Total number of rounds (Color Chase only) | Controls how many rounds the Color Chase game lasts. Default is 10. Rounds beyond 10 are procedurally generated with increasing difficulty |

**Balloon Pop — rounds mode (special case):**

When you launch the **Balloon Pop** game and pass BOTH `reps` and `countdown`, the game switches from the default 30-second timer mode into a **rounds mode**:

- `reps` = number of rounds
- `countdown` = number of balloons spawned per round

The game ends after all rounds are completed. The HUD shows a round counter instead of a timer, and the difficulty stage indicator is hidden.

| Configuration | Behavior |
|---------------|----------|
| `reps: 4, countdown: 2` | 4 rounds × 2 balloons = 8 total pops |
| `reps: 3, countdown: 3` | 3 rounds × 3 balloons = 9 total pops |
| `reps: 6, countdown: 1` | 6 rounds × 1 balloon = 6 total pops (very easy) |
| `reps` not provided | Default timer mode (30s, escalating difficulty) |

**Challenge Mode Configuration**

_Swift (iOS)_
```swift
// Via customParams for challenge integration
kinestex.createChallengeView(
    exercise: exerciseId, // direct
    customParams: [
        "countdown": 5,
        "reps": 20,
        // Color Chase only:
        "gameTotalRounds": 15
        // Balloon Pop rounds-mode example:
        // "reps": 4, "countdown": 2  → 4 rounds × 2 balloons
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams for challenge integration
KinesteXSDK.createChallengeView(
    exercise = exerciseId, // direct
    customParams = mutableMapOf(
        "countdown" to 5,
        "reps" to 20,
        // Color Chase only:
        "gameTotalRounds" to 15
        // Balloon Pop rounds-mode example:
        // "reps" to 4, "countdown" to 2  → 4 rounds × 2 balloons
    )
)
```

_React Native_
```jsx
// Via postData for challenge integration
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    exercise: 'exerciseId',
    countdown: 5,
    reps: 20,
    // Color Chase only:
    gameTotalRounds: 15,
    // Balloon Pop rounds-mode example:
    // reps: 4, countdown: 2  → 4 rounds × 2 balloons
  },
};
```

_Flutter_
```dart
// exercise and countdown are direct params; the rest via customParams
KinesteXAIFramework.createChallengeView(
  exercise: exerciseId, // direct
  countdown: 5, // direct (required)
  customParams: {
    "reps": 20,
    // Color Chase only:
    "gameTotalRounds": 15,
    // Balloon Pop rounds-mode example:
    // "reps": 4, "countdown": 2  → 4 rounds × 2 balloons
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  exercise: exerciseId,
  countdown: 5,
  reps: 20,
  // Color Chase only:
  gameTotalRounds: 15,
  // Balloon Pop rounds-mode example:
  // reps: 4, countdown: 2  → 4 rounds × 2 balloons
};
```

_React (TypeScript)_
```tsx
// Via postData for challenge integration
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    exercise: 'exerciseId',
    countdown: 5,
    reps: 20,
    // Color Chase only:
    gameTotalRounds: 15,
    // Balloon Pop rounds-mode example:
    // reps: 4, countdown: 2  → 4 rounds × 2 balloons
  },
};
```

## Complete UX Customization

Customize the Complete UX (Main View) home page experience.

| Parameter | Type | Description | Effect |
|-----------|------|-------------|--------|
| challenges_home | array | Custom challenges/games for home screen | Defines the two challenge/game options shown on the Complete UX home page |

**challenges_home Configuration:**

The `challenges_home` parameter allows you to customize the challenges and games displayed on the home screen of the Complete UX experience. You must pass exactly **2 objects** in the array.

**Array Object Structure:**
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| id | string | Yes | Exercise ID for challenges, or game ID for games |
| name | string | Yes | Display name shown in the UI |
| isGame | boolean | Yes | Set to `true` for games, `false` for challenges |

**Available Games:**
- `balloonpop` - Balloon Pop game
- `aliensquatshooter` - Alien Squat Shooter game
- `colorchase` - Color Chase game

**Combination Options:**
- Two challenges (both with `isGame: false`)
- Two games (both with `isGame: true`)
- One challenge + one game (mixed `isGame` values)

**Note:** You can pass any exercise ID as a challenge. When specifying a game, ensure `isGame` is set to `true`.

**Complete UX Home Page Customization**

_Swift (iOS)_
```swift
// Customize challenges on Complete UX home page
let exerciseId = "your-exercise-id" // Get from Content API
let exerciseName = "Your Exercise Name"

kinestex.createMainView(
    customParams: [
        "challenges_home": [
            ["id": exerciseId, "name": exerciseName, "isGame": false],
            ["id": "balloonpop", "name": "Balloon Pop", "isGame": true]
        ]
    ]
)
```

_Kotlin (Android)_
```kotlin
// Customize challenges on Complete UX home page
val exerciseId = "your-exercise-id" // Get from Content API
val exerciseName = "Your Exercise Name"

KinesteXSDK.createMainView(
    customParams = mutableMapOf(
        "challenges_home" to listOf(
            mapOf("id" to exerciseId, "name" to exerciseName, "isGame" to false),
            mapOf("id" to "balloonpop", "name" to "Balloon Pop", "isGame" to true)
        )
    )
)
```

_React Native_
```jsx
// Customize challenges on Complete UX home page
const exerciseId = 'your-exercise-id'; // Get from Content API
const exerciseName = 'Your Exercise Name';

const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    challenges_home: [
      { id: exerciseId, name: exerciseName, isGame: false },
      { id: 'balloonpop', name: 'Balloon Pop', isGame: true },
    ],
  },
};
```

_Flutter_
```dart
// Customize challenges on Complete UX home page
final exerciseId = "your-exercise-id"; // Get from Content API
final exerciseName = "Your Exercise Name";

KinesteXAIFramework.createMainView(
  customParams: {
    "challenges_home": [
      {"id": exerciseId, "name": exerciseName, "isGame": false},
      {"id": "balloonpop", "name": "Balloon Pop", "isGame": true},
    ],
  },
);
```

_HTML / JavaScript_
```html
// Customize challenges on Complete UX home page
const exerciseId = "your-exercise-id"; // Get from Content API
const exerciseName = "Your Exercise Name";

const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  challenges_home: [
    { id: exerciseId, name: exerciseName, isGame: false },
    { id: "balloonpop", name: "Balloon Pop", isGame: true },
  ],
};
```

_React (TypeScript)_
```tsx
// Customize challenges on Complete UX home page
const exerciseId = 'your-exercise-id'; // Get from Content API
const exerciseName = 'Your Exercise Name';

const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    challenges_home: [
      { id: exerciseId, name: exerciseName, isGame: false },
      { id: 'balloonpop', name: 'Balloon Pop', isGame: true },
    ],
  },
};
```

## Leaderboard

Configure leaderboard functionality.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| showLeaderboard | boolean | - | Show leaderboard UI | Enables/disables leaderboard visibility |
| username | string | - | Display name for leaderboard | Sets the user's name shown on leaderboards |
| autoSubmitLeaderboard | boolean | false | Silent leaderboard submission (Challenge only) | When true, Challenge results are submitted to the leaderboard without showing the submission modal. The display name is read from the previously stored `leaderboard_username` (or falls back to the user ID) |

**Note:** Username is automatically saved to localStorage for future sessions.

**`autoSubmitLeaderboard` use case:** Use this only for Challenge integrations where you want every completion silently posted to the leaderboard (e.g., when your host app already manages display names and doesn't want a second prompt). Leave it unset (or `false`) to keep the standard modal-based flow.

**Leaderboard Configuration**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "showLeaderboard": true,
        "username": "FitnessPro123",
        "autoSubmitLeaderboard": true // Challenge-only: skip submit modal
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "showLeaderboard" to true,
        "username" to "FitnessPro123",
        "autoSubmitLeaderboard" to true // Challenge-only: skip submit modal
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    showLeaderboard: true,
    username: 'FitnessPro123',
    autoSubmitLeaderboard: true, // Challenge-only: skip submit modal
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "showLeaderboard": true,
    "username": "FitnessPro123",
    "autoSubmitLeaderboard": true, // Challenge-only: skip submit modal
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  showLeaderboard: true,
  username: "FitnessPro123",
  autoSubmitLeaderboard: true, // Challenge-only: skip submit modal
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    showLeaderboard: true,
    username: 'FitnessPro123',
    autoSubmitLeaderboard: true, // Challenge-only: skip submit modal
  },
};
```

## Loading Screen

Customize the loading screen appearance (includes native overlay color that is displayed during initial loading phase).

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| loadingStickmanColor | string | Theme default | Stickman animation color | Changes the color of the loading animation character |
| loadingBackgroundColor | string | Theme default | Background color | Sets the loading screen background color |
| loadingTextColor | string | Theme default | Text color | Sets the color of loading text and messages |

**SDK Support:**
- **Swift:** Direct support via `IStyle` class (hex values with #)
- **Flutter:** Direct support via `IStyle` class (hex values without #)
- **Kotlin:** Direct support via `IStyle` data class (hex values without #)
- **React Native/React:** Direct support via `style` object (hex values without #)
- **HTML/JS:** Direct in postData object

**Native Loading Overlay (Swift):**

The SDK displays a native overlay on top of the WebView until content is fully loaded, preventing users from seeing a blank screen.

- Overlay automatically hides when `KinestexLoaded` message is received
- Overlay color priority:
  1. Uses `loadingBackgroundColor` if set (hex color with #)
  2. Uses white (#FFFFFF) if `style = "light"`
  3. Uses black (#000000) if `style = "dark"` (default)

**Style Properties:**

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| style | String? | "dark" | Base theme style ("dark" or "light") |
| themeName | String? | null | Custom theme name |
| loadingStickmanColor | String? | null | Color for the loading animation stickman (hex without #) |
| loadingBackgroundColor | String? | null | Background color during loading (hex without #) |
| loadingTextColor | String? | null | Text color during loading (hex without #) |

**Loading Screen Customization**

_Swift (iOS)_
```swift
// Direct SDK support via IStyle class
let customStyle = IStyle(
    style: "dark",
    loadingBackgroundColor: "#1A1A2E",
    loadingStickmanColor: "#FF6B00",
    loadingTextColor: "#FFFFFF"
)

kinestex.createWorkoutView(
    workout: "Fitness Lite",
    user: user,
    style: customStyle,
    isLoading: $isLoading,
    onMessageReceived: { /* ... */ }
)
```

_Kotlin (Android)_
```kotlin
// Direct SDK support via IStyle class
KinesteXSDK.createWorkoutView(
    context = this,
    workoutName = "Fitness Lite",
    style = IStyle(
        style = "dark",
        loadingBackgroundColor = "1A1A2E", // hex value without #
        loadingStickmanColor = "FF6B00",
        loadingTextColor = "FFFFFF"
    ),
    isLoading = viewModel.isLoading,
    onMessageReceived = { message ->
        handleWebViewMessage(message)
    },
    permissionHandler = this
)
```

_React Native_
```jsx
// Direct support via style object
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  style: {
    style: 'dark',
    loadingBackgroundColor: '1A1A2E', // hex without #
    loadingTextColor: 'FFFFFF',
  },
  customParameters: {
    loadingStickmanColor: '#FF6B00', // via customParams
  },
};
```

_Flutter_
```dart
// Direct SDK support via IStyle class
KinesteXAIFramework.createWorkoutView(
  workoutName: "Fitness Lite",
  isShowKinestex: showKinesteX,
  isLoading: ValueNotifier<bool>(false),
  style: IStyle(
    style: 'dark',
    loadingBackgroundColor: '1A1A2E', // hex without #
    loadingStickmanColor: 'FF6B00',
    loadingTextColor: 'FFFFFF',
  ),
  onMessageReceived: (message) {
    handleWebViewMessage(message);
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  loadingStickmanColor: "#FF6B00",
  loadingBackgroundColor: "#1A1A2E",
  loadingTextColor: "#FFFFFF",
};
```

_React (TypeScript)_
```tsx
// Direct support via style object
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  style: {
    style: 'dark',
    loadingBackgroundColor: '1A1A2E', // hex without #
    loadingTextColor: 'FFFFFF',
  },
  customParameters: {
    loadingStickmanColor: '#FF6B00', // via customParams
  },
};
```

## Motion Tracking Settings

Control AI-powered motion tracking behavior.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| motionTrackingSettingOn | boolean | - | Show motion tracking toggle | Displays the AI tracking on/off setting |
| motionTrackingEnabled | boolean | - | Enable motion tracking | Session-level override for AI tracking (clears localStorage preference) |
| motionDataEnabled | boolean | true | Record per-frame motion data | When set to `false`, the SDK does NOT collect per-frame pose landmark data during the session. Session replay will be empty for affected sessions, but all other workout functionality is unaffected |

**Note:** When `motionTrackingEnabled` is explicitly set, it clears any saved user preference and uses the provided value for the session.

**`motionDataEnabled` — only use this if you know why it's necessary.** This flag exists for memory-constrained scenarios (e.g., long workouts with many unique exercise videos on older iOS devices where peak memory pressure can cause the WebView to crash). Disabling motion data reduces memory usage at the cost of losing session replay. The recorder state resets on every verification, so the flag does not leak across sessions. Default behavior is unchanged if you omit the parameter.

**Motion Tracking Settings**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "motionTrackingSettingOn": true,
        "motionTrackingEnabled": true,
        "motionDataEnabled": false // Only set when memory-constrained
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "motionTrackingSettingOn" to true,
        "motionTrackingEnabled" to true,
        "motionDataEnabled" to false // Only set when memory-constrained
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    motionTrackingSettingOn: true,
    motionTrackingEnabled: true,
    motionDataEnabled: false, // Only set when memory-constrained
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "motionTrackingSettingOn": true,
    "motionTrackingEnabled": true,
    "motionDataEnabled": false, // Only set when memory-constrained
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  motionTrackingSettingOn: true,
  motionTrackingEnabled: true,
  motionDataEnabled: false, // Only set when memory-constrained
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    motionTrackingSettingOn: true,
    motionTrackingEnabled: true,
    motionDataEnabled: false, // Only set when memory-constrained
  },
};
```

## Debug & Development

Parameters for debugging and development purposes.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| showDebugRecording | boolean | false | Show debug recording UI | Displays recording controls for debugging |
| showNetworkDebugTool | boolean | - | Show network debug panel | Displays network request monitoring tool |
| newModelId | string | - | Test model identifier | Loads a specific ML model version for testing |

**Note:** `showDebugRecording` can also be enabled via URL parameter `?debug=true`

**Debug & Development Settings**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "showDebugRecording": true,
        "showNetworkDebugTool": true,
        "newModelId": "pose_model_v2_beta"
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "showDebugRecording" to true,
        "showNetworkDebugTool" to true,
        "newModelId" to "pose_model_v2_beta"
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    showDebugRecording: true,
    showNetworkDebugTool: true,
    newModelId: 'pose_model_v2_beta',
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "showDebugRecording": true,
    "showNetworkDebugTool": true,
    "newModelId": "pose_model_v2_beta",
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  showDebugRecording: true,
  showNetworkDebugTool: true,
  newModelId: "pose_model_v2_beta",
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    showDebugRecording: true,
    showNetworkDebugTool: true,
    newModelId: 'pose_model_v2_beta',
  },
};
```

## Custom Workout

Configure custom workout sequences. For complete custom workout implementation, see [Custom Integration](/docs/integration/custom-integration).

| Parameter | Type | Description | Effect |
|-----------|------|-------------|--------|
| customWorkoutExercises | array | Array of exercise configurations | Defines a custom sequence of exercises with their parameters |
| restSpeeches | string[] | Rest period audio identifiers | Custom audio to play during rest periods |
| currentRestSpeech | string | Current rest speech identifier | Sets the active rest period audio |
| videoURL | string | Custom video URL | URL for custom exercise demonstration video |

**Custom Workout Flow:**
1. Pass `customWorkoutExercises` during initial verification
2. Send `workout_activity_action: "start"` message to begin the workout
3. The system will navigate to the workout flow automatically

**Custom Workout Parameters**

_Swift (iOS)_
```swift
// Via customParams for additional settings
let customExercises = [
    WorkoutSequenceExercise(
        exerciseId: "exercise-id-1",
        reps: 15,
        duration: nil,
        includeRestPeriod: true,
        restDuration: 20
    )
]

kinestex.createCustomWorkoutView(
    customWorkouts: customExercises, // direct
    customParams: [
        "restSpeeches": ["rest_speech_1", "rest_speech_2"],
        "videoURL": "https://example.com/demo.mp4"
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams for additional settings
val customExercises = listOf(
    WorkoutSequenceExercise(
        exerciseId = "exercise-id-1",
        reps = 15,
        duration = null,
        includeRestPeriod = true,
        restDuration = 20
    )
)

KinesteXSDK.createCustomWorkoutView(
    customWorkouts = customExercises, // direct
    customParams = mutableMapOf(
        "restSpeeches" to listOf("rest_speech_1", "rest_speech_2"),
        "videoURL" to "https://example.com/demo.mp4"
    )
)
```

_React Native_
```jsx
// Direct support in postData
const customWorkoutExercises = [
  {
    exerciseId: 'exercise-id-1',
    reps: 15,
    duration: null,
    includeRestPeriod: true,
    restDuration: 20,
  },
];

const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customWorkoutExercises: customWorkoutExercises, // direct
  customParameters: {
    restSpeeches: ['rest_speech_1', 'rest_speech_2'],
    videoURL: 'https://example.com/demo.mp4',
  },
};
```

_Flutter_
```dart
// Via customParams for additional settings
final customExercises = [
  WorkoutSequenceExercise(
    exerciseId: "exercise-id-1",
    reps: 15,
    duration: null,
    includeRestPeriod: true,
    restDuration: 20,
  ),
];

KinesteXAIFramework.createCustomWorkoutView(
  customWorkouts: customExercises, // direct
  customParams: {
    "restSpeeches": ["rest_speech_1", "rest_speech_2"],
    "videoURL": "https://example.com/demo.mp4",
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const customWorkoutExercises = [
  {
    exerciseId: "exercise-id-1",
    reps: 15,
    duration: null,
    includeRestPeriod: true,
    restDuration: 20,
  },
];

const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  customWorkoutExercises: customWorkoutExercises,
  restSpeeches: ["rest_speech_1", "rest_speech_2"],
  videoURL: "https://example.com/demo.mp4",
};
```

_React (TypeScript)_
```tsx
// Direct support in postData
const customWorkoutExercises: WorkoutSequenceExercise[] = [
  {
    exerciseId: 'exercise-id-1',
    reps: 15,
    duration: null,
    includeRestPeriod: true,
    restDuration: 20,
  },
];

const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customWorkoutExercises: customWorkoutExercises, // direct
  customParameters: {
    restSpeeches: ['rest_speech_1', 'rest_speech_2'],
    videoURL: 'https://example.com/demo.mp4',
  },
};
```

## Workout Activity Actions

Control workout state programmatically via postMessage using the `workout_activity_action` property.

| Action | Description |
|--------|-------------|
| pause_workout | Pauses the workout (video, timer, and tracking) |
| resume_workout | Resumes a paused workout |
| mute_workout | Mutes all audio (speech, sounds, and music) |
| unmute_workout | Unmutes all audio |
| mute_speech | Mutes only speech feedback (sounds still play) |
| unmute_speech | Unmutes speech feedback |

**Note:** These actions are sent via postMessage to the KinesteX iframe/webview after the workout has started.

**Workout Activity Actions**

_Swift (iOS)_
```swift
// Send workout activity action using @State binding
// First, declare the state variable and pass it to the view:
// @State var workoutAction: [String: Any]? = nil
// kinestex.createWorkoutView(..., workoutAction: $workoutAction, ...)

// Pause the workout
workoutAction = ["workout_activity_action": "pause_workout"]

// Resume the workout
workoutAction = ["workout_activity_action": "resume_workout"]

// Mute all audio
workoutAction = ["workout_activity_action": "mute_workout"]

// Unmute all audio
workoutAction = ["workout_activity_action": "unmute_workout"]

// Mute only speech (sounds still play)
workoutAction = ["workout_activity_action": "mute_speech"]

// Unmute speech
workoutAction = ["workout_activity_action": "unmute_speech"]
```

_Kotlin (Android)_
```kotlin
// Send workout activity action
// Pause the workout
KinesteXSDK.sendAction("workout_activity_action", "pause_workout")

// Resume the workout
KinesteXSDK.sendAction("workout_activity_action", "resume_workout")

// Mute all audio
KinesteXSDK.sendAction("workout_activity_action", "mute_workout")

// Unmute all audio
KinesteXSDK.sendAction("workout_activity_action", "unmute_workout")

// Mute only speech (sounds still play)
KinesteXSDK.sendAction("workout_activity_action", "mute_speech")

// Unmute speech
KinesteXSDK.sendAction("workout_activity_action", "unmute_speech")
```

_React Native_
```jsx
// Send workout activity action
const kinestexSDKRef = useRef<KinesteXSDKCamera>(null);

// Pause the workout
kinestexSDKRef.current?.sendAction("workout_activity_action", "pause_workout");

// Resume the workout
kinestexSDKRef.current?.sendAction("workout_activity_action", "resume_workout");

// Mute all audio
kinestexSDKRef.current?.sendAction("workout_activity_action", "mute_workout");

// Unmute all audio
kinestexSDKRef.current?.sendAction("workout_activity_action", "unmute_workout");

// Mute only speech (sounds still play)
kinestexSDKRef.current?.sendAction("workout_activity_action", "mute_speech");

// Unmute speech
kinestexSDKRef.current?.sendAction("workout_activity_action", "unmute_speech");
```

_Flutter_
```dart
// Send workout activity action
// Pause the workout
KinesteXAIFramework.sendAction("workout_activity_action", "pause_workout");

// Resume the workout
KinesteXAIFramework.sendAction("workout_activity_action", "resume_workout");

// Mute all audio
KinesteXAIFramework.sendAction("workout_activity_action", "mute_workout");

// Unmute all audio
KinesteXAIFramework.sendAction("workout_activity_action", "unmute_workout");

// Mute only speech (sounds still play)
KinesteXAIFramework.sendAction("workout_activity_action", "mute_speech");

// Unmute speech
KinesteXAIFramework.sendAction("workout_activity_action", "unmute_speech");
```

_HTML / JavaScript_
```html
// Send workout activity action via postMessage
const iframe = document.getElementById('kinestex-iframe');

// Pause the workout
iframe.contentWindow.postMessage({
  workout_activity_action: "pause_workout"
}, "*");

// Resume the workout
iframe.contentWindow.postMessage({
  workout_activity_action: "resume_workout"
}, "*");

// Mute all audio
iframe.contentWindow.postMessage({
  workout_activity_action: "mute_workout"
}, "*");

// Unmute all audio
iframe.contentWindow.postMessage({
  workout_activity_action: "unmute_workout"
}, "*");

// Mute only speech (sounds still play)
iframe.contentWindow.postMessage({
  workout_activity_action: "mute_speech"
}, "*");

// Unmute speech
iframe.contentWindow.postMessage({
  workout_activity_action: "unmute_speech"
}, "*");
```

_React (TypeScript)_
```tsx
// Send workout activity action
import { useRef } from 'react';
import { type KinesteXSDKCamera } from 'kinestex-sdk-react-ts';

const ref = useRef<KinesteXSDKCamera>(null);

// Pause the workout
ref.current?.sendAction("workout_activity_action", "pause_workout");

// Resume the workout
ref.current?.sendAction("workout_activity_action", "resume_workout");

// Mute all audio
ref.current?.sendAction("workout_activity_action", "mute_workout");

// Unmute all audio
ref.current?.sendAction("workout_activity_action", "unmute_workout");

// Mute only speech (sounds still play)
ref.current?.sendAction("workout_activity_action", "mute_speech");

// Unmute speech
ref.current?.sendAction("workout_activity_action", "unmute_speech");
```

## Navigation

Control navigation and routing behavior.

| Parameter | Type | Description | Effect |
|-----------|------|-------------|--------|
| instantRedirect | string | Path to redirect to | Immediately navigates to specified route after verification |

**Note:** Path will be normalized (leading `/` added if missing).

**Navigation Control**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "instantRedirect": "/workout/start"
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "instantRedirect" to "/workout/start"
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    instantRedirect: '/workout/start',
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "instantRedirect": "/workout/start",
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  instantRedirect: "/workout/start",
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    instantRedirect: '/workout/start',
  },
};
```

## Assessment Configuration

Parameters specific to assessment modes (TUG test, balance tests, etc.). For complete assessment data structures, see [Data Points](/docs/data-points).

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| tugMinRequiredSpace | number | 3.2 | Walk distance (meters) | Sets the required walk distance for the TUG and Gait Speed assessments. Reported speeds (`averageSpeedMs_tug`, `averageGaitSpeed`) are derived from this configured distance — TUG uses 2 × the distance (out and back), Gait Speed uses it directly |
| isHorizontalMode | boolean | true | Landscape walking assessments | Runs the TUG and Gait Speed tests in landscape on mobile/tablet, widening the camera's field of view so the test fits a much smaller space. Users get "Rotate your device" prompts; your WebView/activity must allow landscape orientation. Pass `false` to opt out. Also accepted as a URL query param |

**Note:** For balance assessments (semitandemstand, fulltandem, sidebysidestand), the system automatically uses the "heavy" MediaPipe model for better accuracy.

**Assessment Configuration**

_Swift (iOS)_
```swift
// Via customParams for TUG assessment
kinestex.createAssessmentView(
    exercise: "tugtest", // direct
    customParams: [
        "tugMinRequiredSpace": 3
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams for TUG assessment
KinesteXSDK.createAssessmentView(
    exercise = "tugtest", // direct
    customParams = mutableMapOf(
        "tugMinRequiredSpace" to 3
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    exercise: 'tugtest',
    tugMinRequiredSpace: 3,
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createExperienceView(
  experience: "assessment",
  customParams: {
    "exercise": "tugtest",
    "tugMinRequiredSpace": 3,
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  exercise: "tugtest",
  tugMinRequiredSpace: 3,
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    exercise: 'tugtest',
    tugMinRequiredSpace: 3,
  },
};
```

## Audio Configuration

Control audio playback settings.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| enableM4a | boolean | false | Force M4A audio format | Forces the audio system to use M4A format instead of default |
| includePhrases | string[] | all categories | Spoken-phrase allow-list | Restricts spoken coaching cues to the listed categories (core "static" cues always stay on). Omit for all categories including greeting and farewell; pass an explicit list to enable exactly those — e.g. `["greeting", "farewell"]` re-enables the greeting/farewell voice cues for hosts that had them silenced |

**Audio Configuration**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createView(
    customParams: [
        "enableM4a": true
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createView(
    customParams = mutableMapOf(
        "enableM4a" to true
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    enableM4a: true,
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createMainView( // or any other create*View method
  customParams: {
    "enableM4a": true,
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  enableM4a: true,
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    enableM4a: true,
  },
};
```

## Session & Data Saving

Control session saving and data upload behavior.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| shouldSendStats | boolean | false | Enable session saving | When enabled, workout sessions are automatically saved to the backend upon completion — including per-exercise stats, accuracy scores, calories, and motion recording data |

**Session Saving Configuration**

_Swift (iOS)_
```swift
// Via customParams
kinestex.createWorkoutView(
    workout: "Full Body Burn",
    customParams: [
        "shouldSendStats": true
    ]
)
```

_Kotlin (Android)_
```kotlin
// Via customParams
KinesteXSDK.createWorkoutView(
    workoutName = "Full Body Burn",
    customParams = mutableMapOf(
        "shouldSendStats" to true
    )
)
```

_React Native_
```jsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    shouldSendStats: true,
  },
};
```

_Flutter_
```dart
// Via customParams
KinesteXAIFramework.createWorkoutView(
  workoutName: "Full Body Burn",
  customParams: {
    "shouldSendStats": true,
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  shouldSendStats: true,
};
```

_React (TypeScript)_
```tsx
// Via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    shouldSendStats: true,
  },
};
```

## Plan Context

Pass plan progression context so the SDK associates a directly-launched workout with the correct plan. After the workout finishes, the SDK posts `plan_progression_saved` (or `plan_progression_failed` on error). See [Plans & Programs events](/docs/data-points/plans-programs).

| Parameter | Type | Description |
|-----------|------|-------------|
| planId | string | The ID of the plan the workout belongs to |
| planType | string | Type of plan (e.g., goal-based plan type, or "personalized") |
| progressWorkoutId | string | The plan-day workout ID used to record progression |

**When to use:** Only when you launch a workout **directly** via the SDK (not through the in-app plan UI) and want it to count toward plan progression. The in-app plan flow handles this automatically — you don't need to pass these fields if the user navigates from the plan dashboard.

**Note:** If you launch a workout without these fields, it is treated as a standalone session and won't update plan progression.

**Plan Context Configuration**

_Swift (iOS)_
```swift
// Pass plan context when launching a workout directly
kinestex.createWorkoutView(
    workout: "Day 3 Workout",
    customParams: [
        "planId": "plan_abc123",
        "planType": "personalized",
        "progressWorkoutId": "plan_day_3"
    ]
)
```

_Kotlin (Android)_
```kotlin
// Pass plan context when launching a workout directly
KinesteXSDK.createWorkoutView(
    workoutName = "Day 3 Workout",
    customParams = mutableMapOf(
        "planId" to "plan_abc123",
        "planType" to "personalized",
        "progressWorkoutId" to "plan_day_3"
    )
)
```

_React Native_
```jsx
// Pass plan context via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    planId: 'plan_abc123',
    planType: 'personalized',
    progressWorkoutId: 'plan_day_3',
  },
};
```

_Flutter_
```dart
// Pass plan context via customParams
KinesteXAIFramework.createWorkoutView(
  workoutName: "Day 3 Workout",
  customParams: {
    "planId": "plan_abc123",
    "planType": "personalized",
    "progressWorkoutId": "plan_day_3",
  },
);
```

_HTML / JavaScript_
```html
// Direct in postData object
const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  planId: "plan_abc123",
  planType: "personalized",
  progressWorkoutId: "plan_day_3",
};
```

_React (TypeScript)_
```tsx
// Pass plan context via customParameters
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    planId: 'plan_abc123',
    planType: 'personalized',
    progressWorkoutId: 'plan_day_3',
  },
};
```

## Plan Onboarding Prefill

Pre-fill or skip onboarding survey questions for personalized plans. All fields are optional — only provided fields will be pre-filled and their corresponding screens will be skipped. If all answers are provided for a goal-based plan, the user goes straight to results.

**Availability:** This parameter is used with `createCustomComponentView` (Swift, Kotlin, Flutter) or the `CUSTOM_COMPONENT` integration option (React Native) with `route: "plan-onboarding"`.

| Parameter | Type | Description |
|-----------|------|-------------|
| route | string | Must be `"plan-onboarding"` for this feature to work |
| planOnboardingPrefill | object | Object containing prefill values for onboarding survey |
| planOnboardingPrefill.goal | string | User's fitness goal (e.g., "weight_loss") |
| planOnboardingPrefill.healthIssues | string[] | List of health issues (e.g., ["back_pain"]) |
| planOnboardingPrefill.injuries | string[] | List of injuries (empty array for none) |
| planOnboardingPrefill.duration | number | Preferred workout duration in minutes |
| planOnboardingPrefill.lifestyle | string | User's activity level (e.g., "sedentary", "active") |
| planOnboardingPrefill.assessmentOnly | boolean | When `true`, all survey screens (goal, health issues, injuries, duration, lifestyle) are skipped and the user lands directly on the fitness assessment. Any previously stored plan ID is cleared so a fresh personalized plan is generated after the assessment completes. All other prefill fields are ignored when this is set |

**`assessmentOnly` use case:** Use this for **reassessment flows** — when the user already has a profile (goal, lifestyle, etc.) recorded in your host app and you only want them to perform a fresh fitness assessment to regenerate their personalized plan. Don't combine it with the other prefill fields; they will be ignored.

**`remind_me_later_clicked` event:** When the user is on the Assessment screen inside the plan-onboarding flow and taps "Remind me later", the SDK posts a `remind_me_later_clicked` PostMessage so your host app can dismiss the SDK and schedule a follow-up prompt. This event is only fired from the plan-onboarding page.

**Plan Onboarding Prefill Configuration**

_Swift (iOS)_
```swift
// Use createCustomComponentView with route "plan-onboarding"
kinestex.createCustomComponentView(
    route: "plan-onboarding",
    customParams: [
        "planOnboardingPrefill": [
            "goal": "weight_loss",
            "healthIssues": ["back_pain"],
            "injuries": [],
            "duration": 30,
            "lifestyle": "sedentary"
        ]
    ]
)

// Reassessment-only flow (skips the entire survey)
kinestex.createCustomComponentView(
    route: "plan-onboarding",
    customParams: [
        "planOnboardingPrefill": [
            "assessmentOnly": true
        ]
    ]
)
```

_Kotlin (Android)_
```kotlin
// Use createCustomComponentView with route "plan-onboarding"
KinesteXSDK.createCustomComponentView(
    route = "plan-onboarding",
    customParams = mutableMapOf(
        "planOnboardingPrefill" to mapOf(
            "goal" to "weight_loss",
            "healthIssues" to listOf("back_pain"),
            "injuries" to emptyList<String>(),
            "duration" to 30,
            "lifestyle" to "sedentary"
        )
    )
)
```

_React Native_
```jsx
// Use CUSTOM_COMPONENT integration with route "plan-onboarding"
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    planOnboardingPrefill: {
      goal: 'weight_loss',
      healthIssues: ['back_pain'],
      injuries: [],
      duration: 30,
      lifestyle: 'sedentary',
    },
  },
};

<KinestexSDK
  data={postData}
  route="plan-onboarding"
  integrationOption={IntegrationOption.CUSTOM_COMPONENT}
  handleMessage={handleMessage}
/>
```

_Flutter_
```dart
// Use createCustomComponentView with route "plan-onboarding"
KinesteXAIFramework.createCustomComponentView(
  route: "plan-onboarding",
  customParams: {
    "planOnboardingPrefill": {
      "goal": "weight_loss",
      "healthIssues": ["back_pain"],
      "injuries": [],
      "duration": 30,
      "lifestyle": "sedentary",
    },
  },
);
```

_HTML / JavaScript_
```html
const srcURL = "https://ai.kinestex.com/plan-onboarding";

const postData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  planOnboardingPrefill: {
    goal: "weight_loss",
    healthIssues: ["back_pain"],
    injuries: [],
    duration: 30,
    lifestyle: "sedentary",
  },
};

// Reassessment-only flow (skips the entire survey)
const reassessmentPostData = {
  userId: "user-123",
  company: "YOUR_COMPANY",
  key: "YOUR_API_KEY",
  planOnboardingPrefill: {
    assessmentOnly: true,
  },
};
```

_React (TypeScript)_
```tsx
// Use CUSTOM_COMPONENT integration with route "plan-onboarding"
const postData: IPostData = {
  key: 'YOUR_API_KEY',
  userId: 'user-123',
  company: 'YOUR_COMPANY',
  customParameters: {
    planOnboardingPrefill: {
      goal: 'weight_loss',
      healthIssues: ['back_pain'],
      injuries: [],
      duration: 30,
      lifestyle: 'sedentary',
    },
  },
};

<KinestexSDK
  data={postData}
  route="plan-onboarding"
  integrationOption={IntegrationOption.CUSTOM_COMPONENT}
  handleMessage={handleMessage}
/>
```

## AI Trainer Chat Parameters

Parameters specific to the [AI Trainer Chat](/docs/ai-trainer-chat) view.

| Parameter | Type | Default | Description | Effect |
|-----------|------|---------|-------------|--------|
| isSubscribed | boolean | true | Subscription status | Missing or `true` = subscribed. Only an explicit `false` gates workout generation and triggers the `open_subscription_flow` event — see the [subscription gating guide](/docs/guides/guide-subscription-gating) |
| subscriptionReturnUrl | string | - | Standalone subscription redirect | For link/standalone integrations with no host app: non-subscribed users are redirected here at the generation step instead of receiving `open_subscription_flow`. Accepts https:// URLs or app deep links; script-executing schemes are rejected |
| aiTrainerName | string | - | Trainer display name | Renames the AI trainer everywhere it's labelled (header title, reply labels). Shown verbatim in every language |
| aiTrainerColor | string | - | Trainer icon color | Recolors the trainer's star icon — any CSS color, e.g. `"#7C3AED"` |

The trainer also accepts fitness-profile prefill fields (`fitness_goals`, `injuries`, `health_conditions`, `fitness_level_squats` / `_pushups` / `_cardio`, `other_preferences`) — see [Pre-filling user data](/docs/ai-trainer-chat#prefill).

## URL Parameters

Some parameters can also be passed via URL query string for HTML/JS integrations:

| URL Parameter | Equivalent Config | Example |
|---------------|-------------------|---------|
| style | style | ?style=light |
| delegate | defaultDelegate | ?delegate=GPU |
| debug | showDebugRecording | ?debug=true |

URL parameters serve as defaults and can be overridden by parameters passed in the postMessage data.

## Complete Example

Here's a comprehensive example combining multiple parameter categories:

**Complete Configuration Example**

_Swift (iOS)_
```swift
// Complete configuration example
let kinestex = KinesteXAIKit(
    apiKey: "YOUR_API_KEY",
    companyName: "MyFitnessApp",
    userId: "user_12345"
)

let user = UserDetails(
    age: 28,
    height: 165,
    weight: 60,
    gender: .Female,
    lifestyle: .Active
)

// Theme & Loading via IStyle class (hex values with #)
let customStyle = IStyle(
    style: "dark",
    loadingBackgroundColor: "#1A1A2E",
    loadingStickmanColor: "#00FF88",
    loadingTextColor: "#FFFFFF"
)

kinestex.createWorkoutView(
    workout: "Fitness Lite",
    user: user,
    style: customStyle,
    isLoading: $isLoading,
    // Other customization via customParams
    customParams: [
        // Language
        "language": "es",

        // UI Controls
        "isOnboarding": false,
        "hideFeelingDialog": true,

        // Camera
        "landmarkColor": "#00FF88",
        "showSilhouette": true,
        "shouldShowCameraSelector": true,

        // Leaderboard
        "showLeaderboard": true,
        "username": "FitUser28"
    ],
    onMessageReceived: { message in
        // Handle messages
    }
)
```

_Kotlin (Android)_
```kotlin
// Complete configuration example
KinesteXSDK.initialize(
    context = this,
    apiKey = "YOUR_API_KEY",
    companyName = "MyFitnessApp",
    userId = "user_12345"
)

val userDetails = UserDetails(
    age = 28,
    height = 165,
    weight = 60,
    gender = Gender.FEMALE,
    lifestyle = Lifestyle.ACTIVE
)

KinesteXSDK.createWorkoutView(
    context = this,
    workoutName = workoutId,
    user = userDetails,
    // Theme & Loading via IStyle class (hex values without #)
    style = IStyle(
        style = "dark",
        loadingBackgroundColor = "1A1A2E",
        loadingStickmanColor = "e94560",
        loadingTextColor = "FFFFFF"
    ),
    isLoading = viewModel.isLoading,
    // Other customization via customParams
    customParams = mutableMapOf(
        // Language
        "language" to "es",

        // UI Controls
        "isOnboarding" to false,
        "hideFeelingDialog" to true,

        // Camera
        "landmarkColor" to "#00FF88",
        "showSilhouette" to true,

        // Leaderboard
        "showLeaderboard" to true,
        "username" to "FitUser28"
    ),
    onMessageReceived = { message ->
        handleWebViewMessage(message)
    },
    permissionHandler = this
)
```

_React Native_
```jsx
// Complete configuration example
const postData: IPostData = {
  // Required
  key: 'YOUR_API_KEY',
  userId: 'user_12345',
  company: 'MyFitnessApp',

  // User Profile (direct support)
  age: 28,
  height: 165,
  weight: 60,
  gender: 'Female',
  lifestyle: Lifestyle.Active,

  // Theme (direct support)
  style: {
    style: 'dark',
    loadingBackgroundColor: '1A1A2E',
    loadingTextColor: 'FFFFFF',
  },

  // Additional parameters via customParameters
  customParameters: {
    // Language
    language: 'es',

    // UI Controls
    isOnboarding: false,
    hideFeelingDialog: true,

    // Camera
    landmarkColor: '#00FF88',
    showSilhouette: true,
    shouldShowCameraSelector: true,

    // Leaderboard
    showLeaderboard: true,
    username: 'FitUser28',
  },
};
```

_Flutter_
```dart
// Complete configuration example
await KinesteXAIFramework.initialize(
  apiKey: "YOUR_API_KEY",
  companyName: "MyFitnessApp",
  userId: "user_12345",
);

final userDetails = UserDetails(
  age: 28,
  height: 165,
  weight: 60,
  gender: Gender.Female,
  lifestyle: Lifestyle.Active,
);

KinesteXAIFramework.createWorkoutView(
  workoutName: "Fitness Lite",
  user: userDetails,
  isShowKinestex: showKinesteX,
  isLoading: ValueNotifier<bool>(false),
  // Theme & Loading via IStyle class
  style: IStyle(
    style: 'dark',
    loadingBackgroundColor: '1A1A2E', // hex without #
    loadingStickmanColor: 'e94560',
    loadingTextColor: 'FFFFFF',
  ),
  // Other customization via customParams
  customParams: {
    // Language
    "language": "es",

    // UI Controls
    "isOnboarding": false,
    "hideFeelingDialog": true,

    // Camera
    "landmarkColor": "#00FF88",
    "showSilhouette": true,

    // Leaderboard
    "showLeaderboard": true,
    "username": "FitUser28",
  },
  onMessageReceived: (message) {
    handleWebViewMessage(message);
  },
);
```

_HTML / JavaScript_
```html
// Complete configuration example
// All parameters passed as flat object
const postData = {
  // Required
  userId: "user_12345",
  company: "MyFitnessApp",
  key: "YOUR_API_KEY",

  // User Profile
  age: 28,
  height: 165,
  weight: 60,
  gender: "Female",

  // Theme
  style: "dark",

  // Language
  language: "es",

  // UI Controls
  isOnboarding: false,
  hideFeelingDialog: true,

  // Camera
  landmarkColor: "#00FF88",
  showSilhouette: true,
  shouldShowCameraSelector: true,

  // Leaderboard
  showLeaderboard: true,
  username: "FitUser28",

  // Loading
  loadingBackgroundColor: "#1A1A2E",
  loadingTextColor: "#FFFFFF",
};

// Send to iframe
webView.contentWindow.postMessage(postData, srcURL);
```

_React (TypeScript)_
```tsx
// Complete configuration example
const postData: IPostData = {
  // Required
  key: 'YOUR_API_KEY',
  userId: 'user_12345',
  company: 'MyFitnessApp',

  // User Profile (direct support)
  age: 28,
  height: 165,
  weight: 60,
  gender: 'Female',
  lifestyle: Lifestyle.Active,

  // Theme (direct support)
  style: {
    style: 'dark',
    loadingBackgroundColor: '1A1A2E',
    loadingTextColor: 'FFFFFF',
  },

  // Additional parameters via customParameters
  customParameters: {
    // Language
    language: 'es',

    // UI Controls
    isOnboarding: false,
    hideFeelingDialog: true,

    // Camera
    landmarkColor: '#00FF88',
    showSilhouette: true,
    shouldShowCameraSelector: true,

    // Leaderboard
    showLeaderboard: true,
    username: 'FitUser28',
  },
};
```

---
Source: https://www.kinestex.com/docs/customization-parameters · Index: https://www.kinestex.com/llms.txt
