Skip to main content
POST
Submit a video

Authorizations

Authorization
string
header
required

API key issued by Hooper for your organization. Keys are environment-tagged: hk_prod_ keys work against production, hk_stg_ keys against staging.

Headers

Idempotency-Key
string

Any string up to 255 characters. Replaying the same key with the same body within 24h returns the original response; a different body returns 400 idempotency_key_reused.

Body

application/json
source
object
required

Where the video comes from. type is optional — it is derived from the URL (a Veo link is always routed to Veo).

group
string

A group under your organization. Omit it and the session lands in your organization's own private group.

Example:

"grp_412"

metadata
object

Up to 20 string key/values (keys ≤ 40 chars, values ≤ 500). Echoed on the session and inside every event — use it to carry your own ids.

Example:
options
object

Describes how the video was recorded. Every field is optional. camera_setup, jerseys, session_mode and session_type change how the video is analysed. The others are saved with the session but do not change the results the API returns. Values are case-sensitive; anything outside the listed values is rejected with 400 parameter_invalid, and param names the field.

branding
object

Your own images on the processed video. Both are optional and work with every source type. A branded video is always encoded at 1920×1080; a portrait recording gets black bars at the sides. The session object's branding field shows which images a session carries.

rosters
object

Each team's players. Hooper matches the players it detects to a side's roster by jersey number, so they come back in players with your name and metadata, and players[].team_id follows your sides (1 = recording, 2 = opponent). Send one side or both; an empty object is refused with 400 and param: rosters. Rosters need jersey numbers: they can't be sent with options.jerseys: "disabled" (400, param: options.jerseys), and with the default auto Hooper decides from the video (and keeps reading numbers if it can't tell); send enabled when you know players wear them. See Rosters.

Response

Session queued

One submitted game. The same shape everywhere it appears — single read, list item, webhook payload. Highlights, shots and players are embedded (first 100 of each); their url pages the rest.

id
string
Example:

"sess_18234"

object
string
Allowed value: "session"
created
integer
Example:

1756224000

status
enum<string>
Available options:
queued,
processing,
processed,
failed
group
string
Example:

"grp_412"

source
object
metadata
object
branding
object

Which branding images this session carries. Set when the session is submitted.

teams
object

The two sides of the session, always present. players[].team_id 1 is recording, 2 is opponent.

run_version
integer | null
duration_seconds
integer | null
Example:

5412

cost_cents
integer | null
Example:

752

highlights
object
shots
object
players
object
totals
object
video
object
artifacts
object

Raw model output (JSONL) behind the shots and highlights.

error
object | null

Set when status is failed.