Upload Pipeline

Presigned URL uploads that go directly to storage, bypassing your API server.

How It Works

text
Client                    API                     R2/S3
  │                        │                        │
  │─── POST /presign ─────▶│                        │
  │◀── upload_url + key ───│                        │
  │                        │                        │
  │─── PUT upload_url ────────────────────────────▶│
  │◀── 200 OK ─────────────────────────────────────│
  │                        │                        │
  │─── POST /complete ────▶│                        │
  │◀── asset created ──────│── enqueue transcode ──▶│
  │                        │                        │

The file never touches your API server — it goes directly from the browser to R2/S3 via presigned URL. This keeps your API fast and avoids memory/bandwidth issues with large files.

Step 1: Request Presigned URL

bash
curl -X POST /api/mediakit/uploads/presign \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "vacation.mp4",
    "content_type": "video/mp4",
    "file_size": 104857600,
    "asset_type": "video",
    "title": "Vacation Highlights"
  }'

Request Body

FieldTypeDescription
filenamestringOriginal filename
content_typestringMIME type (video/mp4, image/jpeg, etc.)
file_sizenumberFile size in bytes
asset_typestring"video" or "image"
titlestringDisplay title

Step 2: Upload to Presigned URL

bash
curl -X PUT "PRESIGNED_URL" \
  -H "Content-Type: video/mp4" \
  --data-binary @vacation.mp4

Or in JavaScript with progress tracking:

upload.ts
const xhr = new XMLHttpRequest();
xhr.open("PUT", presignedUrl);
xhr.setRequestHeader("Content-Type", file.type);

xhr.upload.onprogress = (e) => {
  const percent = Math.round((e.loaded / e.total) * 100);
  console.log(`Upload progress: ${percent}%`);
};

xhr.onload = () => {
  if (xhr.status === 200) {
    // Step 3: Confirm upload
    completeUpload(assetId, key);
  }
};

xhr.send(file);

Step 3: Confirm Upload

bash
curl -X POST /api/mediakit/uploads/complete \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"asset_id": 1, "key": "uploads/abc/vacation.mp4"}'

After confirming, if the asset is a video, a transcode job is automatically enqueued. For images, the asset is marked as "ready" immediately.

Delete an Asset

bash
curl -X DELETE /api/mediakit/uploads/1 \
  -H "Authorization: Bearer TOKEN"

This deletes the asset record, all quality renditions, and the original file from storage.

Size Limits

Default max upload size is 10 GB (configurable via MAX_UPLOAD_SIZE_MB env var). Since uploads go directly to R2/S3, your API server's memory is not affected.