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

# Upload Workflow

> Upload media and document assets for SoluDesks API content workflows.

Uploads are a two-stage flow used by SoluDesks API families such as LearnHub. First create an upload session through SoluDesks. Then upload the bytes directly to the returned storage URL and complete the session.

## 1. Initiate Upload

```bash theme={null}
curl "https://staging.api.soludesks.com/v1/external/learnhub/uploads" \
  -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 3b3a7f97-9b41-4bc9-8c55-8f00a5d2147a" \
  -H "Content-Type: application/json" \
  -d '{
    "upload_type": "VIDEO",
    "file_name": "intro.mp4",
    "file_size": 52428800,
    "content_type": "video/mp4"
  }'
```

The response includes either `presigned_url` for single-part uploads or `presigned_urls` plus `multipart_upload_id` for multipart uploads.

## 2. Upload To Storage

For a single-part upload, send the file with the returned `required_headers`.

```bash theme={null}
curl "$PRESIGNED_URL" \
  -X PUT \
  -H "Content-Type: video/mp4" \
  --upload-file ./intro.mp4
```

For multipart uploads, upload each part to its matching presigned URL. You can request more part URLs with the sign-parts endpoint.

## 3. Complete Upload

```bash theme={null}
curl "https://staging.api.soludesks.com/v1/external/learnhub/uploads/UPLOAD_ID/complete" \
  -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

For multipart uploads, include the uploaded part numbers and ETags.

```json theme={null}
{
  "parts": [
    {
      "part_number": 1,
      "etag": "\"etag-from-storage\""
    }
  ]
}
```

## 4. Use The Upload ID

After completion, use the upload session ID in fields such as `cover_image_upload_session_id`, `preview_video_upload_session_id`, `video_upload_session_id`, `document_upload_session_id`, `image_upload_session_id`, `content_media[].upload_session_id`, or `resource_upload_session_ids`.
