Longitudinal concepts
Score each new recording against a subject's own history.
Most analyze endpoints score one recording on its own. Longitudinal analysis asks a second question: how does this recording compare to the same person’s previous ones?
A group is one subject’s job history. Longitudinal analyze adds baseline, deviation, and trend next to the usual result.
Two ways to read a group:
| Endpoint | Answers |
|---|---|
POST .../analyze/longitudinal |
How does this recording compare to the subject’s history? |
GET /v2/groups/{group_id}/longitudinal |
What does the whole trajectory look like so far? |
Request shapes, responses, and examples are in the Longitudinal API. Create and manage groups with the Groups API.
Important A group used with the longitudinal endpoints represents one subject. Personal baselines are per-subject, so a group that mixes people describes no one in particular. Amplifier stores no personal identifiers and cannot verify subject identity — keeping a group to a single subject is the caller’s responsibility. For cohort-level statistics across many subjects, use the aggregate endpoint described in Cohort aggregates.
Concepts
Group. A caller-named container for jobs, scoped to your account. You choose the group_id — a stable identifier from your own system (a user id, a participant code) works well. Groups are created explicitly with POST /v2/groups, or implicitly the first time you submit audio to one.
Raw vs. longitudinal analyze. Every analyze endpoint has two group-aware forms:
.../groups/{group_id}/analyze— registers the job into the group, but scores the recording on its own..../groups/{group_id}/analyze/longitudinal— registers the job and scores it against the group’s history.
Both contribute to the group’s history once the job reaches done, and both cost the same — the two forms bill and rate-limit identically. The only difference is the response: the raw form returns the standard result, the longitudinal form adds the baseline and deviation fields. Use the raw form when a given call does not need them.
Recording time. Pass recorded_at when the audio was captured earlier than it was uploaded. Longitudinal ordering and time-decay use it; it falls back to the job’s created_at when omitted. It is accepted as supplied, since capture time cannot be confirmed server-side.
History window. Group computations read a bounded window: completed jobs recorded within the last 270 days, capped at the 1,000 most recent. Trajectory fields (including data_points) use that window. done_job_count is the whole group. Recency-weighting applies inside the window: older points count less.
Credits and rate limits. Each analyze endpoint bills and rate-limits exactly like its own non-group counterpart: the model variants like POST /v2/models/{model_name}/analyze, the sign variants like POST /v2/signs/{sign_name}/analyze. Group lifecycle, membership, and state endpoints consume no credits. See Billing and Cost and Rate limits.
Baseline and deviation
A longitudinal analyze result carries the recording’s own score, level, and flagged unchanged, plus a set of fields that place the reading against the subject’s own history:
latest_score— the smoothed current estimate after this recording, precision- and time-weighted across the window. It may differ from the rawscore.baseline_score— the subject’s personal baseline, blended toward a population prior while personal history is still accumulating.deviation_from_baseline—latest_score − baseline_score. Positive means above the subject’s own baseline.anomaly—truewhen the change against the subject’s own norm is significant. Slower-moving signs need the change to persist across two distinct timepoints before this is set.z_score— deviation expressed in units of the subject’s own variability.population_z— the subject’s current position relative to the cohort.nullwhen no population reference is available for a signal.
Note All of the longitudinal fields above are
nullon the first submission to a group — with no prior history the result is equivalent to a one-off analysis. Detect that case by checkingbaseline_scorefornull, and treat the other longitudinal fields as available only when it is non-null. Baselines become meaningful as spaced recordings accumulate.
Establishing a baseline. The configured minimum is 3 independent readings (min_data_points_required). Signals with no population reference are held at establishing_baseline until it is met; where a population reference exists the baseline starts from the population prior and firms up as readings accumulate. Recordings taken close together pool into roughly one independent reading, so three recordings minutes apart count as about one. baseline_personal_weight reports how much of baseline_score comes from this subject rather than the population prior, which is useful for deciding when to present the baseline as “your usual”.
Trend
The trajectory endpoint returns a fitted trend per signal under trajectory:
direction—up,down,flat, orinsufficient_data.flatis returned unless the fitted change clears a deadband set by the signal’s own variability.insufficient_datais returned until enough spaced readings are available to fit a trend.slope— change in score per day.nullwhendirectionisinsufficient_data.resolvable— whether a trend was actually fitted. Gate any trend display on this rather than ondata_points_used.data_points_used— time bins the trend was fitted over, not a raw job count. Populated even whenresolvableisfalse.
The trajectory endpoint follows a polling pattern. The first call for a group — or the first after its membership changes — returns status: "running" while the trajectory is computed. Poll until status is done.
A signal with no usable readings in the window is omitted from signals[] entirely rather than returned with a status, so treat an absent signal as “nothing measured in this window” — it can disappear between polls if its readings age out.
Signal naming. For the apex and harbor models a few signs are reported under a model-specific name on job results and under the canonical name on the trajectory and aggregate endpoints, so match on the value those endpoints return rather than joining by the job result’s name.
Cohort aggregates
GET /v2/groups/{group_id}/aggregate is the many-subjects view. It describes the group as a population rather than tracking one person, so it is the right endpoint for a group that intentionally holds recordings from several people. It follows the same polling pattern as the trajectory endpoint, and its statistics count usable readings only, drawn from the same history window.
Per signal it returns the distribution of readings across none, low, consider, moderate, and elevated (values sum to 1.0), mean_score, std_score, flagged_rate, and the job_count that produced a usable reading for that signal.
Next steps
- Longitudinal API — raw analyze into a group, longitudinal analyze, trajectory, and aggregate.
- Groups API — create groups and manage job membership.
- Interpreting Results — the
levelandrecommended_actionfields that longitudinal results carry unchanged. - Response Schema — field definitions for the standard job result.