curl --request POST \
--url https://api.hooper.gg/v1/sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source": {
"upload_id": "up_3f9a1c2b7e5d4a08",
"url": "https://app.veo.co/matches/20260826-acme-vs-north/"
},
"group": "grp_412",
"metadata": {
"external_match_id": "abc-123"
},
"duration_seconds": 2,
"options": {
"session_type": "5v5",
"session_mode": "<string>",
"point_system": 123,
"court_type": "ncaa_men",
"recording_setup": "<string>",
"has_jerseys": false,
"num_players": 123,
"recording_team_name": "<string>",
"opponent_team_name": "<string>"
}
}
'import requests
url = "https://api.hooper.gg/v1/sessions"
payload = {
"source": {
"upload_id": "up_3f9a1c2b7e5d4a08",
"url": "https://app.veo.co/matches/20260826-acme-vs-north/"
},
"group": "grp_412",
"metadata": { "external_match_id": "abc-123" },
"duration_seconds": 2,
"options": {
"session_type": "5v5",
"session_mode": "<string>",
"point_system": 123,
"court_type": "ncaa_men",
"recording_setup": "<string>",
"has_jerseys": False,
"num_players": 123,
"recording_team_name": "<string>",
"opponent_team_name": "<string>"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source: {
upload_id: 'up_3f9a1c2b7e5d4a08',
url: 'https://app.veo.co/matches/20260826-acme-vs-north/'
},
group: 'grp_412',
metadata: {external_match_id: 'abc-123'},
duration_seconds: 2,
options: {
session_type: '5v5',
session_mode: '<string>',
point_system: 123,
court_type: 'ncaa_men',
recording_setup: '<string>',
has_jerseys: false,
num_players: 123,
recording_team_name: '<string>',
opponent_team_name: '<string>'
}
})
};
fetch('https://api.hooper.gg/v1/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "sess_18234",
"object": "session",
"created": 1756224000,
"status": "queued",
"group": "grp_412",
"source": {
"type": "upload",
"url": "<string>"
},
"metadata": {},
"run_version": 123,
"duration_seconds": 5412,
"cost_cents": 752,
"highlights": {
"object": "list",
"has_more": true,
"total_count": 123,
"data": [
{
"id": "hl_9f2c…",
"object": "highlight",
"shot": "shot_a1b2…",
"shot_index": 123,
"length_seconds": 8.5,
"is_lowlight": true,
"is_manual": true,
"player": "plr_5",
"video": {
"default": "<string>",
"horizontal": "<string>",
"1080p": "<string>",
"720p": "<string>",
"480p": "<string>",
"360p": "<string>",
"240p": "<string>",
"144p": "<string>"
},
"preview": {
"default": "<string>",
"horizontal": "<string>"
},
"created": 123
}
],
"url": "/v1/sessions/sess_18234/highlights"
},
"shots": {
"object": "list",
"has_more": true,
"total_count": 123,
"data": [
{
"id": "shot_a1b2…",
"object": "shot",
"index": 123,
"start_seconds": 123,
"end_seconds": 123,
"made": true,
"points": 123,
"type": "fieldgoal",
"is_three_point": true,
"is_free_throw": true,
"is_fouled": true,
"location": {
"shot_image_normed": [
123
],
"shot_world_normed": [
123
],
"hoop_image_normed": [
123
]
},
"excitement_score": 123,
"players": {
"scorer": "plr_5",
"assister": "<string>",
"rebounder": "<string>"
},
"highlight": "hl_9f2c…"
}
],
"url": "/v1/sessions/sess_18234/highlights"
},
"players": {
"object": "list",
"has_more": true,
"total_count": 123,
"data": [
{
"id": "plr_5",
"object": "player",
"name": "<string>",
"jersey": "<string>",
"user_id": "<string>",
"team_id": 123,
"stats": {
"points": 123,
"fg_2pt_att": 123,
"fg_2pt_make": 123,
"fg_3pt_att": 123,
"fg_3pt_make": 123,
"ft_att": 123,
"ft_make": 123,
"assist": 123,
"rebound": 123
}
}
],
"url": "/v1/sessions/sess_18234/highlights"
},
"totals": {
"points": 123,
"fg_2pt_att": 123,
"fg_2pt_make": 123,
"fg_3pt_att": 123,
"fg_3pt_make": 123,
"ft_att": 123,
"ft_make": 123,
"assist": 123,
"rebound": 123
},
"video": {
"url": "<string>",
"preview_url": "<string>",
"1080p": "<string>",
"720p": "<string>",
"360p": "<string>",
"width": 123,
"height": 123,
"fps": 123
},
"artifacts": {
"actions": "<string>",
"balls": "<string>",
"hoops": "<string>",
"clusters": "<string>"
},
"error": {
"code": "no_shots",
"message": "<string>"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}{
"error": {
"type": "insufficient_credits",
"code": "insufficient_credits",
"message": "<string>",
"needed_cents": 752,
"available_cents": 100
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}Submit a video
Places a credit hold, creates the session and queues it for processing. Responds immediately with the session in queued state; you are notified through a webhook (session.processed / session.failed) when it finishes, or you can poll GET /v1/sessions/{id}.
Send an Idempotency-Key header to make retries safe: the same key with the same body returns the original response for 24 hours.
curl --request POST \
--url https://api.hooper.gg/v1/sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source": {
"upload_id": "up_3f9a1c2b7e5d4a08",
"url": "https://app.veo.co/matches/20260826-acme-vs-north/"
},
"group": "grp_412",
"metadata": {
"external_match_id": "abc-123"
},
"duration_seconds": 2,
"options": {
"session_type": "5v5",
"session_mode": "<string>",
"point_system": 123,
"court_type": "ncaa_men",
"recording_setup": "<string>",
"has_jerseys": false,
"num_players": 123,
"recording_team_name": "<string>",
"opponent_team_name": "<string>"
}
}
'import requests
url = "https://api.hooper.gg/v1/sessions"
payload = {
"source": {
"upload_id": "up_3f9a1c2b7e5d4a08",
"url": "https://app.veo.co/matches/20260826-acme-vs-north/"
},
"group": "grp_412",
"metadata": { "external_match_id": "abc-123" },
"duration_seconds": 2,
"options": {
"session_type": "5v5",
"session_mode": "<string>",
"point_system": 123,
"court_type": "ncaa_men",
"recording_setup": "<string>",
"has_jerseys": False,
"num_players": 123,
"recording_team_name": "<string>",
"opponent_team_name": "<string>"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source: {
upload_id: 'up_3f9a1c2b7e5d4a08',
url: 'https://app.veo.co/matches/20260826-acme-vs-north/'
},
group: 'grp_412',
metadata: {external_match_id: 'abc-123'},
duration_seconds: 2,
options: {
session_type: '5v5',
session_mode: '<string>',
point_system: 123,
court_type: 'ncaa_men',
recording_setup: '<string>',
has_jerseys: false,
num_players: 123,
recording_team_name: '<string>',
opponent_team_name: '<string>'
}
})
};
fetch('https://api.hooper.gg/v1/sessions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "sess_18234",
"object": "session",
"created": 1756224000,
"status": "queued",
"group": "grp_412",
"source": {
"type": "upload",
"url": "<string>"
},
"metadata": {},
"run_version": 123,
"duration_seconds": 5412,
"cost_cents": 752,
"highlights": {
"object": "list",
"has_more": true,
"total_count": 123,
"data": [
{
"id": "hl_9f2c…",
"object": "highlight",
"shot": "shot_a1b2…",
"shot_index": 123,
"length_seconds": 8.5,
"is_lowlight": true,
"is_manual": true,
"player": "plr_5",
"video": {
"default": "<string>",
"horizontal": "<string>",
"1080p": "<string>",
"720p": "<string>",
"480p": "<string>",
"360p": "<string>",
"240p": "<string>",
"144p": "<string>"
},
"preview": {
"default": "<string>",
"horizontal": "<string>"
},
"created": 123
}
],
"url": "/v1/sessions/sess_18234/highlights"
},
"shots": {
"object": "list",
"has_more": true,
"total_count": 123,
"data": [
{
"id": "shot_a1b2…",
"object": "shot",
"index": 123,
"start_seconds": 123,
"end_seconds": 123,
"made": true,
"points": 123,
"type": "fieldgoal",
"is_three_point": true,
"is_free_throw": true,
"is_fouled": true,
"location": {
"shot_image_normed": [
123
],
"shot_world_normed": [
123
],
"hoop_image_normed": [
123
]
},
"excitement_score": 123,
"players": {
"scorer": "plr_5",
"assister": "<string>",
"rebounder": "<string>"
},
"highlight": "hl_9f2c…"
}
],
"url": "/v1/sessions/sess_18234/highlights"
},
"players": {
"object": "list",
"has_more": true,
"total_count": 123,
"data": [
{
"id": "plr_5",
"object": "player",
"name": "<string>",
"jersey": "<string>",
"user_id": "<string>",
"team_id": 123,
"stats": {
"points": 123,
"fg_2pt_att": 123,
"fg_2pt_make": 123,
"fg_3pt_att": 123,
"fg_3pt_make": 123,
"ft_att": 123,
"ft_make": 123,
"assist": 123,
"rebound": 123
}
}
],
"url": "/v1/sessions/sess_18234/highlights"
},
"totals": {
"points": 123,
"fg_2pt_att": 123,
"fg_2pt_make": 123,
"fg_3pt_att": 123,
"fg_3pt_make": 123,
"ft_att": 123,
"ft_make": 123,
"assist": 123,
"rebound": 123
},
"video": {
"url": "<string>",
"preview_url": "<string>",
"1080p": "<string>",
"720p": "<string>",
"360p": "<string>",
"width": 123,
"height": 123,
"fps": 123
},
"artifacts": {
"actions": "<string>",
"balls": "<string>",
"hoops": "<string>",
"clusters": "<string>"
},
"error": {
"code": "no_shots",
"message": "<string>"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}{
"error": {
"type": "insufficient_credits",
"code": "insufficient_credits",
"message": "<string>",
"needed_cents": 752,
"available_cents": 100
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "<string>",
"param": "source.url"
}
}Authorizations
API key issued by Hooper for your organization. Keys are environment-tagged: hk_prod_ keys work against production, hk_stg_ keys against staging.
Headers
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
Where the video comes from. type is optional — it is derived from the URL (a Veo link is always routed to Veo).
Show child attributes
Show child attributes
A group under your organization. Defaults to the organization's default group.
"grp_412"
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.
Show child attributes
Show child attributes
{ "external_match_id": "abc-123" }
Optional. Improves the credit hold estimate; the real charge is always the measured length.
x >= 1Show child attributes
Show child attributes
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.
"sess_18234"
"session"1756224000
queued, processing, processed, failed "grp_412"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
5412
752
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Raw model output (JSONL) behind the shots and highlights.
Show child attributes
Show child attributes
Set when status is failed.
Show child attributes
Show child attributes