Metadata-Version: 2.4
Name: fluidcloud
Version: 0.1.0
Summary: Official Python SDK for FluidCloud — private file storage, shareable raw links, and stable public (hotlinkable) URLs.
Project-URL: Homepage, https://cloud.fluidvip.com
Project-URL: Source, https://github.com/Trebuu/FluidCloud
Author: Fluidvip
License-Expression: MIT
Keywords: cdn,fluidcloud,share-links,storage,uploads
Requires-Python: >=3.8
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# fluidcloud — Python SDK for FluidCloud

Official Python client for [FluidCloud](https://cloud.fluidvip.com) — file storage
with shareable raw links and **stable public (hotlinkable) URLs**. The SDK hides the
upload plumbing (presign → direct-to-storage PUT → complete, including multipart for
large files) behind a single `upload()` call.

📚 **Full documentation:** <https://cloud.fluidvip.com/docs>

## Install

```bash
pip install fluidcloud
```

Requires Python 3.8+. The only runtime dependency is `httpx`.

## Quick start

```python
from fluidcloud import FluidCloud

fc = FluidCloud(api_key="fck_live_...")        # base_url defaults to production

# A Space is a top-level bucket; folders and files live inside it.
space = fc.spaces.create("Brand Assets")

# Upload — one call hides presign -> PUT -> complete (+ multipart for big files).
asset = fc.files.upload("logo.png", space_id=space.id, public=True)
print(asset.public_url)        # stable, inline, cacheable hotlink (use as <img src>)

# Or mint links explicitly:
public = fc.files.public_url(asset.id)                 # permanent (never expires)
signed = fc.files.signed_url(asset.id, expires_in_days=7, permission="view")
```

## Authentication

Create an API key in the [dashboard](https://cloud.fluidvip.com) (Settings →
Developer; an active subscription is required) and pass it to the client. The key
(`fck_live_…` / `fck_test_…`) is sent as `X-API-Key`. Keys are **scoped**; a call
outside a key's scopes raises `PermissionError_` (HTTP 403 `insufficient_scope`).

## API surface

```python
fc.spaces.list() / create(name)
fc.folders.list(space_id, parent_id=None) / create(name, space_id, parent_id=None)
          / rename(id, name) / move(id, parent_id) / delete(id) / restore(id)
fc.files.upload(path_or_bytes_or_fileobj, space_id, folder_id=None,
                name=None, content_type=None, public=False)
         .list(space_id, folder_id=None) / get(id)
         .rename(id, name) / move(id, folder_id) / delete(id) / restore(id)
         .download_url(id)                # short-lived download URL
         .public_url(id)                  # permanent public hotlink (Link)
         .signed_url(id, expires_in_days=7, permission="view")   # expiring (Link)
fc.shares.list(file_id=None, include_inactive=False) / revoke(share_id)
fc.quota.usage()                          # bytes_used / bytes_limit / links_*
```

`public_url` vs `signed_url`: a **public** link never expires and is served inline +
edge-cached (ideal for embedding an image in a page, a bot message, or a vision
model's `image_url`). A **signed** link expires (1–365 days). Use
`fc.shares.revoke(link.id)` to revoke either.

## Errors

All errors derive from `FluidCloudError`: `AuthError` (401),
`QuotaExceededError` (402), `PermissionError_` (403), `NotFoundError` (404),
`ConflictError` (409, e.g. sharing a file still being scanned), or `ApiError`.

## Notes

- The client is synchronous (`httpx`) and works as a context manager:
  `with FluidCloud(api_key=...) as fc: ...`.
- The SDK targets the versioned API (`/api/v1`).
- Override the API origin with `base_url=...` if you have been given a different endpoint.

MIT licensed.
