Metadata-Version: 2.4
Name: seb-auth
Version: 0.3.0
Summary: Official Python SDK for SebAuth — auth, database, email, hosting and checkout. Sync + async.
Author: SebAuth
License: MIT
Project-URL: Homepage, https://seb-auth.lovable.app
Project-URL: Documentation, https://seb-auth.lovable.app/docs
Project-URL: API, https://seb-auth.lovable.app/docs
Keywords: sebauth,baas,email,auth,sdk,seb-auth
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Communications :: Email
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25.0
Requires-Dist: httpx>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-mock>=3.10; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: responses>=0.23; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=4.0; extra == "dev"
Dynamic: license-file

# seb-auth

**Official Python SDK for [SebAuth](https://seb-auth.lovable.app)** — auth, document database, transactional email, static hosting and hosted checkout, all from one API key.

[![PyPI](https://img.shields.io/pypi/v/seb-auth.svg)](https://pypi.org/project/seb-auth/)
[![Python](https://img.shields.io/pypi/pyversions/seb-auth.svg)](https://pypi.org/project/seb-auth/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

---

## Install

```bash
pip install seb-auth
```

## Quick start

```python
from seb_auth import SebAuth

seb = SebAuth()  # reads SEBAUTH_API_KEY from the environment

# Send transactional email
seb.email.send(to="user@example.com", subject="Hello", body="Hi from SebAuth!")

# Sign an end user up
user = seb.auth.sign_up(email="ada@example.com", password="s3cret", name="Ada")

# Store JSON documents
seb.database.create_collection("orders")
seb.database.insert("orders", {"sku": "SEB-1", "quantity": 2, "paid": True})

# Publish a static site
seb.host.publish(name="Launch", subdomain="launch", html="<h1>Hi</h1>")

# Take a payment
session = seb.checkout.create_session(
    product_name="Pro plan", amount=2900, currency="usd",
    customer_email="ada@example.com",
)
print(session.url)  # hosted checkout page
```

## Configuration

| Argument     | Env var             | Default                              |
| ------------ | ------------------- | ------------------------------------ |
| `api_key`    | `SEBAUTH_API_KEY`   | — *(required)*                       |
| `base_url`   | `SEBAUTH_BASE_URL`  | `https://seb-auth.lovable.app`       |
| `timeout`    | —                   | `30` seconds                         |

The SDK **never prints or logs your full API key**; `repr()` shows a masked
form (`sk_liv…126b`).

## Services

### SebMail — transactional email

```python
seb.email.send(
    to="user@example.com",
    subject="Welcome",
    body="<h1>Hi there</h1>",
    from_="brand@example.com",    # optional; defaults to no-reply@seb-auth.lovable.app
)

for log in seb.email.logs(limit=50):
    print(log.id, log.to_email, log.status)
```

### SebAuth — end-user authentication

```python
seb.auth.sign_up(email="ada@example.com", password="s3cret", name="Ada")
user = seb.auth.login(email="ada@example.com", password="s3cret")
for u in seb.auth.list_users():
    print(u.id, u.email, u.provider, u.last_login_at)
```

Invalid credentials raise `AuthenticationError`.

### SebBase — JSON document database

```python
seb.database.create_collection("orders", description="Customer orders")

# Direct style
seb.database.insert("orders", {"sku": "SEB-1", "quantity": 2})
docs = seb.database.list("orders", limit=50)

# Handle style
orders = seb.database.collection("orders")
orders.insert({"sku": "SEB-2"})
for doc in orders.list():
    print(doc.id, doc.data, doc.created_at)

# Discover collections
for c in seb.database.list_collections():
    print(c.name, c.description)
```

### SebHost — static site hosting

```python
site = seb.host.publish(
    name="Launch page",
    subdomain="launch",             # 3–40 chars, [a-z0-9-]
    html="<h1>Hello from SebHost</h1>",
    description="Product launch",
)
print(site.url)  # https://seb-auth.lovable.app/site/launch

for s in seb.host.list_sites():
    print(s.subdomain, s.status, s.visits)
```

### SebCheckout — hosted payments

```python
session = seb.checkout.create_session(
    product_name="Pro plan",
    amount=2900,                    # smallest currency unit (cents)
    currency="usd",
    customer_email="ada@example.com",
)
redirect_to(session.url)

for p in seb.checkout.list_payments():
    print(p.id, p.amount, p.currency, p.status)
```

## Async usage (FastAPI, asyncio)

`AsyncSebAuth` is a first-class, `httpx`-powered mirror of the sync
client. Every service method is awaitable:

```python
from seb_auth import AsyncSebAuth

async def welcome(email: str):
    async with AsyncSebAuth() as seb:
        await seb.email.send(to=email, subject="Welcome", body="Hello!")
        await seb.auth.sign_up(email=email, password="s3cret")
```

Sharing one client across a FastAPI app:

```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
from seb_auth import AsyncSebAuth

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.seb = AsyncSebAuth()
    try:
        yield
    finally:
        await app.state.seb.aclose()

app = FastAPI(lifespan=lifespan)

@app.post("/signup")
async def signup(email: str, password: str):
    user = await app.state.seb.auth.sign_up(email=email, password=password)
    await app.state.seb.email.send(to=email, subject="Welcome", body="Hi!")
    return {"user_id": user.id}
```

The async client shares the exact same exception hierarchy, models, and
configuration as the sync one.

## Error handling

Every exception raised by the SDK inherits from `SebAuthError`, so you can
catch everything with one clause or drill down:

```python
from seb_auth import (
    SebAuthError, AuthenticationError, BadRequestError,
    NotFoundError, RateLimitError, ServerError,
    TimeoutError, ConnectionError,
)

try:
    seb.email.send(to="user@example.com", subject="Hi", body="Hello!")
except AuthenticationError:
    ...   # your API key is invalid
except BadRequestError as e:
    print(e.status_code, e.message, e.response_body)
except RateLimitError:
    ...   # you have been rate limited
except (TimeoutError, ConnectionError):
    ...   # network issue
except SebAuthError:
    ...   # everything else the SDK might raise
```

## Models

Every service returns a lightweight `dict` subclass (`User`, `Email`,
`MailLog`, `Collection`, `Document`, `Site`, `CheckoutSession`,
`Payment`). They behave like plain dicts *and* expose keys as attributes:

```python
user = seb.auth.login(email="ada@example.com", password="s3cret")
user.id, user.email, user["created_at"]  # all work
```

## Development

```bash
git clone https://github.com/sebauth/seb-auth-python
cd seb-auth-python
pip install -e ".[dev]"
pytest
```

The runtime SDK always talks to the real SebAuth API; only the test
suite mocks HTTP (via `responses` for sync and `httpx.MockTransport` for
async).

## License

MIT © SebAuth
