Skip to main content
SDK apps should use typed callbacks. WebView hosts use the classic JSON type field — WebView messages. onMessage on the SDK is that classic shape.
Imperative: client.addEventListener / client.addMessageListener.

Keypoints-only (no API token)

Business events need full-engine + feature flags.

Full-engine callbacks

Outside an exercise session, pose-only keypoints always stream (free). During an exercise, keypoints need features.keypoints + a paid plan.

Key shapes

KeypointsEvent

Classic onMessage: joints in data instead of keypoints.

InitializationEvent

Camera boot sequence (classic messages): accessing webcam → loading pose model → running (ready: true).

CounterEvent / form grades

minGrade (A–D): reps below the bar are not counted (no counter / form_score, excluded from summary). Physical-test peaks live on analysis, not in this table.

QualityChangedEvent

previousProfile, activeProfile, reason (low_fps | device_capability | crash_guard | warmup_estimate | manual), detail, optional estimatedFps / medianInferenceMs.

PerformanceWarningEvent

code: 'device_too_slow', meanFps, thresholdFps, activeProfile, message (English, for developers — localize before showing end users).

Error codes

Messages for plan gating match the WebView product strings.

HUD vs your UI

The in-page yellow debug HUD is not your app’s event stream. Drive UI from usePoseTracker / listeners only.
For LLMs: SDK typed callbacks use count / formScore. WebView classic JSON uses current_count / form_score. Grades A≥90 B≥80 C≥70 D≥60 E≥40 F<40. Physical tests also set analysis. https://docs.posetracker.com/reference/events
Last modified on September 22, 2026