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/upload

Headers

HeaderRequiredDescription
x-api-key✅ YesYour API key
Content-Type✅ YesMust be application/json

Request Body

JSON
{
  "filename": "backup_2024.zip",
  "mimeType": "application/zip",
  "size": 104857600,
  "folderPath": "/backups/server-a"
}
FieldTypeRequiredDescription
filenamestring✅ YesName of the file to upload
mimeTypestring✅ YesMIME type (e.g., application/pdf)
sizenumber✅ YesFile size in bytes
folderPathstring❌ NoVirtual 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
}
FieldDescription
uploadUrlGoogle Drive resumable upload URL
expiresInURL expiration time in seconds (1 hour)
methodHTTP method to use (PUT)
_metaInternal metadata (optional for debugging)

Error Responses

HTTP CodeErrorDescription
400Missing or invalid fieldRequired field validation failed
401Invalid or inactive API keyAuthentication failed
500Upload failedInternal error during initialization
507Insufficient storageNo 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}")

Next Steps