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

# Upload File

> Upload media to the gallery using multipart form data or a JSON payload.

## Method

`POST` `/v1/gallery/upload`

## Multipart Form Fields

* `file` (**required**) – Binary file upload.
* `folderId` – UUID of destination folder.
* `fileName` – Override the stored filename (defaults to the uploaded name).
* `publish` – Truthy value (`1`, `true`, `on`, `yes`) keeps the file public; otherwise it remains private.
* `metadata` – JSON string merged into file metadata.
* `width`, `height`, `duration` – Optional numeric hints for images/videos.

## JSON Body Parameters

<ParamField name="file" type="object">Includes `name`, `size` (bytes), `type` (MIME), and base64 `data`.</ParamField>
<ParamField name="folderId" type="uuid">Destination folder.</ParamField>
<ParamField name="metadata" type="object">Custom metadata stored on the record.</ParamField>
<ParamField name="fileName" type="string">Override the stored filename.</ParamField>
<ParamField name="isPublic" type="boolean">Defaults to `true`. Set `false` to keep the asset private.</ParamField>

## Headers

<ParamField header="Authorization" type="string">Bearer token (e.g. <code>Authorization: Bearer YOUR\_API\_KEY</code>)</ParamField>
<ParamField header="content-type" type="string">`multipart/form-data` or `application/json`</ParamField>

## Request Example

<RequestExample>
  ```bash cURL (multipart) theme={null}
  curl -X POST https://api.voyantcloud.com/v1/gallery/upload \
    -H "Authorization: Bearer $VOYANT_API_KEY" \
    -F "file=@hero.jpg" \
    -F "folderId=00000000-0000-0000-0000-000000000000" \
    -F "publish=true" \
    -F "metadata={\"campaign\":\"summer-2025\"}"
  ```

  ```javascript Node.js (multipart) theme={null}
  const form = new FormData()
  form.append("file", fs.createReadStream("./hero.jpg"))
  form.append("folderId", "00000000-0000-0000-0000-000000000000")
  form.append("publish", "true")

  const res = await fetch("https://api.voyantcloud.com/v1/gallery/upload", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.VOYANT_API_KEY}` },
    body: form,
  })
  const payload = await res.json()
  ```

  ```python Python (JSON) theme={null}
  import base64, os, requests

  file_path = "hero.jpg"
  with open(file_path, "rb") as fh:
    encoded = base64.b64encode(fh.read()).decode("utf-8")

  payload = {
    "file": {
      "name": "hero.jpg",
      "size": os.path.getsize(file_path),
      "type": "image/jpeg",
      "data": encoded,
    },
    "folderId": "00000000-0000-0000-0000-000000000000",
    "metadata": {"campaign": "summer-2025"},
    "isPublic": True,
  }

  resp = requests.post(
    "https://api.voyantcloud.com/v1/gallery/upload",
    headers={
      "Authorization": f"Bearer {os.environ['VOYANT_API_KEY']}",
      "content-type": "application/json",
    },
    json=payload,
  )
  result = resp.json()
  ```
</RequestExample>

## Response

<ResponseExample>
  ```json 202 Accepted theme={null}
  {
    "fileId": "gal_file_123",
    "jobId": "gallery-job-456",
    "status": "processing",
    "publicUrls": {
      "primary": "https://cdn.voyantcloud.com/gallery/ws_abc/hero.jpg",
      "thumbnail": "https://cdn.voyantcloud.com/gallery/ws_abc/hero.jpg?w=200,h=200"
    }
  }
  ```
</ResponseExample>

<Tip>The upload response is asynchronous. Poll <code>/v1/gallery/files</code> or subscribe to <code>gallery.file.uploaded</code> webhooks to know when processing finishes.</Tip>

<Note>For videos larger than 100MB, use the [Upload Large Video](/api-reference/gallery/upload-video) endpoint which supports resumable uploads.</Note>
