Python SDK AI Prompt
Copy/paste this prompt into your AI assistant (e.g., GitHub Copilot Chat, Cursor, ChatGPT) to integrate the ExisOne Python SDK into your application.
Prompt
You're assisting me in integrating the ExisOne Python SDK for software licensing.
GOAL
- Generate a stable hardware ID on first run
- Activate a license with user input (activation key + email) and report app version
- Validate the license on every app start (online or offline) with version checking
- Check for software updates by comparing client version to server version
- Deactivate the license from the same hardware when requested
- Support offline customers with RSA-signed offline activation codes
- Submit support tickets from within the app
CONTEXT
- SDK package: exisone-client (version 0.7.0)
- Python: 3.8+
- I have an API base URL and an access token (format: exo_at_<public>_<secret>)
- Validate requires 'verify' permission on the access token
- For offline validation, I have an RSA public key (PEM format) from the Crypto Keys page
- Server may enforce minimum version requirements - client must handle version_outdated status
REQUIREMENTS
1) Install the package:
pip install exisone-client
2) Initialize the client:
from exisone import ExisOneClient, ExisOneClientOptions
options = ExisOneClientOptions(
base_url="https://YOUR-API-HOST",
access_token="exo_at_PUBLIC_SECRET",
offline_public_key="""-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
-----END PUBLIC KEY-----""" # Optional: for offline license validation
)
client = ExisOneClient(options)
# Log SDK version
print(f"ExisOne SDK: {client.get_version()}")
3) Hardware ID:
- On first run, compute client.generate_hardware_id(), persist locally (e.g., config file, user data)
- Reuse the persisted value thereafter
- Display to user so they can request offline licenses if needed
4) Activation flow with version:
- Ask for Activation Key (or Offline Code) and Email
- For online keys with version check:
result = client.activate(
activation_key=key,
email=email,
hardware_id=hardware_id,
product_name="MyProduct",
version="1.0.0"
)
if not result.success:
if result.error_code == "version_outdated":
# User must upgrade before activating
show_error(f"Please upgrade to version {result.minimum_required_version}")
else:
show_error(result.error_message)
else:
# Activation successful - optionally notify about updates
if result.server_version != "1.0.0":
show_info(f"Update available: v{result.server_version}")
- For offline codes: use validate_offline() or validate_smart() - no activation needed
5) Validation with version check:
- Rich validation with version:
result = client.validate(
activation_key=key,
hardware_id=hwid,
product_name="MyProduct",
version="1.0.0"
)
if result.status == "version_outdated":
# Force upgrade - license valid but version too old
show_error(f"Please upgrade to version {result.minimum_required_version} to continue")
return
if result.is_valid:
print(f"Licensed until: {result.expiration_date}")
print(f"Features: {', '.join(result.features)}")
# Optionally check for updates
if result.server_version and result.server_version != "1.0.0":
show_info(f"Update available: v{result.server_version}")
- Smart validation (handles online/offline):
result = client.validate_smart(key_or_code, hardware_id, "MyProduct")
# result.server_version and result.minimum_required_version available
6) Offline-only validation (no network):
- result = client.validate_offline(offline_code, hardware_id)
- Check result.is_valid, result.is_expired, result.hardware_mismatch
- Use when you know the user has an offline code and want zero network calls
7) Deactivation flow:
- For smart deactivation (tries server, succeeds locally if offline):
result = client.deactivate_smart(key_or_code, hardware_id, "MyProduct")
print(f"Success: {result.success}, Server notified: {result.server_notified}")
- Legacy online-only: client.deactivate(key, hardware_id, "MyProduct")
8) Support tickets:
- Provide a form (product, email, subject, message)
- Call: client.send_support_ticket(product_name, email, subject, message)
9) Offline license workflow for customers without internet:
- Customer sees their Hardware ID in your app (from generate_hardware_id())
- Customer contacts you (email/phone) with their Hardware ID
- You generate an Offline Activation Code in the License Keys dashboard
- Customer enters the long code into your app
- Your app validates using validate_offline() or validate_smart()
10) Tenancy:
- Ensure the access token belongs to the same tenant that owns the activation keys
11) Version enforcement handling:
- Always pass your app's version during activation and validation
- Handle "version_outdated" status by prompting user to upgrade
- Use server_version to notify users when updates are available
- minimum_required_version tells you the oldest acceptable version
12) Error handling:
import requests
try:
result = client.validate(activation_key, hardware_id)
except requests.HTTPError as e:
print(f"HTTP error: {e.response.status_code}")
except requests.RequestException as e:
print(f"Network error: {e}")
OFFLINE CODE SECURITY
- Offline codes are RSA-SHA256 signed (Base32 encoded with dashes)
- They embed: product ID, hardware ID, expiration date, email, features
- Cannot be forged, transferred, or modified
- Expiration is checked against local machine time
RESULT TYPES (0.7.0)
@dataclass
class ActivationResult:
success: bool
error_code: str | None
error_message: str | None
server_version: str | None
minimum_required_version: str | None
license_data: str | None
@dataclass
class ValidationResult:
is_valid: bool
status: str
expiration_date: datetime | None
features: list[str]
server_version: str | None
minimum_required_version: str | None
@dataclass
class OfflineValidationResult:
is_valid: bool
error_message: str | None
product_name: str | None
expiration_date: datetime | None
features: list[str]
is_expired: bool
hardware_mismatch: bool
@dataclass
class SmartValidationResult:
is_valid: bool
status: str
expiration_date: datetime | None
features: list[str]
was_offline: bool
error_message: str | None
product_name: str | None
server_version: str | None
minimum_required_version: str | None
@dataclass
class DeactivationResult:
success: bool
server_notified: bool
error_message: str | None
DELIVERABLES
- Add initialization and configuration code
- Implement activation UI supporting both online keys and offline codes
- Pass app version during activation and validation
- Handle version_outdated status with upgrade prompts
- Optionally notify users when server_version differs from current version
- Use validate_smart() for seamless online/offline handling
- Provide code snippets for persistence of hardware ID and license key/code
- Display hardware ID to users for offline license requests
- Ensure proper exception handling
Please produce idiomatic Python for my stack (PyQt/Tkinter/CLI/etc. as applicable), with concise functions and no extraneous commentary.
Notes
- See Python SDK Docs for full API details and permissions.
- Current SDK version:
0.7.0. - PyPI Package Page
- Features: Features return names (
list[str]) like["Export", "API Access"]. - Version enforcement: Pass client version during activation/validation; handle
version_outdatedstatus; receiveserver_versionandminimum_required_versionfor update notifications. - Offline validation: RSA-signed codes for air-gapped environments, smart validation with automatic fallback.
- Get your RSA public key from the Crypto Keys page for offline validation.
- Configure minimum version requirements in the Product Management page.