Skip to main content

The problem

Most AI endpoints take your media as a URL (image_url, video_url, audio_url, reference_images, …). That’s easy when your file already lives on the public internet — but if it’s a local file, or something you generated on the fly, you have nowhere to point those endpoints to. The Upload Files API solves this: you upload the file once and get back a readable URL (asset_url) that you can drop into any endpoint that accepts a URL — images, video or audio alike.
asset_url is a plain, publicly-fetchable URL. Anywhere an endpoint asks for an image_url / video_url / audio_url (or a reference image), pass the asset_url of your upload.

How it works

1

Request an upload URL

Call POST /v1/ai/uploads/request-url with the content_type of each file. You get back, per file, a short-lived upload_url (to send the bytes to) and a readable asset_url (to use later).
2

Upload the bytes

PUT the raw file bytes to upload_url, including the returned headers. The upload happens directly against storage — the upload_url is short-lived (see expires_in).
3

Use the asset_url

Pass the asset_url as the input URL of any AI endpoint that accepts one. Re-fetch it any time from GET /v1/ai/uploads.

Supported file types

Pass one of these as content_type: Maximum size: 1 GiB per file.

1. Request an upload URL

You can request up to 14 files in a single call (files array).
file_id
string
Identifier of the uploaded file (upl_…).
upload_url
string
Pre-signed URL to PUT the raw file bytes to. Short-lived — see expires_in.
headers
object
Headers you must include in the PUT request (they are part of the URL signature).
expires_in
integer
Seconds until upload_url expires (do the PUT right after requesting it).
asset_url
string
Readable URL of the uploaded file. Valid once the PUT completes. Use it as the input URL in any endpoint that accepts one. Expires in ~24h — don’t persist it.
asset_url_expires_in
integer
Seconds until asset_url expires (counted from this response).

2. Upload the bytes

PUT the file to the upload_url, echoing the headers from step 1. Do not send your API key here — the request goes straight to storage and is authorized by the signed URL.
The Content-Type you send here must match the content_type you requested in step 1, and the x-goog-content-length-range header is required — both are covered by the URL signature.

3. Use the asset_url

Once the upload completes, pass the asset_url wherever an endpoint expects a URL:
The same asset_url works for video and audio inputs on endpoints that accept them (video_url, audio_url, …).

List your uploads

Lost the response from step 1, or your asset_url expired? List your files — each item comes with a freshly-signed asset_url:

Expiration

Two independent clocks:
  • asset_url_expires_in — how long the URL itself stays valid (~1 day). An expired URL returns 403 — just call GET /v1/ai/uploads again to get a fresh one (a new URL is signed on every listing). Don’t persist the asset_url.
  • ttl_seconds — how long until the file becomes eligible for auto-deletion (~7 days). Deletion is eventual, so a file may linger a little past this — but once it is deleted, its asset_url stops working. Treat uploads as a staging area, not storage.