---
title: "Ingest a scouting video from a URL"
method: POST
path: "/api/vortex/upload-video-from-url"
tags: ["Vortex"]
---

# Ingest a scouting video from a URL

`POST /api/vortex/upload-video-from-url`

## Request

- Base URL: `https://api.sponsorunited.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.sponsorunited.com/api/vortex/upload-video-from-url`
- Auth: API key in header `X-API-Key`
- TypeScript: <https://skmtc.dev/sponsorunited/apis/sponsorunited-api/docs/api/vortex/upload-video-from-url/post.ts> (a function with typed inputs; its response is checked against the schema)

Pulls a video from the provided presigned URL, stores it on the video bucket, creates the Video record and queues the MediaConvert transcode. Returns as soon as the transcode is queued, so job_status is null in this response — a scheduled sweep checks the transcode every minute and records PROGRESSING, then COMPLETE together with output_url and thumbnail_url, or ERROR or CANCELED, as MediaConvert reports them. A job_status of ERROR means MediaConvert refused the job; the Video id is still valid. The returned id can be attached to a scouting session via media_type=video on POST /api/vortex/user-event-uploads. Repeating the call for the same source object returns the existing record instead of ingesting it twice. Callers must allow at least 300 seconds for this request: the 120 second budget bounds the download alone, and the mediainfo probe, the copy of up to 500 MB to S3, the checksum and the insert all follow it unbounded. Callers must also generate the presigned URL at call time rather than in advance, and send a URL whose path ends with the file extension. Authenticated via X-API-Key.

## Request body

- UploadVideoFromUrlRequest: Request schema for ingesting a video from a URL into the video bucket
  - `url` string, url, required: A presigned S3 GET URL for the video. The path must end with the file extension (mp4, mov, m4v, mpg or qt); the extension is what names the stored object and makes repeated calls for the same clip idempotent.

## Response `201`

Video ingested and transcode queued

- Video
  - `id` integer
  - `original_name` string
  - `stored_name` string
  - `hash_code` string, nullable
  - `input_url` string
  - `output_url` string, nullable: HLS playlist URL. Null until job_status is COMPLETE, and stays null when the transcode fails (job_status ERROR or CANCELED).
  - `thumbnail_url` string, nullable: Poster image URL. Null until job_status is COMPLETE, and stays null when the transcode fails (job_status ERROR or CANCELED).
  - `width` integer
  - `height` integer
  - `duration` integer
  - `original_file_size` integer
  - `job_id` string, nullable
  - `job_status` 'SUBMITTED' | 'PROGRESSING' | 'COMPLETE' | 'CANCELED' | 'ERROR', nullable: MediaConvert transcode status. Pending: null (job queued, no status reported yet), SUBMITTED or PROGRESSING; output_url and thumbnail_url are null. Complete: COMPLETE; output_url and thumbnail_url are set. Failed: ERROR (MediaConvert rejected or failed the job) or CANCELED; output_url and thumbnail_url stay null permanently.
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `deleted_at` string, date-time, nullable
  - `media_type` string

## Other responses

- `401`: Unauthenticated
- `422`: Validation error, a URL with no path or whose path carries no file extension, an unsupported extension, a size over the ceiling (either declared by Content-Length or measured while downloading), an unreachable host, a non-2xx response from the source, a file carrying no video track, video metadata the probe could not read, or a download that exceeded the 120 second budget

---

[API](https://skmtc.dev/sponsorunited/apis/sponsorunited-api.md) - [All operations](https://skmtc.dev/sponsorunited/apis/sponsorunited-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sponsorunited/apis/sponsorunited-api/revisions/cbf1ca5bff8f?raw)
