Try it

Pick a file once — Create session and PUT upload use the same name, type, and size.

Upload file
No file chosen

Required for upload session and CDN PUT examples.

Packages

reupload-sdk (Python)

View on PyPI →

Official server-side Python SDK for the Reupload public API. Typed API aligned with @reupload/sdk, built on httpx. Requires Python 3.10+.

All packages · @reupload/sdk · Server-side uploads · Django guide

Install

terminal
pip install reupload-sdk
 
# FastAPI route helpers
pip install "reupload-sdk[fastapi]"

Environment variables

VariableRequiredDescription
REUPLOAD_API_KEYYesAPI key (ru_…)
REUPLOAD_PROJECT_IDYesProject UUID for uploads (from project settings in the dashboard)
REUPLOAD_API_BASE_URLNoDefault https://api.reupload.dev/api/v1

Quick start

main.py
from reupload import create_reupload_from_env
 
client = create_reupload_from_env()
me = client.whoami()
print(me["projects"])

Sync and async clients

ClassUse when
ReuploadScripts, sync WSGI, blocking code
AsyncReuploadFastAPI, asyncio, async def routes (recommended)
client.py
from reupload import Reupload, AsyncReupload, create_async_reupload_from_env
 
# Manual sync client
sync = Reupload(api_key="ru_…", default_project_id="project-uuid")
 
# Async (e.g. FastAPI)
async_client = create_async_reupload_from_env()

API overview

MethodDescription
client.whoami()Verify key and list projects
client.uploads.create_session()Start CDN upload session
put_to_upload_url() / aput_to_upload_url()PUT bytes to signed CDN URL
client.uploads.complete()Finalize CDN upload
client.uploads.upload()Session + CDN PUT + complete in one call
client.uploads.upload_direct()Server multipart direct upload (single file)
client.uploads.upload_direct_batch()Multiple files in one multipart request
client.uploads.get_session() / wait_for_completion()Poll session status
client.files.get() / access() / delete()File metadata and signed URLs

HTTP equivalents: API reference. Node.js mirror: @reupload/sdk. For files.access(), expiresIn is 60–604800 seconds (default 300).

CDN upload from Python

upload.py
from pathlib import Path
 
from reupload import create_reupload_from_env, put_to_upload_url
 
client = create_reupload_from_env()
payload = Path("photo.jpg").read_bytes()
 
session = client.uploads.create_session(
    {
        "projectId": client.default_project_id,
        "filename": "photo.jpg",
        "contentType": "image/jpeg",
        "size": len(payload),
        "isPublic": True,  # optional
    },
)
 
put_to_upload_url(session["uploadUrl"], payload, "image/jpeg")
 
done = client.uploads.complete({"uploadId": session["uploadId"]})
print(done["fileId"])

Or use the combined helper:

upload_one_shot.py
done = client.uploads.upload(
    {
        "projectId": client.default_project_id,
        "filename": "photo.jpg",
        "contentType": "image/jpeg",
        "size": len(payload),
        "file": {
            "data": payload,
            "filename": "photo.jpg",
            "contentType": "image/jpeg",
            "size": len(payload),
        },
    },
)

Direct upload

One multipart request to Reupload — use when the browser uploads to your API first. See Server-side uploads and Server-side upload guide.

direct.py
result = client.uploads.upload_direct(
    {
        "projectId": client.default_project_id,
        "isPublic": True,  # optional
        "file": {
            "data": payload,
            "filename": "photo.jpg",
            "contentType": "image/jpeg",
            "size": len(payload),
        },
    },
)
# {"uploadId", "fileId", "status": "processing"}

Direct upload stores your file before the response returns

202 + processing means background work (scan, finalize, quotas) is still running — not that the upload failed. Use webhooks or poll GET /uploads/session/:uploadId for path, url, and confirmed sizeBytes. Why this design →

Multiple files

direct_batch.py
from reupload import build_direct_upload_batch_multipart
 
batch = client.uploads.upload_direct_batch(
    {
        "projectId": client.default_project_id,
        "files": [file_a, file_b],
    },
)
 
# Or build multipart parts for a custom httpx call:
data, files = build_direct_upload_batch_multipart(
    {
        "projectId": client.default_project_id,
        "files": [file_a, file_b],
    },
)

FastAPI

Optional helpers under reupload.fastapi (install reupload-sdk[fastapi]). Accepts multipart fields projectId, file, optional filename, and optional isPublic.

main.py
from fastapi import FastAPI
from reupload import create_async_reupload_from_env
from reupload.fastapi import create_async_fastapi_direct_upload_handler
 
app = FastAPI()
client = create_async_reupload_from_env()
upload = create_async_fastapi_direct_upload_handler(client=client)
 
@app.post("/api/upload")
async def api_upload(request):
    return await upload(request)

Django: full walkthrough with direct upload and CDN routes — Django + reupload-sdk. Other frameworks: read uploaded bytes from the request, then call upload_direct or use helpers from reupload.fastapi.shared (framework-agnostic).

Backend file router (CDN)

For browser CDN uploads, expose routes your front end calls — then use @reupload/client or @reupload/react in the UI (JavaScript/TypeScript only). On Python:

  • POST /uploads/prepare uploads.create_session()
  • POST /uploads/completeuploads.complete()
  • GET /uploads/:id/statusuploads.get_session()

CDN walkthrough: React/Next + Node.js (browser packages are npm-only today).

Errors

errors.py
from reupload import ReuploadError, is_reupload_error, is_reupload_cdn_error
 
try:
    client.files.get(file_id)
except ReuploadError as error:
    print(error.status, error.code, error.message)
 
# CDN PUT failures
except Exception as error:
    if is_reupload_cdn_error(error):
        print("CDN PUT failed", error.status)