Metadata-Version: 2.4
Name: reupload-sdk
Version: 0.1.1
Summary: Official Python SDK for the Reupload public API
Project-URL: Homepage, https://docs.reupload.dev
Project-URL: Repository, https://github.com/Reupload-v2/reupload-sdk
Author-email: Reupload <support@reupload.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: fastapi,reupload,sdk,storage,upload
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27.0
Provides-Extra: dev
Requires-Dist: fastapi>=0.110.0; extra == 'dev'
Requires-Dist: httpx>=0.27.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: python-multipart>=0.0.9; extra == 'dev'
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.110.0; extra == 'fastapi'
Requires-Dist: python-multipart>=0.0.9; extra == 'fastapi'
Description-Content-Type: text/markdown

# reupload-sdk

Official **server-side** Python SDK for the [Reupload](https://reupload.dev) public API.

- Typed API aligned with `@reupload/sdk` (Node.js)
- Sync (`Reupload`) and async (`AsyncReupload`) clients via [httpx](https://www.python-httpx.org/)
- CDN upload flow (session → PUT → complete) and server direct multipart upload
- Optional **FastAPI** route helpers

## Install

```bash
pip install reupload-sdk

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

Requires **Python 3.10+**.

## Quick start

```python
from reupload import create_reupload_from_env

client = create_reupload_from_env()
me = client.whoami()
print(me["projects"])
```

### Environment variables

| Variable | Required | Description |
|----------|----------|-------------|
| `REUPLOAD_API_KEY` | Yes | API key (`ru_…`) |
| `REUPLOAD_PROJECT_ID` | Yes | Default project UUID |
| `REUPLOAD_API_BASE_URL` | No | Default `https://api.reupload.dev/api/v1` |

### Manual client

```python
from reupload import Reupload

client = Reupload(
    api_key="ru_…",
    default_project_id="your-project-uuid",
)
```

## API overview

| Method | Description |
|--------|-------------|
| `client.whoami()` | Verify key and list projects |
| `client.uploads.create_session()` | Start CDN upload session |
| `put_to_upload_url(url, body, content_type)` | PUT bytes to signed CDN URL |
| `client.uploads.complete()` | Finalize CDN upload |
| `client.uploads.upload()` | Session + CDN PUT + complete |
| `client.uploads.upload_direct()` | Server multipart direct upload |
| `client.uploads.upload_direct_batch()` | Multiple files in one request |
| `client.uploads.get_session()` | Poll session status |
| `client.uploads.wait_for_completion()` | Poll until `COMPLETED` |
| `client.files.get()` | File metadata |
| `client.files.access()` | Signed download URL |
| `client.files.delete()` | Delete file |

Use `AsyncReupload` and `await` for the same methods in async code.

### CDN upload

```python
from pathlib import Path

from reupload import Reupload, put_to_upload_url

client = Reupload(api_key="ru_…", default_project_id="…")
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,
    },
)

put_to_upload_url(session["uploadUrl"], payload, "image/jpeg")
done = client.uploads.complete({"uploadId": session["uploadId"]})
print(done["fileId"])
```

Or the combined helper:

```python
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

```python
result = client.uploads.upload_direct(
    {
        "projectId": client.default_project_id,
        "isPublic": True,
        "file": {
            "data": payload,
            "filename": "photo.jpg",
            "contentType": "image/jpeg",
            "size": len(payload),
        },
    },
)
```

## FastAPI

```python
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()

@app.post("/api/upload")
async def upload(request):
    return await create_async_fastapi_direct_upload_handler(client=client)(request)
```

Or build the handler once:

```python
upload_handler = create_async_fastapi_direct_upload_handler(client=client)

@app.post("/api/upload")
async def upload(request):
    return await upload_handler(request)
```

Accepts multipart fields: `projectId`, `file`, optional `filename`, optional `isPublic`.

## Errors

```python
from reupload import ReuploadError, is_reupload_error, is_reupload_cdn_error

try:
    client.files.get("…")
except ReuploadError as error:
    print(error.status, error.code, error.message)
```

## Development

```bash
cd python-packages/reupload-sdk
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
python -m build
```

## License

MIT
