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

# Uploading Media

> How to upload files directly to Dreep Storage using Presigned URLs.

Dreep uses a highly efficient, two-step upload process that allows your users (or your backend) to upload files directly to the underlying Dreep storage edge. This completely bypasses the primary Dreep API server, preventing bottlenecks and eliminating strict file-size limits on the API layer.

<Note>
  For files you're happy to send through the API, a single multipart
  `POST /api/v1/upload` is simpler — see [Upload Media](/api-reference/upload/upload-media).
  The two-step flow below is for large files and browser uploads.
</Note>

### Step 1: Generate a Presigned URL

Make a `POST` request to `/api/v1/upload/presign` with the details of the file
you intend to upload (size, mime-type, and where it should land).

The destination is named exactly the same way as a direct upload: a `folder`
path, a full `key`, or a `folderId`. Missing folders are created for you — see
[Folders & Paths](/guides/folders-and-paths).

```bash theme={null}
curl -X POST https://api.dreep.cloud/api/v1/upload/presign \
  -H "Authorization: Bearer drp_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "video.mp4",
    "contentType": "video/mp4",
    "sizeBytes": 52428800,
    "folder": "launch/2024"
  }'
```

The API will return an `uploadUrl` and a tracking `id`.

```json theme={null}
{
  "id": "2f928a3f-1d2a-4a2b-8a8b-123456789abc",
  "uploadUrl": "https://cdn.dreep.cloud/..."
}
```

If you send a `contentHash` that matches content Dreep already stores, the
response comes back with `"alreadyExists": true` and no `uploadUrl` — skip
Step 2 and go straight to Step 3.

### Step 2: PUT the file to the Upload URL

Take the `uploadUrl` returned from Step 1, and make an HTTP `PUT` request directly to it containing the raw file binary.

**Crucial requirements for Step 2:**

1. The HTTP method **MUST** be `PUT` (not `POST`).
2. The `Content-Type` header **MUST** exactly match the `mimeType` you provided in Step 1.
3. The `Content-Length` header **MUST** exactly match the `sizeBytes` you provided in Step 1.

<CodeGroup>
  ```javascript Node.js / Browser theme={null}
  // 1. Get the presigned URL from your backend / Dreep API
  const { uploadUrl, id } = await getPresignedUrlFromBackend(file);

  // 2. Upload directly to Dreep Storage
  const response = await fetch(uploadUrl, {
  method: "PUT",
  headers: {
  "Content-Type": file.type,
  // Note: The browser automatically sets Content-Length based on the file object
  },
  body: file,
  });

  if (response.ok) {
  console.log("Upload successful! File ID is:", id);
  }

  ```

  ```python Python theme={null}
  import requests

  # 1. Get the presigned URL
  upload_url = "https://cdn.dreep.cloud/..."
  file_path = "video.mp4"
  mime_type = "video/mp4"

  # 2. Upload directly to Dreep Storage
  with open(file_path, "rb") as f:
      headers = { "Content-Type": mime_type }
      response = requests.put(upload_url, data=f, headers=headers)

  if response.status_code == 200:
      print("Upload successful!")
  ```
</CodeGroup>

### Step 3: Confirm the upload

Once the `PUT` succeeds, call the confirm endpoint with the `id` from Step 1.
Dreep verifies the object landed, reads its metadata, applies any transform,
and marks the asset `ready`. Until you do this the asset stays `pending` and is
excluded from media listings.

```bash theme={null}
curl -X POST https://api.dreep.cloud/api/v1/upload/2f928a3f-1d2a-4a2b-8a8b-123456789abc/confirm \
  -H "Authorization: Bearer drp_live_xxxxx"
```

### Uploading to Secure Folders

By default, uploads go to your project's default public folder. To upload an asset into a Private or Signed folder, name that folder in Step 1 — by `folder` path or by `folderId`.

Folders created on the fly by a path inherit their parent's access control, so uploading to `invoices/2024/q1` under a Private `invoices` folder keeps the new subfolders private. See [Folders & Paths](/guides/folders-and-paths).

If you upload into a Signed folder, you can optionally provide `expiresInSeconds` during Step 1 to override the folder's default expiration just for this specific asset.

***

## Supported File Formats

Dreep supports direct uploads up to **500MB** per file. Uploaded files are categorized into three asset kinds:

| Asset Kind   | Supported Formats / Extensions                                                                                                                                                                            | Pipeline Behavior                                                  |
| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------- |
| **Image**    | JPEG (`.jpeg`, `.jpg`), PNG (`.png`), WebP (`.webp`), GIF (`.gif`), TIFF (`.tiff`), BMP (`.bmp`), SVG (`.svg`), HEIC (`.heic`), HEIF (`.heif`)                                                            | Format conversion, Resizing, Compression                           |
| **Video**    | MP4 (`.mp4`), MOV (`.mov`), WEBM (`.webm`)                                                                                                                                                                | Format conversion, Trimming, HLS Streaming                         |
| **Raw File** | **Documents**: PDF (`.pdf`), Word (`.doc`, `.docx`), Excel (`.xls`, `.xlsx`), PowerPoint (`.ppt`, `.pptx`)<br />**Text/Data**: CSV (`.csv`), TXT (`.txt`), JSON (`.json`)<br />**Archives**: ZIP (`.zip`) | Stored and served directly as-is. Transformations are not allowed. |

***

## Format Conversion Rules

When requesting format conversions during upload or delivery (via the `format` parameter), Dreep strictly enforces **media family boundaries**:

* **Image → Image**: Images can be converted to `jpeg`, `png`, `webp`, `avif`, `gif`, or `tiff`.
* **Video → Video**: Videos can be converted to `mp4`, `webm`, `mov`, `hls` (`.m3u8`), or `gif` (animated GIF clip).
* **Cross-Family Restrictions**: Converting an Image to a Video format (or Video to an Image format other than `gif`) is blocked and returns an `Unsupported format conversion` error.
* **Raw Files**: Non-transformable raw files (PDF, DOCX, ZIP) cannot be converted to any target format.
