Skip to main content
GET
/
api
/
media
/
upload
Upload Media
curl --request GET \
  --url https://api.example.com/api/media/upload
{
  "status": "<string>",
  "data": {
    "server": "<string>",
    "token": "<string>"
  },
  "message": "<string>",
  "code": "<string>"
}

Overview

This endpoint initiates the media upload process by registering a new file upload with Mediastream. It returns an upload server URL and token that you’ll use to upload file chunks directly to Mediastream’s servers.
This endpoint only registers the upload. The actual file chunks are uploaded directly to the Mediastream server URL returned in the response.

Authentication

This endpoint requires authentication. The backend automatically includes your Mediastream API credentials configured in the environment variables:
  • MEDIASTREAM_API_URL - Your Mediastream API base URL
  • MEDIASTREAM_API_KEY - Your API authentication token

Query Parameters

size
integer
required
The total size of the file to upload in bytes.Example: 52428800 (50MB file)
file_name
string
required
The name of the file being uploaded, including the file extension.Example: "my-video.mp4"
type
string
The upload type. Defaults to "remote" for client-side uploads.Supported values:
  • remote - Upload chunks directly from the client to Mediastream

Response

status
string
The status of the request. Returns "success" when upload is registered successfully.
data
object
Upload credentials and server information.
server
string
The base URL where file chunks should be uploaded. Each chunk is uploaded to {server}/{chunkNumber}.Example: "https://mdstrm.com/upload/abc123"
token
string
Authentication token for uploading chunks. Include this in each chunk upload request.Example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Request Example

curl -X GET "https://your-app.com/api/media/upload?size=52428800&file_name=my-video.mp4&type=remote" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer YOUR_AUTH_TOKEN"

Response Example

{
  "status": "success",
  "data": {
    "server": "https://mdstrm.com/upload/abc123def456",
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
  }
}

Uploading File Chunks

After registering the upload, split your file into chunks and upload each chunk sequentially:

Chunked Upload Process

1

Register Upload

Call this endpoint with file metadata to get server URL and token
2

Split File

Divide the file into 10MB chunks using File.slice()
const chunkSize = 10 * 1024 * 1024 // 10MB
const totalChunks = Math.ceil(file.size / chunkSize)
3

Upload Each Chunk

Upload chunks sequentially to {server}/{chunkNumber}
for (let i = 1; i <= totalChunks; i++) {
  const start = (i - 1) * chunkSize
  const end = Math.min(file.size, start + chunkSize)
  const chunk = file.slice(start, end)
  
  const formData = new FormData()
  formData.append('file', chunk)
  formData.append('name', file.name)
  formData.append('token', token)
  
  await axios.post(`${server}/${i}`, formData, {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
  })
}
4

Track Progress

Monitor upload progress using Axios onUploadProgress callback
onUploadProgress: (event) => {
  const progress = (event.loaded / event.total) * 100
  console.log(`Upload progress: ${progress}%`)
}

Complete Upload Example

const uploadFile = async (file) => {
  // Step 1: Register upload
  const response = await axios.get('/api/media/upload', {
    params: {
      size: file.size,
      file_name: file.name,
      type: 'remote',
    },
  })

  const { server, token } = response.data.data
  
  // Step 2: Upload chunks
  const chunkSize = 10 * 1024 * 1024 // 10MB
  const totalChunks = Math.ceil(file.size / chunkSize)
  
  for (let i = 1; i <= totalChunks; i++) {
    const start = (i - 1) * chunkSize
    const end = Math.min(file.size, start + chunkSize)
    const chunk = file.slice(start, end)
    
    const formData = new FormData()
    formData.append('file', chunk)
    formData.append('name', file.name)
    if (token) formData.append('token', token)
    
    await axios.post(`${server}/${i}`, formData, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      onUploadProgress: (event) => {
        if (event.total) {
          const chunkProgress = (event.loaded / event.total) * (1 / totalChunks) * 100
          const totalProgress = ((i - 1) / totalChunks) * 100 + chunkProgress
          console.log(`Upload progress: ${totalProgress.toFixed(0)}%`)
        }
      },
    })
  }
  
  console.log('Upload complete!')
}

File Format Support

Mediastream supports various video formats:

MP4

H.264/H.265 codec

MOV

QuickTime format

AVI

Audio Video Interleave

MKV

Matroska container

WebM

VP8/VP9 codec

FLV

Flash Video format

File Size Limits

File size limits depend on your Mediastream account tier:
  • Free Tier: Up to 500MB per file
  • Pro Tier: Up to 5GB per file
  • Enterprise: Custom limits available
Files exceeding your account’s size limit will be rejected during registration. Upgrade your plan for larger file support.

Error Responses

status
string
Returns "error" when the request fails.
message
string
Human-readable error message describing what went wrong.
code
string
Machine-readable error code for programmatic handling.Common error codes:
  • invalid_file_size - File size is 0 or exceeds limit
  • invalid_file_name - File name contains invalid characters
  • quota_exceeded - Account storage quota exceeded
  • invalid_api_key - API authentication failed
  • rate_limit_exceeded - Too many upload requests

Error Response Example

{
  "status": "error",
  "message": "File size exceeds maximum allowed limit of 5GB",
  "code": "invalid_file_size"
}

Best Practices

Use 10MB chunks for optimal performance:
  • Smaller chunks (5MB): More requests, slower overall speed
  • Larger chunks (20MB+): Higher failure rate on slow connections
  • 10MB: Best balance for reliability and speed
Implement retry logic for failed chunks:
const uploadChunkWithRetry = async (chunk, url, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await axios.post(url, chunk)
    } catch (error) {
      if (attempt === maxRetries) throw error
      await new Promise(r => setTimeout(r, 1000 * attempt))
    }
  }
}
Provide real-time feedback to users:
  • Show overall progress percentage
  • Display estimated time remaining
  • Indicate current chunk being uploaded
  • Allow users to cancel in-progress uploads
Validate files before uploading:
const validateFile = (file) => {
  const maxSize = 5 * 1024 * 1024 * 1024 // 5GB
  const allowedTypes = ['video/mp4', 'video/quicktime', 'video/x-msvideo']
  
  if (file.size > maxSize) {
    throw new Error('File too large')
  }
  if (!allowedTypes.includes(file.type)) {
    throw new Error('Unsupported file format')
  }
}

Implementation

The backend implementation proxies requests to Mediastream’s API:
<?php

namespace App\Http\Controllers\Api\Media;

use App\Http\Controllers\Controller;
use App\Http\Services\MediastreamService;
use Illuminate\Http\Request;

class UploadMediaController extends Controller
{
    public function upload(Request $request)
    {
        $size = $request->query('size');
        $fileName = $request->query('file_name');

        $response = MediastreamService::request(
            '/media/upload',
            'get',
            [
                'size' => $size,
                'file_name' => $fileName,
            ]
        );

        return $response->json();
    }
}
The MediastreamService automatically includes authentication headers using credentials from your .env file.

Create Episode

Link uploaded media to episodes

Series Management

Manage series for organizing content

See Also

Build docs developers (and LLMs) love