Upload files to Beecargo using the API.
POST https://api.beecargo.net/files/uploadUse this endpoint for files under 4MB. The client examples below show how to automatically handle larger files with multipart upload.
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_KEYOption 2: Anonymous upload - No authentication required. Limited to 25GB per file, expires after 15 days.
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.
Use these ready-to-use code examples that automatically handle any file size. Copy and paste into your project - no modifications needed!
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"| Parameter | Type | Required | Description |
|---|---|---|---|
| file | File | Yes | The file to upload |
| folderId | String | No | Optional folder ID to organize the file |
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.
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.
200 parts ร 2s = 400s (~6.7 min)
200 parts รท 4 ร 2s = 100s (~1.7 min)
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}')See Python (parallel) example above.
{
"success": false,
"error": "Unauthorized"
}