Metadata-Version: 2.4
Name: viewrium
Version: 0.1.0
Summary: Official Python SDK for the Viewrium API. Create and manage 3D models, api keys, and usage records.
Project-URL: Homepage, https://viewrium.com
Project-URL: Repository, https://github.com/davidzagyvaig/viewrium
Project-URL: Documentation, https://docs.viewrium.com
Author-email: Viewrium <hello@viewrium.com>
License: Apache-2.0
Keywords: 3d,api,ar,model-viewer,sdk,viewrium
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Description-Content-Type: text/markdown

# viewrium

Official Python SDK for the [Viewrium](https://viewrium.com) API. Create and manage 3D models, API keys, and usage records.

## Install

```bash
pip install viewrium
```

Python 3.10+.

## Configure

```python
import viewrium
viewrium.api_key = "sk_live_..."
```

Or via environment variable:

```bash
export VIEWRIUM_API_KEY=sk_live_...
```

Both are supported; the module variable wins if both are set.

Other config (all optional):

| Variable | Env | Default |
|---|---|---|
| `viewrium.api_base` | `VIEWRIUM_API_BASE` | `https://api.viewrium.com` |
| `viewrium.timeout` | - | `60` seconds |
| `viewrium.max_retries` | - | `3` (retries 429 / 5xx, respects `Retry-After`) |

## Quickstart (sync)

```python
import viewrium

viewrium.api_key = "sk_live_..."

model = viewrium.Model.create(
    custom_id="sku-1",
    images=["https://example.com/img1.jpg", "https://example.com/img2.jpg"],
    height=90,
    tags=["chair", "summer-2026"],
)
print(model.id, model.status)

models = viewrium.Model.list(tag="chair", limit=20)
for m in models.data:
    print(m.custom_id, m.status)
```

## Quickstart (async)

```python
import asyncio
import viewrium

viewrium.api_key = "sk_live_..."

async def main():
    model = await viewrium.AsyncModel.create(
        custom_id="sku-1",
        images=["https://example.com/img1.jpg"],
        height=35,
        size_unit="in",  # converted to cm server-side
    )
    events = await viewrium.AsyncModel.list_events(model.id)
    return model, events

asyncio.run(main())
```

## Resources

Each resource has a sync class and an `Async`-prefixed async twin.

| Sync | Async | Methods |
|---|---|---|
| `Model` | `AsyncModel` | `create`, `create_from_images`, `create_from_video`, `retrieve`, `list`, `modify`, `delete`, `list_events` |
| `ApiKey` | `AsyncApiKey` | `create`, `list`, `delete` |
| `Usage` | `AsyncUsage` | `retrieve` |
| `Tag` | `AsyncTag` | `list` |

## Uploading files

```python
model = viewrium.Model.create_from_images(
    ["./chair-front.jpg", "./chair-side.jpg", "./chair-back.jpg"],
    custom_id="sku-1",
    height=90,
    tags=["chair"],
)

model = viewrium.Model.create_from_video(
    "./chair-walkaround.mp4",
    custom_id="sku-2",
    height=92,
)
```

Paths are strings or `pathlib.Path`. Files are opened + closed by the SDK.

## Sizing

Pass `height` + optional `size_unit` (`"cm"` or `"in"`, default `"cm"`). The server normalizes to cm before storing. Explicit `height` wins over scraped values; if neither is present, the model renders unscaled.

## Errors

```python
from viewrium import (
    ViewriumError,       # base class
    AuthError,           # 401 / missing key
    NotFoundError,       # 404
    ValidationError,     # 400 / 409 / 422
    RateLimitError,      # 429 (has .retry_after)
    APIError,            # 5xx / other
)

try:
    viewrium.Model.retrieve("not-a-real-id")
except NotFoundError:
    ...
except RateLimitError as e:
    print("back off for", e.retry_after, "seconds")
```

## Cleanup

The SDK lazily opens HTTP clients and tears them down on process exit. If you need to close eagerly:

```python
viewrium.close()           # sync client
await viewrium.aclose()    # async client
```

## License

Apache 2.0.
