> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mosaic.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload Flow

> How asset uploads work for video, audio, and image inputs.

Some agent nodes accept images, audio, or videos as parameters. Use these endpoints to upload files and get UUIDs that you can pass to `update_params` when running agents.

## Flow

```text theme={null}
POST /uploads/{type}/get_upload_url  →  POST file to upload_url  →  POST /uploads/{type}/finalize_upload
```

1. Call `get_upload_url` to get a signed URL and the asset UUID
2. POST your file to that URL (include `upload_fields` as form data)
3. Call `finalize_upload` to confirm the upload

Use the returned UUID in `update_params`:

```json theme={null}
{
  "update_params": {
    "NODE_ID": {
      "audio_id": "your-uploaded-uuid"
    }
  }
}
```

## Full Example

Upload audio and use it in `update_params`:

<CodeGroup>
  ```python Python theme={null}
  import requests

  API_KEY = "mk_your_api_key"
  BASE = "https://api.mosaic.so"

  # 1. Get upload URL
  data = requests.post(f"{BASE}/uploads/audio/get_upload_url",
      headers={"Authorization": f"Bearer {API_KEY}"}).json()

  # 2. Upload file
  with open("music.mp3", "rb") as f:
      requests.post(data["upload_url"], data=data["upload_fields"], files={"file": f})

  # 3. Finalize
  result = requests.post(f"{BASE}/uploads/audio/finalize_upload",
      headers={"Authorization": f"Bearer {API_KEY}"},
      json={"audio_id": data["audio_id"]}).json()

  # 4. Use in update_params
  run = requests.post(f"{BASE}/agent/YOUR_AGENT_ID/run",
      headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
      json={
          "video_urls": ["https://youtube.com/watch?v=dQw4w9WgXcQ"],
          "update_params": {
              "AUDIO_NODE_ID": {"audio_id": result["audio_id"]}
          }
      }).json()

  print(f"Run ID: {run['run_id']}")
  ```

  ```javascript JavaScript theme={null}
  const API_KEY = "mk_your_api_key";
  const BASE = "https://api.mosaic.so";

  // 1. Get upload URL
  const data = await fetch(`${BASE}/uploads/audio/get_upload_url`, {
    method: "POST",
    headers: { "Authorization": `Bearer ${API_KEY}` }
  }).then(r => r.json());

  // 2. Upload file
  const formData = new FormData();
  Object.entries(data.upload_fields).forEach(([k, v]) => formData.append(k, v));
  formData.append("file", audioFile);
  await fetch(data.upload_url, { method: "POST", body: formData });

  // 3. Finalize
  const result = await fetch(`${BASE}/uploads/audio/finalize_upload`, {
    method: "POST",
    headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ audio_id: data.audio_id })
  }).then(r => r.json());

  // 4. Use in update_params
  const run = await fetch(`${BASE}/agent/YOUR_AGENT_ID/run`, {
    method: "POST",
    headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({
      video_urls: ["https://youtube.com/watch?v=dQw4w9WgXcQ"],
      update_params: {
        "AUDIO_NODE_ID": { audio_id: result.audio_id }
      }
    })
  }).then(r => r.json());

  console.log(`Run ID: ${run.run_id}`);
  ```
</CodeGroup>

## Supported Formats

| Type  | Formats                             | Max Size | Max Duration                                                        |
| ----- | ----------------------------------- | -------- | ------------------------------------------------------------------- |
| Video | MP4, MOV, AVI, WebM, MKV, M4V       | 5 GB     | Plan-based: 2 hours on Standard, 5 hours on Professional/Enterprise |
| Audio | MP3, WAV, M4A, FLAC, OGG, AAC, Opus | 500 MB   | 5 hours                                                             |
| Image | PNG, JPEG, GIF, WebP, SVG           | 50 MB    | -                                                                   |

## Errors

| Error | Cause                             |
| ----- | --------------------------------- |
| 404   | Upload ID not found or expired    |
| 400   | File not uploaded before finalize |
| 413   | File exceeds size limit           |
