Overview
Most multimodal models on ModelRunner accept files (images, audio clips, videos) as URLs in their input. ModelRunner provides two upload patterns:- Single-part upload — one presigned
PUTto S3, suitable for files up to ~5 GB. - Multipart upload — three-step flow with per-part presigned URLs, required for very large files or when you want resumability.
media.modelrunner.ai URL that you can pass directly to any model input field that accepts a file.
The SDKs wrap the single-part flow as
storage.upload() (JS) and upload_file() (Python). Use the raw HTTP flow below when you need multipart or when calling the API directly.Single-part upload
A two-step flow: initiate → PUT bytes to the returned presigned URL.1
Initiate the upload
POST /storage/upload/initiate returns a presigned upload_url and the canonical file_url to use as model input.cURL
2
PUT the bytes to the presigned URL
Send the raw file body to On success,
upload_url with the same Content-Type. Do not add the Authorization header — the presigned URL carries its own credentials.cURL
file_url is immediately usable. Pass it to any model input that accepts a URL:Setting an expiration
Uploads are kept until you delete them. To have one expire automatically, send the object-lifecycle header on the initiate call — the same header used for generated media:complete call instead, since that is where the file is recorded.
In the JavaScript SDK this is the lifecycle option:
Using the SDKs
Multipart upload (large files)
For multi-gigabyte videos or when you want resumability, use the three-step multipart flow.1
Initiate the multipart upload
POST /storage/upload/initiate-multipart returns an uploadId, uploadKey, and the canonical fileUrl.2
Upload each part
Split the file into parts (S3 requires each part except the last to be ≥ 5 MiB). For each part number starting at
1, request a presigned URL and PUT the part to it.3
Complete the upload
POST /storage/upload/complete finalizes the multipart upload and creates the file row.When the S3 host is blocked
Both flows abovePUT the bytes straight to AWS S3. Clients that run behind an egress allowlist — AI assistants and agent sandboxes, mainly — often cannot reach that host and get a 403 with host_not_allowed. Two fallbacks stay on ModelRunner’s own domain:
- Upload relay. Send
"relay": trueon Initiate Upload and the response carries arelay_upload_urlalongside the usualupload_url.PUTthe raw bytes there instead and we stream them to storage server-side. Same 5-minute window, samefile_url, and noAuthorizationheader — the token in the URL is the credential. Try the S3 URL first; the relay costs an extra hop. - Chunked inline upload. If neither host is reachable,
POST /storage/upload/chunktakes the file as small base64 chunks and assembles it server-side. Capped at 50 MiB per file and slower than eitherPUT— a last resort.
Your asset library
Every upload and every model output becomes a file record you can list, search, and organize:- List Files — your library, filterable by bucket (
upload/output/input), MIME type, tag, or favorite. - Get File by URL — resolve a
media.modelrunner.aiURL you are holding back to its record, including which requests used it. - Favorite and tag files to organize them. Both also exempt a file from expiry, so something you meant to keep is not swept away — see data retention.
- Delete File removes the record, not the stored bytes — and with the record gone there is nothing left to find the object by. Set an expiry at upload time for anything you want cleaned up automatically.
Reference
Every endpoint except the relay takes the standard
Authorization: Key <your_key> header — see API keys. Full request and response schemas live in the Platform API reference.
