# Async jobs and files

Video, music, long audio and task aliases run as jobs. No standard
exists for this, so the shape is the gateway's.

## Submit

    POST /gw/jobs
    { "model": "clip", "input": { "prompt": "a red cube rotating", "seconds": "5" },
      "native": { ... }, "gw_context": { "run": "r1" } }

    -> 202
    { "job_id": "job_...", "status": "queued", "model": "clip",
      "created_at": "...", "updated_at": "...", "poll_after_ms": 2000 }

`input` must satisfy the alias's `input_schema` (see `/v1/models`).
The job is acknowledged only once it is durably recorded: a gateway
restart loses no accepted job.

## Poll

    GET /gw/jobs/{job_id}

| `status` | Meaning | Also present |
|---|---|---|
| `queued` | Accepted, not started | `poll_after_ms` |
| `running` | In flight at the provider | `poll_after_ms` |
| `succeeded` | Done | `output`, `x_gateway` |
| `failed` | Terminal | `error` |

`output.files[]` carries `{file_id, url, mime_type, bytes, expires_at,
source_url}`. `url` is a gateway URL (`/gw/files/{id}`) that your key
can read; `source_url` is the provider's own link, which expires on its
schedule. A task alias's `output.completion` is the dialect-shaped
completion the task endpoint returned.

Honour `poll_after_ms`. Jobs and their files are kept for a retention
window and then reaped.

## `/v1/videos` — the OpenAI video shape

The same job, in the shape the OpenAI SDK's `videos` client speaks:

    POST /v1/videos   (multipart, as the SDK sends it, or JSON)
      model=clip  prompt=...  seconds=5
    -> 202 {"id":"job_...","object":"video","status":"queued","progress":0}
    GET  /v1/videos/{id}           -> {"status":"queued|in_progress|completed|failed", ...}
    GET  /v1/videos/{id}/content   -> the video bytes

## Files

    POST /gw/files      multipart/form-data with one file part
    -> 201 {"file_id":"file_...","mime_type":"...","bytes":...,"expires_at":"..."}
    GET  /gw/files/{id} -> the bytes (only with the key that uploaded it, or whose job produced it)

`file_id` is accepted by `POST /v1/audio/transcriptions` and
`POST /v1/images/edits` as a JSON body `{"model":...,"file_id":...}` in
place of multipart — the only form that can be reused across calls.
