# Tracking Endpoint Message to handle

The **same message structure** is used across:

* real-time tracking
* upload tracking (video/image)

***

### Form score and grades (V3)

Each completed repetition is scored **0–100** and mapped to a grade:

* **A**: score ≥ 90
* **B**: score ≥ 80
* **C**: score ≥ 70
* **D**: score ≥ 60
* **F**: score < 60

The grade reflects execution quality (depth, angles, tempo, stability, and form).

#### Where the grade is sent

In V3, the authoritative score/grade for a **counted rep** is sent inside the **`counter` event** (`counter.form_score`).

> Do not rely on a separate `form_score` event to get the grade of the rep that was just counted.

***

### Message types (V3)

#### Core lifecycle

* `initialization`
* `posture`
* `counter`
* `error`

#### Optional outputs (plan-gated)

* `keypoints`
* `angles`
* `progression`
* `recommendations`

#### Jump-specific (custom exercises)

* `jump_calibration`, `jump_started`, `jump_discarded`, `jump_height`, `jump_summary`

***

### `counter` (updated V3 payload)

The `counter` message is sent **each time the rep count changes**. For upload video, a final counter is emitted once processing ends (`final: true`).

#### Fields

* `type`: `"counter"`
* `current_count`: `number` — total counted reps so far
* `final`: `boolean` (optional) — true when processing has finished (upload video)
* `form_score`: `object` (optional) — score for the rep that was just counted (or current state when `final:true`)
  * `score`: `number` (0–100)
  * `avg_score`: `number` (running average)
  * `grade`: `"A" | "B" | "C" | "D" | "F"`

#### `reference_score` (when using `reference`)

When using `reference=REFERENCE_UUID`, the `counter` event may include a `reference_score` object.

This object contains similarity metrics between the user’s movement and the selected reference movement.

* `overallScore` (`number`, `0..1`) — overall similarity score
* `poseScore` (`number`, `0..1`) — pose similarity
* `timingScore` (`number`, `0..1`) — timing similarity
* `movementScore` (`number`, `0..1`) — movement amplitude similarity
* `grade` (`string`) — letter grade for the repetition

Example:

```json
{
  "type": "counter",
  "current_count": 3,
  "reference_score": {
    "overallScore": 0.82,
    "poseScore": 0.78,
    "timingScore": 0.9,
    "movementScore": 0.84,
    "grade": "B"
  }
}
```

Use `overallScore` if you want a single global score. Use the sub-scores if you want custom logic or custom UI feedback.

#### Concrete examples

```json
{"type":"counter","current_count":1,"form_score":{"score":88,"avg_score":88,"grade":"B"}}
```

```json
{"type":"counter","current_count":5,"form_score":{"score":72,"avg_score":81,"grade":"C"}}
```

```json
{"type":"counter","current_count":10,"final":true,"form_score":{"score":90,"avg_score":84,"grade":"A"}}
```

***

### Standalone `form_score` event (if you see it)

If a `form_score`-only message exists in other contexts (e.g. live feedback while a rep is in progress), it **must not** be treated as the authoritative grade for a **counted** rep.

**Single source of truth for counted reps:** `counter.form_score`.

***

### Tips for developers: minGrade vs client-side filtering

#### Server-side filtering (recommended): `minGrade`

If you set `minGrade=B`, PoseTracker only increments `current_count` for reps graded **A or B**. This means:

* `current_count` becomes your “valid reps” count
* each counter event already corresponds to a valid rep

#### Client-side filtering (if you don’t want server filtering)

If you do **not** set `minGrade`, you receive every counted rep with its grade inside `counter.form_score`. You can maintain your own strict count:

Pseudo-logic:

* if `payload.form_score.grade` is in `["A","B"]`, increment your local strict counter

***

### Errors

(keep your existing error section; ensure it includes plan restriction errors and invalid\_exercise)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://posetracker.gitbook.io/posetracker-api/use-posetracker-on-real-time-camera-webcam/tracking-endpoint-message-to-handle.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
