> For the complete documentation index, see [llms.txt](https://docs.viesus.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.viesus.com/reference/cloud-api/uploading.md).

# Uploading

Every enhancement starts with an upload. The upload creates a persistent file record that you reference by `id` in subsequent enhancement requests.

***

## Which method to use

| Your file is...                 | Method                                          |
| ------------------------------- | ----------------------------------------------- |
| At a reachable public URL       | [Upload from URL](#upload-from-a-url) — simpler |
| On your server or local machine | [Signed upload URL](#upload-with-a-signed-url)  |

***

## Upload from a URL

The simplest method. VIESUS Cloud fetches the file directly from the URL you provide.

```graphql
mutation {
  createUploadFromUrl(
    input: {
      url: "https://www.example.com/photo.jpg"
    }
  ) {
    id
    status
    filesize
    mimetype
    extension
    originalFilename
    filename
    width
    height
    url
    startedAt
    finishedAt
    duration
  }
}
```

Save the returned `id` — you need it to trigger enhancements.

**curl example:**

```bash
curl -X POST https://api.viesus.cloud/graphql \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR-API-KEY" \
  -d '{
    "query": "mutation { createUploadFromUrl(input: { url: \"https://example.com/photo.jpg\" }) { id status } }"
  }'
```

***

## Upload with a signed URL

For files on your server, local machine, or user uploads that go directly from the browser to VIESUS Cloud storage. This is a three-step process.

{% stepper %}
{% step %}

#### Request a signed URL

```graphql
mutation {
  createSignedUploadUrl(
    input: {
      filename: "photo.jpg"
      filesize: 2048000
      mimetype: "image/jpeg"
    }
  ) {
    uploadId
    uploadUrl
  }
}
```

{% hint style="danger" %}
`filesize` and `mimetype` must match the actual file. Incorrect values cause the upload to fail at the final step.
{% endhint %}
{% endstep %}

{% step %}

#### PUT the file to the signed URL

Use the `uploadUrl` from the previous step to PUT the file directly to storage:

**Node.js:**

```js
const fs = require('fs');

const filePath = './photo.jpg';
const fileBuffer = fs.readFileSync(filePath);
const stats = fs.statSync(filePath);

await fetch(uploadUrl, {
  method: 'PUT',
  body: fileBuffer,
  headers: {
    'Content-Type': 'image/jpeg',
    'Content-Length': stats.size.toString(),
  },
});
```

**Browser (file input):**

```js
async function putFile(uploadUrl, file) {
  await fetch(uploadUrl, {
    method: 'PUT',
    body: await file.arrayBuffer(),
    headers: {
      'Content-Type': file.type,
    },
  });
}
```

**curl:**

```bash
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg
```

{% endstep %}

{% step %}

#### Complete the upload

Finalize using the `uploadId` from the first step:

```graphql
mutation {
  completeSignedUpload(id: "uploadId") {
    id
    status
    filesize
    mimetype
    width
    height
    url
    startedAt
    finishedAt
    duration
  }
}
```

The returned `id` is the upload ID for all subsequent enhancement requests.
{% endstep %}
{% endstepper %}

***

## Upload response fields

<table><thead><tr><th width="246.800048828125">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>Upload identifier — required for enhancement mutations</td></tr><tr><td><code>status</code></td><td>Upload state</td></tr><tr><td><code>filesize</code></td><td>File size in bytes</td></tr><tr><td><code>mimetype</code></td><td>Detected MIME type</td></tr><tr><td><code>extension</code></td><td>File extension</td></tr><tr><td><code>originalFilename</code></td><td>Filename as uploaded</td></tr><tr><td><code>filename</code></td><td>Storage filename</td></tr><tr><td><code>width</code> / <code>height</code></td><td>Image dimensions in pixels (0 for PDFs)</td></tr><tr><td><code>url</code></td><td>URL to access the original uploaded file</td></tr><tr><td><code>startedAt</code> / <code>finishedAt</code></td><td>Upload timestamps (ISO 8601)</td></tr><tr><td><code>duration</code></td><td>Upload processing time in milliseconds</td></tr></tbody></table>

***

## Upload retention

Uploads are stored for **30 days** by default, then automatically deleted. To change the default retention for new uploads:

```graphql
mutation {
  updateFileRetention(days: 7) {
    uploadRetentionDays
  }
}
```

This setting applies to uploads made after the change — existing uploads keep their original retention.

To delete an upload immediately:

```graphql
mutation {
  deleteUploads(ids: ["upload-id-1", "upload-id-2"]) {
    deletedUploadIds
  }
}
```

***

## Multiple enhancements from one upload

The same upload can be enhanced multiple times with different parameters. You do not need to re-upload the file:

```graphql
mutation EnhanceA {
  createEnhancedImage(uploadId: "upload-id", input: { mode: ENHANCE }) {
    id status
  }
}

mutation EnhanceB {
  createEnhancedImage(uploadId: "upload-id", input: { mode: ENHANCE, upscalingFactor: X2 }) {
    id status
  }
}
```

This is useful for generating multiple output variants (e.g., with and without upscaling) without paying upload costs twice.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.viesus.com/reference/cloud-api/uploading.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
