Appearance
Videos
GET /video/{video_id}/status
Returns id, device_id, status, start_time, end_time, delayed_processing, delayed_processing_since, and updated_at.
| Status | Meaning |
|---|---|
SCHEDULED | A future recording exists and has not started. |
QUEUED | The initial processing job is waiting for a worker. |
RECORDING | The camera is capturing the recording. |
PROCESSING | The initial Clutch analysis is running. |
UPLOADING | The camera is uploading the full recording. |
UPLOADED | The upload finished. This is terminal for standard recordings and may be transient for match recordings. |
UPLOAD_FAILED | The full-recording upload failed. |
COMPLETED | Initial analysis is complete. Stats, highlights, and video_stream are ready. The recording may remain in COMPLETED while the camera uploads the raw video. Clutch may reprocess it if poor internet caused excessive frame loss. |
COMPLETED_EMPTY_COURT | Initial analysis found no usable match. The stream may be ready. Match stats and highlights are omitted. |
DELAYED_PROCESSING | Initial processing failed or was incomplete. Clutch will retry through delayed processing, usually within 1 to 2 hours. |
OK | All processing is complete. The full video and available match outputs are ready. |
OK_EMPTY_COURT | All processing is complete and no usable match was found. The full video may be available. Match stats and highlights are omitted. |
FAILED_DEVICE_OCCUPIED | The scheduled recording could not start because the camera remained busy. |
FAILED_DEVICE_OFFLINE | The scheduled recording could not start because the camera was offline. |
CANCELLED | The scheduled recording was cancelled before it started. |
delayed_processing reports whether a second processing pass is expected, running, or finished: not_expected, expected, in_progress, or done. expected means Clutch detected a degraded stream while the recording was in progress and will reprocess once the camera’s recording uploads.
delayed_processing_since is when the pending re-run was detected for expected, not when the re-run starts. For in_progress and done it is when the re-run was dispatched. Null otherwise.
An internal FAILED state is returned as DELAYED_PROCESSING. Treat any undocumented transient status as in progress.
Sample response
json
{
"data": {
"id": "B92BFC8A-2454-4632-9580-F96E99FB7C85",
"device_id": "4580f207-b672-4df0-83eb-110cc408466b",
"status": "PROCESSING",
"start_time": "2026-08-01T17:02:00Z",
"end_time": "2026-08-01T18:30:00Z",
"delayed_processing": "not_expected",
"delayed_processing_since": null,
"updated_at": "2026-08-01T19:05:00Z"
}
}GET /video/{video_id}/results
Returns the Clutch app link and output URLs. Treat URLs as opaque and call the endpoint again for current values. HTTP 202 means there are no results to return right now, and the message names the current status, for example {"error": "Video is not yet processed. Status: PROCESSING"}.
CANCELLED, FAILED_DEVICE_OCCUPIED and FAILED_DEVICE_OFFLINE also return 202 but will never have results, so stop polling on those statuses. UPLOAD_FAILED also returns 202, and results only follow if the camera retries the upload successfully.
HTTP 200 does not always mean the analysis is ready. During DELAYED_PROCESSING this endpoint returns 200 with only video or an empty outputs list, and court_keypoints is null. Use GET /video/{video_id}/status or the webhook to see when analysis has finished.
Sample response
json
{
"data": {
"id": "B92BFC8A-2454-4632-9580-F96E99FB7C85",
"device_id": "4580f207-b672-4df0-83eb-110cc408466b",
"app_link": "https://app.clutchapp.io/match/B92BFC8A-2454-4632-9580-F96E99FB7C85",
"outputs": [
{
"key": "match.json",
"url": "https://assets.example.com/public/dd2dfc8c-4244-4a6e-b410-eec76f9254c0/output/B92BFC8A-2454-4632-9580-F96E99FB7C85/data/match.json"
},
{
"key": "video_stream",
"url": "https://assets.example.com/public/dd2dfc8c-4244-4a6e-b410-eec76f9254c0/B92BFC8A-2454-4632-9580-F96E99FB7C85_stream.mp4"
}
],
"court_keypoints": {
"frame": { "width": 1920, "height": 1080 },
"points": {
"tol": [741, 165],
"tor": [1187, 165],
"point_7": [112, 810],
"point_9": [1803, 815]
}
}
}
}Output keys may include video, video_stream, match.json, player_crop_urls.json, thumbnails, highlight manifests, and highlight videos.
court_keypoints gives the court points the AI used for the recording, in pixels of a 1920×1080 frame, or null when none were saved. The AI analyses every recording at that size, so scale by width / 1920 and height / 1080 before drawing on a 4K video. The points apply to video and video_stream, not to the cropped highlight clips. Each recording keeps the points it was processed with, even if the camera is moved later.
A padel court is 10 m wide and 20 m long. tol is the origin, the far baseline corner on the left of the image. x runs across the court and y towards the camera, with the net at y = 10 and the service lines at y = 3 and y = 17. Current cameras label four points: tol (0, 0), tor (10, 0), point_7 (0, 17) and point_9 (10, 17), in metres. A perspective transform over those four pairs, such as OpenCV's getPerspectiveTransform, maps pixels to court metres and back. The wide lens bends lines slightly near the frame edges, so the transform is exact at the labelled points and approximate elsewhere. Recordings from before 2025 can carry other point names; other sports label the court corners tol, tor, bol and bor.
Shots and outcomes in match.json
The shot types, subtypes, outcomes and every player_stats counter in match.json are defined in the Shot Dictionary.
DELETE /video/{video_id}/cancel
Cancels a scheduled recording.
Sample response
json
{
"message": "Recording scheduled for start-time: 2026-08-01 17:00:00Z, end-time: 2026-08-01 18:30:00Z has now been cancelled.",
"video_id": "B92BFC8A-2454-4632-9580-F96E99FB7C85"
}