Integration guide

Mapping Plyomat test types

A short guide for anyone integrating with the Plyomat Open API. It covers the two ways a coach can capture data, why display_mode is not the test name, what each measurement mode actually records, and how to handle a null assessment_id.

Start here

How coaches capture data

There are two ways a coach can run and save a test, and both save into a session.

Display Mode

assessment_id: null

The coach picks a mode (Vertical, RSI, Drop Jump, PPS, and so on), picks an athlete, and saves. This is normal training or a quick check. No formal protocol is enforced.

Assessment

assessment_id: "uuid"

The coach picks a named assessment (Standing Vertical Jump, 10/5 RSI, SL Vertical Jump, and so on), picks an athlete, and saves. Rep count, kept reps, sidedness, and start position are fixed by the protocol, so the test stays standardized and repeatable.

Every set carries a session_id either way, so session_id is not how you tell them apart. The single field that distinguishes the two paths is assessment_id.

The core rule

display_mode is not the test name

display_mode is the measurement mode: what the mat measured and which metric is primary.

The test name lives on the assessment.

A set carries an assessment_id. Resolve it to get the real protocol:

set.assessment_id  →  GET /v1/assessments  →  { name, display_mode, sidedness,
                                                rep_count, reps_kept, drop_height_cm }

Why it matters: display_mode: "rsi" is a family, not a test. A 10-rep bilateral rebound protocol and a single-leg 5-hop both report rsi, but they are completely different assessments and should never land in the same bucket.

Map on assessment.name for the test. Use display_mode for the category.

Reference

What each mode measures

display_modeWhat the mat measuresPrimary metric
verticalFlight time of a vertical jumpjump_height_cm
contactGround contact time, repeated hopscontact_time_ms
rsiRebound jumps, flight ÷ contactrsi
drop_jumpDrop from a set box height, then reboundrsi
ppsPower, using body mass and any added loadjump height + body weight
bounce_factorTwo-jump bounce protocolrsi
timerOpen recording on a countdownnot a test
freeRaw flight and contact capturenot a test

Note that DRI is not a mode. The mode is drop_jump, and DRI is a scoring option within it.

Treat display_mode as an open string, not a fixed enum. New modes get added over time. An integration that hard-fails on an unrecognized value will break, so fall back to the assessment name and carry the raw value through.

Naming

Vertical, CMJ, and org-defined names

The closest standard equivalent to vertical is a countermovement jump measured by flight time, and the built-in Standing Vertical Jump protocol is performed with a countermovement.

Be precise in your model, though: the mat measures flight time and cannot detect whether the athlete used a countermovement, an arm swing, or a static squat jump. That is coach-controlled protocol, not something the data guarantees. So if a coach names their assessment CMJ, that exact string is what assessment.name returns, and that is your reliable signal, not the mode.

Assessment names are organization-defined

Plyomat ships built-in assessments: Standing Vertical Jump, SL Vertical Jump, Repeat Vertical Jump, 10/5 RSI, 4/2 RSI, Max RSI, SL Max RSI, SL 5-Hop RSI, SL Lateral to Vertical RSI, Drop Jump DRI at 6″, 12″, 18″ and 24″, Speed Box Hop x 15, Load Power Profile, and High Load Power Profile. But every organization can create and name its own.

  • Never hard-code a list of test names. Read GET /v1/assessments per organization and map dynamically.
  • is_system: true means a Plyomat built-in. false means that organization created it.
  • Names are not unique across organizations and can be edited, so key your mapping on assessment.id and treat the name as a display label.
Extra context

Tags

Every set carries a tags array of strings. Coaches apply these on Display Mode saves to annotate what they actually ran, and they are often exactly the detail a measurement mode cannot capture on its own. Real examples in use today: CMJ, SJ, Seated Jump, Hands on hip, Trap Bar, Box 18in, preseason, post-injury.

Two things to know before you build on them:

  • Tags are a Display Mode concept. Assessment saves are tag-free by design, because the assessment name already carries the protocol. So tags and assessment names fill the same gap from opposite ends.
  • Tags are free text, not a controlled vocabulary. One array can mix protocol variants, equipment, constraints, body side, and training context. Spellings drift between coaches. Treat tags as a useful hint and surface them to the user, but do not key a structured test-type field on them.

If an organization wants a variant like CMJ or Squat Jump to be reliable, structured data, the right home is a named assessment. Tags are the annotation layer on top.

Edge case

When assessment_id is null

A null assessment_id is normal and expected. It means the coach used Display Mode rather than selecting a formal assessment: normal training, a warm-up, or a quick check.

Those sets are real captured data, but they are not a named test. Handle it explicitly:

test_name = assessment_id
  ? assessments[assessment_id].name   // a named test
  : null                              // Display Mode capture, use display_mode

Depending on your product, either label those as ad-hoc or exclude them from formal test reporting. What you should not do is silently treat them as an untitled test of type display_mode.

Details

Reading the reps

  • Units are metric. jump_height_cm in centimeters, all times in milliseconds.
  • Filter on is_kept. Reps the coach discarded come through with is_kept: false. Exclude them before computing bests or averages.
  • Laterality. Unilateral assessments carry sidedness: "unilateral" and each rep carries side: "left" or "right". Bilateral reps have side: null.
  • Null metrics are expected per mode. A vertical set has no contact_time_ms and no rsi, because that mode does not measure them. Do not treat null as missing data.
  • body_weight_kg_at_capture is a snapshot taken at test time, not the athlete's current roster weight. Use it for any mass-dependent math so historical results stay reproducible.

Suggested mapping shape

{
  test_id:      set.assessment_id,          // null = Display Mode
  test_name:    assessment?.name ?? null,   // organization-defined string
  test_family:  set.display_mode,           // open string, not an enum
  is_builtin:   assessment?.is_system ?? null,
  tags:         set.tags,                   // coach annotations, free text
  laterality:   set.laterality,
  performed_at: set.started_at,
  athlete_id:   set.athlete_id,
  reps:         set.reps.filter(r => r.is_kept)
}
Keep reading

All developer docs

  • Open API overview: what you can read, authentication, endpoints, paging, syncing, and webhooks.
  • Mapping test types (this page): Display Mode vs Assessment, test names, modes, tags, and null handling.
  • Interactive API reference: every endpoint, parameter, and response shape, with a live Try it.

Build on your own data.

The full interactive reference lists every endpoint, parameter, and response shape.