Beecargo

INTRODUCTION

Welcome

API

Overview
  • Upload a file
  • Remote upload
  • Claim a file
  • Agent API
  • Retrieve a file
  • Get file info
  • List files & folders
  • Delete a file

MCP

Overview

LEGAL

PrivacyTermsAcceptable useCookiesRefundsDMCA
PreviousOverviewNextRemote upload

Upload a file

Upload files to Beecargo using the API.


Endpoint

POST https://api.beecargo.net/files/upload

Use this endpoint for files under 4MB. The client examples below show how to automatically handle larger files with multipart upload.

Authentication

Option 1: API key with Bearer token (recommended) - Include your API key in the Authorization header using the Bearer token format (OAuth 2.0 standard). Create an API key in your dashboard settings.

Authorization: Bearer YOUR_API_KEY

Option 2: Anonymous upload - No authentication required. Limited to 25GB per file, expires after 15 days.

Smart upload logic

Automatic file size handling: The code examples below implement smart logic that automatically uses direct upload for files under 4MB and multipart upload for larger files. Just call the uploadFile()function and it handles everything for you!

Sequential uploads for reliability: Our examples use sequential (one-at-a-time) part uploads for maximum stability and compatibility. This works reliably through proxies, VPNs, corporate networks, and file transfer services. While parallel uploads are faster, sequential uploads are more stable and less prone to connection timeouts.

Request examples

Use these ready-to-use code examples that automatically handle any file size. Copy and paste into your project - no modifications needed!

Performance tip: Parallel uploads

The examples below show sequential uploads for simplicity. For 3-6x faster speeds, use parallel chunk uploads (3-6 concurrent chunks depending on file size) - just like the Beecargo web interface does!

Scroll down to see "High-performance parallel upload examples" after the basic examples.

With API key - Bearer token:

# For files < 4MB - Use Bearer token format (OAuth 2.0 standard)

curl -L -X POST https://api.beecargo.net/files/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@/path/to/document.pdf"

# For files >= 4MB, use the client library examples below

# (multipart upload requires multiple API calls)

Anonymous Upload (NOT saved to account):

# File will NOT appear in your dashboard and expires in 15 days

curl -L -X POST https://api.beecargo.net/files/upload \
  -F "file=@/path/to/document.pdf"

Parameters

ParameterTypeRequiredDescription
fileFileYesThe file to upload
folderIdStringNoOptional folder ID to organize the file

Response

The URL returned is a temporary signed URL valid for 24 hours. For permanent access, use the short URL: https://beecargo.net/d/${shortId}

{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "document.pdf",
    "size": 1048576,
    "url": "https://signed-url.cloudflare.com/...",
    "mimeType": "application/pdf",
    "createdAt": "2025-11-16T12:00:00.000Z",
    "isAnonymous": false,
    "expiresAt": null,
    "shortId": "abc123"
  }
}

Note: Anonymous uploads will have isAnonymous: true and expiresAt set to 15 days from upload.

High-performance parallel upload examples

3-6x faster upload speeds

The basic examples above upload chunks one at a time (sequential). The examples below upload multiple chunks simultaneously (parallel) for dramatically faster speeds - matching the performance of the Beecargo web interface.

Sequential upload (basic)

200 parts ร— 2s = 400s (~6.7 min)

Parallel upload (4x)

200 parts รท 4 ร— 2s = 100s (~1.7 min)

Python (parallel)

import requests
import os
import time
from concurrent.futures import ThreadPoolExecutor, as_completed

API_KEY = 'YOUR_API_KEY'  # Get from dashboard settings
BASE_URL = 'https://api.beecargo.net'
MULTIPART_THRESHOLD = 4 *1024* 1024  # 4MB

def get_optimal_parallelism(file_size):
    """Determine optimal number of parallel uploads based on file size"""
    if file_size > 50 *1024**3:  # > 50GB
        return 3
    elif file_size > 10 * 1024**3:  # > 10GB
        return 4
    elif file_size > 1* 1024**3:  # > 1GB
        return 5
    else:
        return 6

def upload_small_file(file_path, folder_id=None):
    """Upload small files (< 4MB) directly"""
    url = f'{BASE_URL}/files/upload'
    file_size = os.path.getsize(file_path)
    file_name = os.path.basename(file_path)

    print(f"๐Ÿ“ค Uploading {file_name} ({file_size / (1024**2):.2f} MB)...")
    
    headers = {}
    if API_KEY:
        headers['Authorization'] = f'Bearer {API_KEY}'
    
    with open(file_path, 'rb') as f:
        files = {'file': (file_name, f)}
        data = {}
        if folder_id:
            data['folderId'] = folder_id
        
        response = requests.post(url, headers=headers, files=files, data=data)
    
    response.raise_for_status()
    result = response.json()
    if not result.get('success'):
        raise Exception(result.get('error', 'Upload failed'))
    
    print(f"โœ… Upload completed!")
    return result['data']

def upload_large_file_parallel(file_path, folder_id=None):
    """Upload large files (>= 4MB) with PARALLEL multipart for maximum speed"""
    file_size = os.path.getsize(file_path)
    file_name = os.path.basename(file_path)

    headers = {'Content-Type': 'application/json'}
    if API_KEY:
        headers['Authorization'] = f'Bearer {API_KEY}'
    
    # 1. Initialize multipart upload
    print(f"๐Ÿ“ฆ Initializing upload for {file_name} ({file_size / (1024**3):.2f} GB)...")
    init_res = requests.post(
        f'{BASE_URL}/files/multipart/init',
        headers=headers,
        json={
            'fileName': file_name,
            'fileSize': file_size,
            'fileType': 'application/octet-stream',
            'folderId': folder_id
        }
    )
    init_res.raise_for_status()
    init_data = init_res.json()
    upload_id = init_data['uploadId']
    key = init_data['key']
    chunk_size = init_data['chunkSize']
    total_parts = init_data['totalParts']
    
    print(f"โœ… Upload initialized: {total_parts} parts ร— {chunk_size / (1024**2):.1f} MB")
    
    # 2. Get all presigned URLs upfront
    print(f"๐Ÿ”— Getting presigned URLs for {total_parts} parts...")
    urls_res = requests.post(
        f'{BASE_URL}/files/multipart/batch-urls',
        headers={'Content-Type': 'application/json'},
        json={'key': key, 'uploadId': upload_id, 'totalParts': total_parts}
    )
    urls_res.raise_for_status()
    urls_data = urls_res.json()
    if not urls_data.get('success'):
        raise Exception(urls_data.get('error', 'Failed to get upload URLs'))
    
    urls_dict = urls_data['urls']
    print(f"โœ… Got all presigned URLs")
    
    # 3. Upload parts in PARALLEL for maximum speed
    parallelism = get_optimal_parallelism(file_size)
    print(f"\n๐Ÿš€ Uploading {total_parts} parts with {parallelism}x parallelism...")
    start_time = time.time()
    uploaded_parts = []
    completed_parts = 0
    
    def upload_part(part_number):
        """Upload a single part"""
        url = urls_dict[str(part_number)]
        
        with open(file_path, 'rb') as f:
            f.seek((part_number - 1) * chunk_size)
            chunk = f.read(chunk_size)
        
        # Upload with retry logic
        max_retries = 3
        for attempt in range(max_retries):
            try:
                res = requests.put(url, data=chunk, timeout=300)
                res.raise_for_status()
                etag = res.headers.get('ETag', '').strip('"')
                return {'partNumber': part_number, 'etag': etag}
            except Exception as e:
                if attempt == max_retries - 1:
                    raise
                time.sleep(2 ** attempt)  # Exponential backoff
    
    # Use ThreadPoolExecutor for parallel uploads
    with ThreadPoolExecutor(max_workers=parallelism) as executor:
        futures = {executor.submit(upload_part, i): i for i in range(1, total_parts + 1)}
        
        for future in as_completed(futures):
            part_number = futures[future]
            try:
                result = future.result()
                uploaded_parts.append(result)
                completed_parts += 1
                
                # Update progress
                elapsed = time.time() - start_time
                uploaded_bytes = completed_parts * chunk_size
                speed = uploaded_bytes / elapsed / (1024**2) if elapsed > 0 else 0
                progress = (completed_parts / total_parts) * 100
                eta = (total_parts - completed_parts) * chunk_size / (uploaded_bytes / elapsed) if uploaded_bytes > 0 else 0
                
                # Progress bar
                bar_length = 30
                filled = int(bar_length * completed_parts / total_parts)
                bar = 'โ–ˆ' * filled + 'โ–‘' * (bar_length - filled)
                
                print(f"\r[{bar}] {progress:.1f}% | {completed_parts}/{total_parts} parts | "
                      f"{speed:.1f} MB/s | ETA: {eta:.0f}s", end='', flush=True)
            except Exception as e:
                print(f"\nโŒ Failed to upload part {part_number}: {e}")
                raise
    
    elapsed_total = time.time() - start_time
    avg_speed = file_size / elapsed_total / (1024**2)
    print(f"\nโœ… Upload completed in {elapsed_total:.1f}s (avg: {avg_speed:.1f} MB/s)")
    
    uploaded_parts.sort(key=lambda x: x['partNumber'])
    
    # 4. Complete multipart upload
    print(f"๐Ÿ”„ Finalizing upload...")
    complete_res = requests.post(
        f'{BASE_URL}/files/multipart/complete',
        headers=headers,
        json={
            'key': key,
            'uploadId': upload_id,
            'parts': uploaded_parts,
            'fileName': file_name,
            'fileSize': file_size,
            'contentType': 'application/octet-stream',
            'folderId': folder_id
        }
    )
    complete_res.raise_for_status()
    result = complete_res.json()
    if not result.get('success'):
        raise Exception(result.get('error'))
    
    print(f"โœ… File saved to database")
    return result['file']

def upload_file(file_path, folder_id=None):
    """Main upload function - automatically handles any file size with optimal performance"""
    file_size = os.path.getsize(file_path)

    if file_size < MULTIPART_THRESHOLD:
        return upload_small_file(file_path, folder_id)
    else:
        return upload_large_file_parallel(file_path, folder_id)

# Example usage

if **name** == '**main**':
    try:
        result = upload_file('./large_file.zip')
        print(f"\n๐ŸŽ‰ Success! Share: https://beecargo.net/d/{result['shortId']}")
    except Exception as e:
        print(f'โŒ Upload failed: {e}')

JavaScript (parallel)

See Python (parallel) example above.

Key differences from sequential upload

  • Parallel execution: Uses ThreadPoolExecutor (Python) or Promise.all (JavaScript) to upload multiple chunks simultaneously
  • Adaptive concurrency: Automatically adjusts parallelism (3-6 workers) based on file size for optimal performance
  • Batch URL generation: Pre-fetches all presigned URLs upfront to eliminate latency between chunks
  • Retry logic: Each chunk has independent retry handling with exponential backoff
  • Real-time progress: Tracks completion across all parallel workers for accurate progress reporting

Error response

{
  "success": false,
  "error": "Unauthorized"
}