Workflow: from video to results
The end-to-end path. Step 2 is optional but recommended. It anchors team identity, which improves the labelling of every downstream result.
1. POST /videos register the video (by URL)
2. confirm sides widget or PUT /videos/{id} (optional)
3. POST /videos/{id}/analysis start the analysis
4. GET /analyses/{id} poll until done (or use webhooks)
5. fetch results events / summary / tracking / query-intervals / crops
1. Register the video
POST /v1/videos
{
"video_file_url": "https://cdn.example.com/match-4711.mp4",
"title": "Cup final",
"date": "2026-07-12",
"home_team_name": "Home FC",
"away_team_name": "Away FC",
"left_start_team": "home",
"start_offset_seconds": 0,
"end_offset_seconds": null
}
Only video_file_url is required. Hub downloads the file in the background. Provide team
names if you know them. They label every downstream result. Registering also starts the
team preview pass.
The video's status runs created -> downloading -> available, or error if the
download or validation fails. Step 3 does not wait for available: an analysis parks as
waiting_for_video until the download finishes.
2. Confirm teams (optional)
Let your user say which of the two detected kits is the home team. The video cannot
determine this on its own. Embed the confirm-sides widget, or
build your own step on
GET /videos/{id}/preview-teams.
Do not ask which side that team starts on. The analysis derives left_start_team from the
kit answer and writes it back when it completes. Set it at creation only if you already
know it.
Nothing blocks the run. Team identity (names and sides) resolves at read time via
GET /analyses/{id}/team-mapping. A confirm-sides answer
or corrected metadata arriving after the run fixes the labels on every result.
3. Start the analysis
POST /v1/videos/{id}/analysis
An empty body {} is accepted. Returns the analysis with its id and status. There is
nothing to configure. Analyses never wait on the client. The wait_for and
wait_for_timeout_minutes parameters no longer exist. Identity is composed at read time
instead of blocking the run.
The analysis may park briefly as status: "waiting_for_meta" with
waiting_for: ["game_context"] while hub finishes its kit-colour pass on the footage. This
hold is automatic and bounded and needs no action.
4. Wait for completion
Poll GET /v1/analyses/{id}. status runs init -> waiting_for_video ->
(waiting_for_meta ->) running -> done, with progress while running. To avoid
polling, register a webhook to be called on completion (see the webhooks concept page).
5. Fetch results
Once status is done:
| What | Endpoint |
|---|---|
| Detected events (passes, shots, possession, …) | GET /analyses/{id}/events |
| Match summary & aggregate stats | GET /analyses/{id}/summary |
| Raw tracking data | GET /analyses/{id}/tracking/download |
| Video intervals matching your filters | POST /analyses/{id}/query-intervals |
| Player/team thumbnails | GET /analyses/{id}/exemplar-crops |
| Machine-readable output schema | GET /analyses/{id}/schema |
See the endpoint reference and the events/filters pages for the payloads.
Cleaning up
DELETE /v1/videos/{id}
Removes the video and every analysis of it, results included. This is permanent, with no
undelete. Returns 204 No Content.
While one of the video's analyses is running, the delete is refused with 409 Conflict.
Wait for done or error and retry. An analysis that has not started yet (init,
waiting_for_video, waiting_for_meta) does not block the delete. Deleting the video is
also how you abandon a queued analysis.