---
title: "Start a direct upload"
method: POST
path: "/files/upload"
tags: ["Files"]
---

# Start a direct upload

`POST /files/upload`

## Request

- Base URL: `https://api.livereacting.com/v1/external`
- URL: `https://api.livereacting.com/v1/external/files/upload`
- Auth: HTTP bearer

Upload a file from your own machine or browser straight to LiveReacting storage. The bytes never
pass through the API, so large files work.

1. Call this endpoint with the file name, type and exact size in bytes.
2. `PUT` each part of the file to its URL from `parts` (no `Authorization` header; the URL is signed).
   Part N holds bytes `(N-1) * partSize` up to `N * partSize - 1`, and must be exactly `parts[].size`
   bytes: storage refuses a part of any other size with 403. You can upload parts in parallel and
   re-send a part that failed.
3. Call `POST /files/upload/complete` with the `uploadToken`.

Same limits as a Studio upload: the extension must match the type, the size must fit your plan's
max file size, and a video upload is refused once your storage is full. Encoding and thumbnails
start after completion, as for a Studio upload.

One-part file (up to 256 MiB):

```bash
FILE=intro.mp4
SIZE=$(wc -c < "$FILE" | tr -d ' ')
START=$(curl -s -X POST https://api.livereacting.com/v1/external/files/upload \
  -H "Authorization: Bearer $LR_API_KEY" -H "Content-Type: application/json" \
  -d "{\"name\": \"$FILE\", \"type\": \"video\", \"size\": $SIZE}")
# -f fails on an HTTP error, -w prints the status, --speed-* stop a stalled transfer
curl -sS -f -o /dev/null -w 'part 1: %{http_code}\n' --speed-limit 1024 --speed-time 60 \
  -T "$FILE" "$(echo "$START" | jq -r '.parts[0].url')"
curl -X POST https://api.livereacting.com/v1/external/files/upload/complete \
  -H "Authorization: Bearer $LR_API_KEY" -H "Content-Type: application/json" \
  -d "{\"uploadToken\": \"$(echo "$START" | jq -r '.uploadToken')\"}"
```

Larger file: run the first four lines above (`FILE`, `SIZE`, `START`), then this, then the
`upload/complete` call above. If a part fails, the loop stops: `PUT` that part again before you complete.

```bash
split -b "$(echo "$START" | jq -r '.partSize')" -a 4 "$FILE" part_
i=0
for PART in part_*; do
  URL=$(echo "$START" | jq -r ".parts[$i].url")
  curl -sS -f -o /dev/null -w "part $((i + 1)): %{http_code}\n" --speed-limit 1024 --speed-time 60 \
    -T "$PART" "$URL" || break
  i=$((i + 1))
done
```

**Browser clients:** the part URLs point to the storage bucket, not to the API. A web page can
upload to them only from an origin the bucket allows; contact us to add yours.

## Request body

- StartUploadRequest
  - `name` string, required: File name shown in the media library. Its extension must match `type`: - video: .mp4 .m4v .mov .flv .webm .ogv .3gp .wmv .avi .mkv - audio: .mp3 .m4a .wav - image: .jpg .jpeg .png .gif .bmp .svg .heic .webp
  - `type` 'video' | 'image' | 'audio', required
  - `size` integer, required: Exact file size in bytes. It must not exceed your plan's max file size.
  - `folderId` string, nullable: Folder to put the file in. The folder type must match `type`. Omit for the root.

## Response `201`

Upload started. Upload the parts, then complete it.

- StartUploadResponse
  - `uploadToken` string: Opaque token. Send it to `POST /files/upload/complete` after every part is uploaded.
  - `partSize` integer: Bytes per part. Part N holds bytes `(N-1) * partSize` up to `N * partSize - 1`; the last part holds the rest. A file up to 256 MiB has exactly one part.
  - `parts` object[]
    - `partNumber` integer
    - `size` integer: Exact number of bytes this part must contain. Storage refuses any other size.
    - `url` string, uri: Presigned storage URL. Send the part's bytes to it with an HTTP `PUT`.
  - `expiresAt` string, date-time: The part URLs and the token stop working at this time (3 days after the start).

## Other responses

- `400`: Validation error or a limit is reached
- `401`: Authentication failed
- `404`: Folder not found or its type does not match
- `429`: Rate limit exceeded

---

[API](https://skmtc.dev/livereacting/apis/livereacting-api.md) · [All operations](https://skmtc.dev/livereacting/apis/livereacting-api/llms.txt) · [OpenAPI document](https://skmtc.dev/livereacting/apis/livereacting-api/revisions/17a9f1677fbf?raw)
