Upload Endpoint
The upload endpoint implements a 2-step flow to bypass Vercel's 4.5MB body size limit while supporting files up to 5TB.
Endpoint
POST
/api/v1/storage/uploadHeaders
| Header | Required | Description |
|---|---|---|
x-api-key | ✅ Yes | Your API key |
Content-Type | ✅ Yes | Must be application/json |
Request Body
JSON
{
"filename": "backup_2024.zip",
"mimeType": "application/zip",
"size": 104857600,
"folderPath": "/backups/server-a"
}| Field | Type | Required | Description |
|---|---|---|---|
filename | string | ✅ Yes | Name of the file to upload |
mimeType | string | ✅ Yes | MIME type (e.g., application/pdf) |
size | number | ✅ Yes | File size in bytes |
folderPath | string | ❌ No | Virtual folder path (auto-created) |
Response
Success (200)
JSON
{
"success": true,
"data": {
"uploadUrl": "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=...",
"expiresIn": 3600,
"method": "PUT",
"_meta": {
"nodeId": "clx1234abcd",
"reservationId": "clx5678efgh",
"folderId": "clx9012ijkl"
}
},
"error": null
}| Field | Description |
|---|---|
uploadUrl | Google Drive resumable upload URL |
expiresIn | URL expiration time in seconds (1 hour) |
method | HTTP method to use (PUT) |
_meta | Internal metadata (optional for debugging) |
Error Responses
| HTTP Code | Error | Description |
|---|---|---|
400 | Missing or invalid field | Required field validation failed |
401 | Invalid or inactive API key | Authentication failed |
500 | Upload failed | Internal error during initialization |
507 | Insufficient storage | No nodes with available space |
2-Step Upload Flow
┌─────────┐ ┌─────────┐ ┌──────────────┐
│ Client │ │ EDS API │ │ Google Drive │
└────┬────┘ └────┬────┘ └──────┬───────┘
│ │ │
│ 1. POST /api/v1/storage/upload │
│────────────────────────────>│ │
│ │ Init resumable session │
│ │─────────────────────────────>│
│ │ │
│ │<─────────────────────────────│
│ 2. { success, uploadUrl } │ Upload URL │
│<────────────────────────────│ │
│ │ │
│ 3. PUT [uploadUrl] + Binary Data │
│────────────────────────────────────────────────────────────>│
│ │ │
│ 4. 200 OK │ │
│<────────────────────────────────────────────────────────────│Step 1: Request Upload URL
cURL
curl -X POST https://your-domain.com/api/v1/storage/upload \
-H "x-api-key: exstr_live_..." \
-H "Content-Type: application/json" \
-d '{
"filename": "data.csv",
"mimeType": "text/csv",
"size": 1048576,
"folderPath": "/datasets"
}'Step 2: Upload to Google Drive
Use the uploadUrl from the response to upload the actual file:
cURL
curl -X PUT "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=..." \ --data-binary @data.csv
💡 Pro Tip
The uploadUrl expires after 1 hour. For large files, ensure your upload completes within this window or implement chunked upload retry logic.
Complete Example
Python
import requests
import os
API_KEY = os.environ["EDS_API_KEY"]
BASE_URL = "https://your-domain.com/api/v1/storage"
FILE_PATH = "backup.zip"
# Step 1: Get upload URL
file_size = os.path.getsize(FILE_PATH)
response = requests.post(
f"{BASE_URL}/upload",
headers={"x-api-key": API_KEY},
json={
"filename": os.path.basename(FILE_PATH),
"mimeType": "application/zip",
"size": file_size,
"folderPath": "/backups"
}
)
result = response.json()
if not result["success"]:
raise Exception(result["error"])
# Step 2: Upload directly to Google Drive
with open(FILE_PATH, "rb") as f:
upload_response = requests.put(
result["data"]["uploadUrl"],
data=f
)
if upload_response.status_code == 200:
print("✅ Upload successful!")
else:
print(f"❌ Upload failed: {upload_response.text}")