Metadata-Version: 2.4
Name: purehosting-sdk
Version: 1.0.0
Summary: Official Python SDK for the PureHosting API (servers, domains, Telegram accounts, balance, webhooks, WebSocket events).
License: MIT
Project-URL: Homepage, https://docs.purehosting.top
Project-URL: Source, https://github.com/permach-dev/vds/tree/main/sdk/purehosting-python
Keywords: purehosting,vps,vds,hosting,sdk,api
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# purehosting-sdk (Python)

Official Python SDK for the [PureHosting API](https://docs.purehosting.top) — servers, domains, Telegram accounts, balance, webhooks and WebSocket events. Standard library only, no pip dependencies.

## Install

Not yet on PyPI — install straight from the repository:

```bash
pip install "git+https://github.com/permach-dev/vds.git#subdirectory=sdk/purehosting-python"
```

Or copy the `purehosting/` package into your project — it has no dependencies to drag along.

## Quick start

```python
from purehosting import PureHosting

client = PureHosting(api_key="phk_...")  # Profile → API access in the bot

servers = client.servers.list()["items"]
print(servers)
```

## Servers

```python
client.servers.list()
client.servers.get(42)
client.servers.catalog()
client.servers.buy({"tariff_id": "DE-3", "months": 1, "os_family": "ubuntu", "os_version": "24.04"})
client.servers.power(42, "restart")  # 'start' | 'stop' | 'restart'
client.servers.reinstall(42, {"os_family": "ubuntu", "os_version": "24.04"})
client.servers.reset_password(42)
client.servers.os_options(42)
client.servers.cancel(42)     # only while not yet issued
client.servers.extend(42, 3)  # 3 months
```

## Domains

```python
client.domains.list()
client.domains.get(7)
client.domains.check("example")
client.domains.buy({"name": "example", "tld": "com"})
client.domains.cancel(7)

client.domains.dns.list(7)
client.domains.dns.add(7, {"type": "A", "name": "@", "value": "1.2.3.4", "ttl": 3600})
client.domains.dns.delete(7, 15)
```

## Telegram accounts

```python
client.accounts.list()
client.accounts.catalog()
acc = client.accounts.buy("US")           # ISO 3166-1 alpha-2
client.accounts.request_code(acc["id"])    # AFTER signing in with that number
client.accounts.mark_used(acc["id"])

bulk = client.accounts.bulk.buy("US", 10)
client.accounts.bulk.get(bulk["id"])       # poll until status != 'pending'
archive_bytes = client.accounts.bulk.download(bulk["id"])
with open("accounts.zip", "wb") as f:
    f.write(archive_bytes)
```

## Balance

```python
balance = client.balance.get()["balance_usd"]
tx = client.balance.transactions(limit=50)
```

## Webhooks

```python
cfg = client.webhook.set("https://example.com/hooks/purehosting")
print(cfg["secret"])  # save this — it signs every incoming request

# In your webhook handler:
ok = PureHosting.verify_webhook_signature(
    stored_secret,
    raw_body,  # the RAW request body string/bytes, not json.loads()'d
    request.headers.get("X-PureHosting-Signature"),
)
if not ok:
    return "", 401
```

Delivery: 5 attempts (1 initial + 4 retries) with a 1 → 2 → 4 → 8 minute pause between them.

## WebSocket

```python
stream = client.connect_websocket()
stream.on("open", lambda _: print("connected"))
stream.on("event", lambda msg: print("any event:", msg))
stream.on("server.expiring", lambda data: print("expiring:", data["order_id"]))
stream.start(background=True)  # runs the receive loop in a daemon thread

# ... your app keeps running ...
stream.close()
```

Reconnects automatically with a growing pause (1s → 2s → … → 60s). Implements the RFC 6455 handshake and framing directly over `socket`/`ssl` — no `websockets`/`websocket-client` dependency.

## Errors

```python
from purehosting import PureHosting, PureHostingError

try:
    client.servers.buy({...})
except PureHostingError as e:
    print(e.status, e.body.get("error"), e.body.get("detail"))
```

## Full docs

[docs.purehosting.top](https://docs.purehosting.top) — every endpoint, schemas, webhook event formats.
