Metadata-Version: 2.4
Name: validpin-client
Version: 1.0.2
Summary: Official Python client for Validpin license verification
Home-page: https://github.com/Clerk-Global-LTD/validpin-client
Author: Validpin Team
Author-email: support@validpin.com
Project-URL: Documentation, https://github.com/Clerk-Global-LTD/validpin-client
Project-URL: Platform, https://validpin.com
Project-URL: Source, https://github.com/Clerk-Global-LTD/validpin-client
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: project-url
Dynamic: requires-python
Dynamic: summary

<div align="center">

# 🐍 validpin-client

**Official Validpin Python Client — License Verification for Python**

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

Zero-dependency license verification client for the [Validpin](https://validpin.com) platform.
Verify, enforce, and cache license keys with a single line of code.

</div>

---

## ✨ Features

- ✅ **DOMAIN LOCKING** — Verify against the exact domain the license was issued for
- 🚀 **24-HOUR CACHE** — `cache_enabled: True` (default) avoids re-hitting the API on every request
- 🛡️ `enforce()` — Raises `PermissionError` on invalid/expired licenses; perfect for backend bootstrapping
- ⚙️ **Configurable endpoint** — `api_url` option (v1.0.1+) points at any Validpin-compatible server (self-hosted / local)
- 📦 **Zero dependencies** — Pure standard library (`urllib`); no runtime packages required
- 🧩 **Context manager** — `with ValidpinClient(...) as client:` for scoped usage
- 🐍 **Python 3.7+** — Broad compatibility

---

## 📦 Installation

```bash
pip install validpin-client
```

---

## 🚀 Quick Start

```python
from validpin_client import ValidpinClient

# 1. Initialize with your Website API Key
client = ValidpinClient(
    api_key='lcs_your_website_api_key',
    domain='my-customer-site.com',  # domain lock (required for production)
    cache_enabled=True,             # 24h cache (default: True)
)

# 2. The license key provided by your user
license_key = 'A1B2-C3D4-E5F6-G7H8'

# 3. Verify
if client.verify(license_key):
    print("Access Granted!")
    # Run your application logic here...
else:
    print("Access Denied:", client.last_error)
```

### Enforce mode (stops execution on failure)

```python
from validpin_client import ValidpinClient

client = ValidpinClient('lcs_your_website_api_key', domain='my-customer-site.com')

try:
    client.enforce('A1B2-C3D4-E5F6-G7H8')
    print("License valid — continuing...")
except PermissionError as e:
    print("License check failed:", e)
    # Abort, show a payment page, etc.
```

### Context manager

```python
with ValidpinClient('lcs_your_website_api_key', domain='example.com') as client:
    if client.verify('A1B2-C3D4-E5F6-G7H8'):
        print("Access Granted!")
```

---

## 📖 API Reference

### `ValidpinClient(api_key, domain=None, cache_dir=None, timeout=10, cache_enabled=True, api_url='https://api.validpin.com/v1/verify')`

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `api_key` | `str` | ✅ | Your Website API Key (`lcs_...`) from the Validpin dashboard |
| `domain` | `str` | ❌ | Domain lock override |
| `cache_dir` | `str` | ❌ | Cache directory (default: system temp) |
| `timeout` | `int` | ❌ | Request timeout in seconds (default: `10`) |
| `cache_enabled` | `bool` | ❌ | Enable 24h caching (default: `True`) |
| `api_url` | `str` | ❌ | Verification endpoint override — self-hosted / local Validpin-compatible servers (default: Validpin SaaS API) |

### `verify(license_key) -> bool`

Returns `True` if the license is valid (and caches the result for 24h). Returns `False` otherwise — inspect `client.last_error` for the reason.

### `enforce(license_key) -> None`

Calls `verify()` and **raises `PermissionError`** if the license is invalid. Returns `None` on success.

### `last_error: Optional[str]`

Human-readable reason for the last failure (`license_not_found`, `license_expired`, `Request timed out`, etc.).

---

## 🔒 Security

- License verification should always happen **server-side** — never trust client-only checks
- Keep your Website API Key (`lcs_...`) out of client-side code and version control
- If your key leaks, regenerate it from the Validpin dashboard — the old one becomes invalid immediately
- The Website API Key is **verify-only**: it cannot access dashboard, license-management, or other API endpoints

---

## 🧪 Development

```bash
# Install locally
pip install -e .

# Smoke test
python -c "from validpin_client import ValidpinClient; c = ValidpinClient('lcs_test'); print(c.api_url)"
```

---

## 📄 License

MIT © [Clerk Global LTD](https://github.com/Clerk-Global-LTD)

---

## 💬 Support

- **Platform**: https://validpin.com
- **Issues**: [Clerk-Global-LTD/validpin-client](https://github.com/Clerk-Global-LTD/validpin-client/issues)
- **Main Repo Issues**: [Clerk-Global-LTD/validpin](https://github.com/Clerk-Global-LTD/validpin/issues)
