Skip to main content
This is a client-side method to upload files using the signed URL obtained from the /upload/signed-url endpoint.
Pricing:
  • API calls are free
  • Storage fee: $0.001/1GB per day
Quick Start: Use the “Complete Example” section below to get a signed URL and upload a file in one go. Just replace the file path and run the code!

Workflow

  1. Get a signed URL and asset_id from /upload/signed-url
  2. Use the signed URL to upload your file directly to storage
  3. Verify upload completion via /get-metadata (poll until upload_status is SUCCESS)

Complete Example (Ready to Test)

Here’s a complete example that shows how to get a signed URL and use it for upload:
import requests

BASE_URL = "https://mavi-backend.memories.ai/serve/api/v2"
API_KEY = "sk-mai-this_a_test_string_please_use_your_generated_key_during_testing"
HEADERS = {
    "Authorization": f"{API_KEY}"
}

# Step 1: Get signed URL from /upload/signed-url
def get_signed_url(original_filename: str) -> tuple[str, str]:
    """Get a signed URL and asset_id for file upload"""
    url = f"{BASE_URL}/upload/signed-url"
    data = {"original_filename": original_filename}
    response = requests.post(url, json=data, headers=HEADERS)
    result = response.json()
    print(f"Signed URL response: {result}")
    return result['data']['signed_url'], result['data']['asset_id']

# Step 2: Upload file using the signed URL
def upload_by_signed_url(signed_url: str, file_path: str) -> tuple[int, str]:
    """
    Upload file using signed URL
    
    Args:
        signed_url: The signed URL obtained from /upload/signed-url
        file_path: Path to the local file to upload
    
    Returns:
        Tuple of (status_code, response_text)
    """
    with open(file_path, "rb") as f:
        files = {"file": (file_path, f)}
        resp = requests.post(signed_url, files=files)
    
    return resp.status_code, resp.text

# Complete workflow - ready to test
if __name__ == "__main__":
    # Replace with your actual file path
    file_path = "path/to/your/video.mp4"
    original_filename = "video.mp4"
    
    # Get signed URL and asset_id
    print("Step 1: Getting signed URL...")
    signed_url, asset_id = get_signed_url(original_filename)
    print(f"Asset ID: {asset_id}")
    print(f"Signed URL: {signed_url[:100]}...")
    
    # Upload file
    print("\nStep 2: Uploading file...")
    status, response = upload_by_signed_url(signed_url, file_path)
    print(f"Upload status: {status}")
    print(f"Upload response: {response}")
    print(f"\nUse asset_id '{asset_id}' for subsequent API calls (e.g., /video/edit, /transcriptions)")

Code Examples (Using Existing Signed URL)

// Assuming you have the signed URL
const signedUrl = "https://storage.example.com/upload?signature=...";
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];

const formData = new FormData();
formData.append('file', file);

const response = await fetch(signedUrl, {
  method: 'POST',
  body: formData
});

if (response.ok) {
  console.log('Upload successful');
} else {
  console.error('Upload failed:', response.status);
}

Parameters

ParameterTypeRequiredDescription
signed_urlstringYesThe pre-signed URL obtained from /upload/signed-url
fileFile/BlobYesThe file to upload

Response

Returns HTTP status code and response text from the storage service. Success Response (200):
Status: 200 OK
File uploaded successfully
Error Response (4xx/5xx):
Status: 400/500
Error message from storage service

Confirming Upload Completion

After uploading via the signed URL, the MAVI backend automatically detects the file. Use the Get Metadata endpoint with the asset_id (returned in Step 1) to verify the upload is complete:
# Step 3: Confirm upload is complete
metadata = get_metadata(asset_id)
status = metadata['data']['resource'][0]['upload_status']
print(f"Upload status: {status}")  # Should be "SUCCESS"
StatusDescription
WAITINGUpload request received, waiting to process
UPLOADINGFile is being uploaded and processed
SUCCESSUpload completed — asset is ready for use
FAILEDUpload failed — retry the upload
Only assets with upload_status: "SUCCESS" can be used in subsequent API calls (transcription, editing, etc.). Poll the Get Metadata endpoint until the status is SUCCESS before proceeding.

Notes

  • This upload happens directly to cloud storage (e.g., GCS)
  • No authentication headers needed — the URL contains the signature
  • Signed URLs expire after the time specified in expires_in (typically 26 hours)
  • Make sure to upload the file before the URL expires
  • Supports files up to 5 GB (for files under 500 MB, you can also use the simpler direct upload)