Metadata-Version: 2.4
Name: novence
Version: 0.2.1
Summary: Official Python SDK for Novence — static site hosting for AI agents
License-Expression: MIT
Project-URL: Homepage, https://novence.ai
Project-URL: Documentation, https://novence.ai/docs
Project-URL: Issues, https://novence.ai/support
Keywords: novence,static-site-hosting,deploy,hosting,edge,ai-agents
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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 :: Internet :: WWW/HTTP :: Site Management
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# novence (Python)

Python SDK for [Novence](https://novence.ai) — static site hosting built for AI agents.

```bash
pip install novence
```

Requires Python 3.10+. No third-party dependencies — standard library only.

## Quick start

```python
from novence import Novence, bootstrap_account, verify_email

boot = bootstrap_account("you@example.com")     # emails a 6-digit OTP
verify_email("you@example.com", "123456")

client = Novence(api_key=boot["apiKey"])
project = client.create_project("launch")
pid = project["project"]["id"]

client.upload_bytes(pid, "index.html", "text/html; charset=utf-8", b"<h1>hi</h1>")
client.deploy(pid)

deployment = client.wait_for_deployment(pid)     # polls until live or failed
print(deployment["liveUrl"])
```

## Configuration

`base_url` defaults to `https://api.novence.ai`. Override per client, or set
`NOVENCE_BASE_URL` to point everything at a different control plane:

```python
client = Novence(api_key=key, base_url="http://127.0.0.1:8080")
```

The variable is read at call time, so setting it after import still works.

## Deploys are asynchronous

`deploy()` returns as soon as the deployment is queued. Use
`wait_for_deployment(project_id, timeout=300, interval=2)` to block until it is
live, or poll `latest_deployment(project_id)` yourself.

`checks_results["passed"]` is `None` when checks were **skipped** (unverified
accounts). That is not a pass.

## API

| Area | Methods |
| --- | --- |
| Projects | `create_project` `list_projects` `get_project` `update_project` `project_usage` `project_analytics` |
| Uploads | `upload_dir` `upload_file` `upload_bytes` `get_upload_url` `get_upload_urls_batch` `confirm_upload` `confirm_batch` |
| Deploys | `deploy` `latest_deployment` `wait_for_deployment` |
| Domains | `configure_domain` `domain_status` |
| Forms | `create_form` `list_forms` `get_form` `update_form` `delete_form` `list_form_submissions` `delete_form_submission` |
| Billing | `quotas` `checkout` `billing_portal` `mpp_upgrade` |
| Account | `get_account` `account_console_kit` `create_session` `revoke_session` `revoke_api_key` |

Module-level: `bootstrap_account` `verify_email` `resend_verification` `reissue_api_key`.

`reissue_api_key` issues a new key and revokes the old one — rebuild your client
with the returned key.

## Uploading a directory

```python
result = client.upload_dir(pid, "./dist")
result["uploaded"]   # site paths that went up
result["skipped"]    # local files whose extension the platform does not accept
```

Dotfiles and dot-directories (`.git`, `.env`) are skipped, matching the
TypeScript SDK.

## Errors

Every API error raises `RuntimeError` carrying the API's message — including
rate limits and quota rejections.

## Security

`nv_` keys are server-side credentials. Read them from the environment; never
commit one or put one in client-side code.

## License

MIT
