---
title: "Create a presigned upload"
method: POST
path: "/documents/uploads"
tags: ["Documents"]
---

# Create a presigned upload

`POST /documents/uploads`

## Request

- Base URL: `https://dataroom.corgi.com/api/v1`
- URL: `https://dataroom.corgi.com/api/v1/documents/uploads`
- Auth: HTTP bearer

Mint a presigned direct-to-storage upload for a real/large file — no base64 through the API. Nothing is created here. Step 1 of 3: (1) POST here; (2) `PUT` the bytes to the returned `uploadUrl`, sending EVERY header from the response's `headers` map (on encrypted S3 that includes a signed `x-amz-server-side-encryption` you must echo, or the PUT fails 403), e.g. `curl -T file.pdf -H "Content-Type: <type>" -H "x-amz-server-side-encryption: AES256" "<uploadUrl>"`; (3) POST /documents/uploads/finalize with the returned `storageKey` and `token` to register the document. The response is `{ uploadUrl, storageKey, method: "PUT", headers, expiresInSec, token }`; PUT with the given `headers` and finalize before `expiresInSec` elapses. Max 100 MiB. On the local/proxy storage backend `uploadUrl` points at PUT /documents/uploads/blob. Scope: `documents:write`.

## Request body

- object
  - `filename` string, required: Filename including extension, e.g. board-deck.pdf
  - `contentType` string: MIME type you will PUT with (default application/octet-stream)
  - `folderId` string: Destination library folder id; omit for the top level
  - `sizeBytes` integer: File size in bytes, if known — binds the URL and rejects over-cap files early

## Response `201`

A presigned upload (`uploadUrl`, `storageKey`, `method`, `headers`, `expiresInSec`, `token`)

## Other responses

- `400`: Validation error

---

[API](https://skmtc.dev/corgi/apis/dataroom-api.md) - [All operations](https://skmtc.dev/corgi/apis/dataroom-api/llms.txt) - [OpenAPI document](https://skmtc.dev/corgi/apis/dataroom-api/revisions/73f75ef04a00?raw)
