Skip to content

The analysis lifecycle

A session moves through four states:

stateDiagram-v2
    [*] --> pending: POST /api/sessions/<br/>debits 1 session
    pending --> processing: a worker picks it up
    processing --> completed: analysis finished
    processing --> failed: analysis failed
    failed --> pending: reanalyze<br/>re-takes a slot
    completed --> pending: reanalyze<br/>free, still holds its debit
    note right of failed
        quota refunded automatically
    end note
status Meaning
pending Queued. No worker has picked it up.
processing Running. progress carries the current stage.
completed Done. metrics, metric_targets, analyzed_url are populated.
failed failure_reason says why — and the quota slot is refunded automatically.

There are no webhooks yet. Poll GET /api/sessions/{id}/.

A typical clip finishes in tens of seconds. The first request after a quiet period may take ~10 s longer because the GPU scales to zero between bursts — that is a cold start, not a stall.

While processing, the progress object carries the worker’s most recent stage:

{
"stage": "pose_extract",
"stage_idx": 2,
"frame_done": 431,
"frame_total": 900
}

A failed session returns its quota slot automatically. Deleting the failed row afterwards refunds nothing extra — a debit is refunded at most once.

Re-running an existing session with POST /api/sessions/{id}/reanalyze/ is free if the session still holds its original debit. One that already failed released its slot, so the re-run re-takes it, and can return 402 quota_exhausted if the slot was spent elsewhere in between.

This is the part most integrations miss.

capture_findings is a list of quality problems detected in the footage, and it appears on completed sessions — not failed ones. The analysis ran, a report exists, and the numbers are not reliable:

{ "code": "pose_sparse", "severity": "advisory", "data": { "detection_ratio": 0.42 } }

Five codes exist: pose_sparse, implausible_geometry, subject_too_far, camera_off_plane, subject_left_frame. Each one means the angles, phases and scores in that report were computed from footage the tracker could not read properly.

Surface them. A report with pose_sparse should reach the coach as “re-film this”, not as a result — and it did consume a session, because it processed to a finished report. The troubleshooting guide covers what each code means and how to fix the recording.