Skip to main content
Files are how media moves between calls on Opper. Upload a file (or let a generation store its output) and you get back a file_<id> — a reusable handle you can pass as input to later calls instead of re-uploading or re-encoding bytes. One uploaded image can seed a video; one generated image can be edited by the next call; a generated audio clip can be fed straight to transcription.

Two ways files appear

  • You upload them. POST /v3/files (multipart) returns a file_<id> for reference media — an image to animate, a source video to edit, an audio clip to transcribe.
  • Generations store them when asked. The image, audio, and video endpoints save their output to Files when you pass store: true, and return a file_id alongside the result. Nothing is stored otherwise.

Using a file_id as input

A file_id is accepted anywhere a media source is — next to an http(s) URL or a data-URI:

Lifecycle

Files are permanent until you delete them — uploads and stored generation outputs alike. There is no default expiry: a file_id you get today keeps working until you call DELETE /v3/files/{id}. If you want a file to clean itself up, opt into an expiry:
  • On upload — pass ttl_seconds (a positive integer, up to 100 years) as a form field and the file expires that many seconds from now.
  • Later — PATCH /v3/files/{id} with {"ttl_seconds": 3600} sets or reschedules the expiry from the moment of the call; {"ttl_seconds": null} clears it and makes the file permanent again.
Expired files are removed by a background sweep, within the hour of their expiry.

Files and retention policy

Retention rules govern telemetry (traces and generation recordings), not your stored files. A 30-day retention rule does not delete files. The one exception is zero data retention: a zero-day scope cannot hold files at all. Uploads are rejected, store: true on a generation is refused, and enabling zero-day on a scope that already holds files permanently deletes them, after an explicit confirmation of the file count.

Quotas

Each organization has a storage quota — a total byte budget (it can vary by plan) and a cap on the number of files. Uploads and stored generation outputs draw from the same budget.
  • Uploads that would exceed the quota are rejected with 413.
  • Generated outputs (store: true) are refused with 413 when the quota is already full. If it fills up while the call runs, the call still succeeds and returns the result inline without storing it, and the response signals the skip.
Since files never expire on their own, the quota is what bounds your storage: delete files you no longer need, or give short-lived ones a ttl_seconds so they clean themselves up. Larger budgets are tied to your plan.

Operations

What’s next

Images

Generate and edit images; feed a file_id for image-to-image.

Video

Seed a video from an uploaded or generated image.

Audio

Transcribe an audio file_id.

Multimodality

How the modalities fit together.