Official Python SDK for LicenseChain - Secure license management for Python applications.
- 🔐 Secure Authentication - User registration, login, and session management
- 📜 License Management - Create, validate, update, and revoke licenses
- 🛡️ Hardware ID Validation - Prevent license sharing and unauthorized access
- 🔔 Webhook Support - Real-time license events and notifications
- 📊 Analytics Integration - Basic and advanced analytics with comprehensive metrics
- 📦 Product Management - Create and manage products for license sales (Seller)
- 👥 Team Collaboration - Team management and shared app/license access (Pro+)
- ⚡ High Performance - Optimized for production workloads
- 🔄 Async Operations - Non-blocking HTTP requests and data processing
- 🛠️ Easy Integration - Simple API with comprehensive documentation
# Install via pip
pip install licensechain-sdk
# Or with specific version
pip install licensechain-sdk==1.0.0# Install via pipenv
pipenv install licensechain-sdk# Install via Poetry
poetry add licensechain-sdk- Download the latest release from GitHub Releases
- Extract to your project directory
- Install dependencies
importasynciofromlicensechainimportLicenseChainClient, LicenseChainConfigasyncdefmain():
# Initialize the clientconfig=LicenseChainConfig(
api_key="your-api-key",
app_name="your-app-name",
version="1.0.0"
)
client=LicenseChainClient(config)
# Connect to LicenseChaintry:
awaitclient.connect()
print("Connected to LicenseChain successfully!")
exceptExceptionase:
print(f"Failed to connect: {e}")
if__name__=="__main__":
asyncio.run(main())# Register a new usertry:
user=awaitclient.register("username", "password", "email@example.com")
print("User registered successfully!")
print(f"User ID: {user.id}")
exceptExceptionase:
print(f"Registration failed: {e}")
# Login existing usertry:
user=awaitclient.login("username", "password")
print("User logged in successfully!")
print(f"Session ID: {user.session_id}")
exceptExceptionase:
print(f"Login failed: {e}")# Validate a licensetry:
license=awaitclient.validate_license("LICENSE-KEY-HERE")
print("License is valid!")
print(f"License Key: {license.key}")
print(f"Status: {license.status}")
print(f"Expires: {license.expires}")
print(f"Features: {', '.join(license.features)}")
print(f"User: {license.user}")
exceptExceptionase:
print(f"License validation failed: {e}")
# Get user's licensestry:
licenses=awaitclient.get_user_licenses()
print(f"Found {len(licenses)} licenses:")
fori, licenseinenumerate(licenses):
print(f" {i+1}. {license.key} - {license.status} (Expires: {license.expires})")
exceptExceptionase:
print(f"Failed to get licenses: {e}")# Get hardware ID (automatically generated)hardware_id=client.get_hardware_id()
print(f"Hardware ID: {hardware_id}")
# Validate hardware ID with licensetry:
is_valid=awaitclient.validate_hardware_id("LICENSE-KEY-HERE", hardware_id)
ifis_valid:
print("Hardware ID is valid for this license!")
else:
print("Hardware ID is not valid for this license.")
exceptExceptionase:
print(f"Hardware ID validation failed: {e}")# Set up webhook handlerdefwebhook_handler(event, data):
print(f"Webhook received: {event}")
ifevent=="license.created":
print(f"New license created: {data['licenseKey']}")
elifevent=="license.updated":
print(f"License updated: {data['licenseKey']}")
elifevent=="license.revoked":
print(f"License revoked: {data['licenseKey']}")
client.set_webhook_handler(webhook_handler)
# Start webhook listenerawaitclient.start_webhook_listener()Use the canonical API base URL https://api.licensechain.app/v1. The SDK also accepts the root host and normalizes requests to the same API version.
- Production:
https://api.licensechain.app/v1 - Development:
https://api.licensechain.app/v1
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/health | Health check |
POST | /v1/auth/login | User login |
POST | /v1/auth/register | User registration |
GET | /v1/apps | List applications |
POST | /v1/apps | Create application |
GET | /v1/licenses | List licenses |
POST | /v1/licenses/verify | Verify license |
GET | /v1/webhooks | List webhooks |
POST | /v1/webhooks | Create webhook |
GET | /v1/analytics | Get analytics |
Note: The SDK accepts either the root host or the canonical /v1 base and normalizes endpoint requests automatically.
config=LicenseChainConfig(
api_key="your-api-key",
app_name="your-app-name",
version="1.0.0",
base_url="https://api.licensechain.app/v1"# Optional
)
client=LicenseChainClient(config)# Connect to LicenseChainawaitclient.connect()
# Disconnect from LicenseChainawaitclient.disconnect()
# Check connection statusis_connected=client.is_connected()# Register a new useruser=awaitclient.register(username, password, email)
# Login existing useruser=awaitclient.login(username, password)
# Logout current userawaitclient.logout()
# Get current user infouser=awaitclient.get_current_user()# Validate a licenselicense=awaitclient.validate_license(license_key)
# Get user's licenseslicenses=awaitclient.get_user_licenses()
# Create a new licenselicense=awaitclient.create_license(user_id, features, expires)
# Update a licenselicense=awaitclient.update_license(license_key, updates)
# Revoke a licenseawaitclient.revoke_license(license_key)
# Extend a licenselicense=awaitclient.extend_license(license_key, days)# Get hardware IDhardware_id=client.get_hardware_id()
# Validate hardware IDis_valid=awaitclient.validate_hardware_id(license_key, hardware_id)
# Bind hardware ID to licenseawaitclient.bind_hardware_id(license_key, hardware_id)# Set webhook handlerclient.set_webhook_handler(handler)
# Start webhook listenerawaitclient.start_webhook_listener()
# Stop webhook listenerawaitclient.stop_webhook_listener()# Get basic dashboard insights (all tiers)insights=awaitclient.get_dashboard_insights()
# Get advanced analytics (Pro+ tier)advanced=awaitclient.get_advanced_analytics(
start_date="2024-01-01",
end_date="2024-12-31",
metric="revenue"
)
# Get general analyticsanalytics=awaitclient.get_analytics(
app_id="app_123",
start_date="2024-01-01",
end_date="2024-12-31"
)
# Get usage statisticsusage=awaitclient.get_usage_stats(period="30d")
# Get license-specific analyticslicense_analytics=awaitclient.get_license_analytics("license_id")# List productsproducts=awaitclient.list_products(
limit=50,
offset=0,
active=True,
search="Premium"
)
# Create a productproduct=awaitclient.create_product(
name="Premium License",
price=99.99,
description="Premium license with all features",
currency="USD",
active=True
)
# Update a productupdated=awaitclient.update_product(
product_id="product_123",
price=149.99,
description="Updated description"
)
# Get product analyticsanalytics=awaitclient.get_product_analytics(product_id="product_123")
# Delete a product (if no licenses)awaitclient.delete_product("product_123")# List teamsteams=awaitclient.list_teams()
# Create a teamteam=awaitclient.create_team(
name="Development Team",
description="Team for development"
)
# Get team detailsteam_details=awaitclient.get_team("team_123")
# Invite team memberawaitclient.invite_team_member(
team_id="team_123",
email="member@example.com",
role="member"# owner, admin, or member
)
# List team membersmembers=awaitclient.list_team_members("team_123")
# Update team member roleawaitclient.update_team_member(
team_id="team_123",
member_id="member_123",
role="admin"
)
# Remove team memberawaitclient.remove_team_member("team_123", "member_123")
# Share app with teamawaitclient.share_app_with_team("team_123", "app_123")
# List team appsteam_apps=awaitclient.list_team_apps("team_123")
# Remove app from teamawaitclient.remove_app_from_team("team_123", "app_123")
# Accept team invitationawaitclient.accept_team_invitation("team_123")
# Update teamawaitclient.update_team(
team_id="team_123",
name="Updated Team Name",
description="New description"
)
# Delete team (owner only)awaitclient.delete_team("team_123")Set these in your environment or through your build process:
# Requiredexport LICENSECHAIN_API_KEY=your-api-key
export LICENSECHAIN_APP_NAME=your-app-name
export LICENSECHAIN_APP_VERSION=1.0.0
# Optionalexport LICENSECHAIN_BASE_URL=https://api.licensechain.app/v1
export LICENSECHAIN_DEBUG=trueconfig=LicenseChainConfig(
api_key="your-api-key",
app_name="your-app-name",
version="1.0.0",
base_url="https://api.licensechain.app/v1",
timeout=30, # Request timeout in secondsretries=3, # Number of retry attemptsdebug=False, # Enable debug logginguser_agent="MyApp/1.0.0"# Custom user agent
)The SDK automatically generates and manages hardware IDs to prevent license sharing:
# Hardware ID is automatically generated and storedhardware_id=client.get_hardware_id()
# Validate against licenseis_valid=awaitclient.validate_hardware_id(license_key, hardware_id)- All API requests use HTTPS
- API keys are securely stored and transmitted
- Session tokens are automatically managed
- Webhook signatures are verified
- Real-time license validation
- Hardware ID binding
- Expiration checking
- Feature-based access control
# Track custom eventsawaitclient.track_event("app.started", {
"level": 1,
"playerCount": 10
})
# Track license eventsawaitclient.track_event("license.validated", {
"licenseKey": "LICENSE-KEY",
"features": "premium,unlimited"
})# Get performance metricsmetrics=awaitclient.get_performance_metrics()
print(f"API Response Time: {metrics.average_response_time}ms")
print(f"Success Rate: {metrics.success_rate:.2%}")
print(f"Error Count: {metrics.error_count}")try:
license=awaitclient.validate_license("invalid-key")
exceptInvalidLicenseError:
print("License key is invalid")
exceptExpiredLicenseError:
print("License has expired")
exceptNetworkErrorase:
print(f"Network connection failed: {e}")
exceptLicenseChainErrorase:
print(f"LicenseChain error: {e}")# Automatic retry for network errorsconfig=LicenseChainConfig(
api_key="your-api-key",
app_name="your-app-name",
version="1.0.0",
retries=3, # Retry up to 3 timestimeout=30# Wait 30 seconds for each request
)# Run tests
pytest
# Run tests with coverage
pytest --cov=licensechain
# Run specific test
pytest tests/test_client.py# Test with real API
pytest tests/integration/See the examples/ directory for complete examples:
basic_usage.py- Basic SDK usagebasic_analytics.py- Basic analytics featuresadvanced_analytics.py- Advanced analytics for Pro+ tierslicenses_comprehensive.py- Comprehensive license managementproducts_example.py- Product management (Seller only)teams_example.py- Team collaboration (Pro+ tiers)secure_integration.py- Secure integration example preventing license bypassingtest_connection.py- Test script to verify SDK-API connectiontest_licenses.py- Test script for validating specific license keys
The secure_integration.py example demonstrates how to properly integrate LicenseChain SDK into your application to prevent license bypassing:
Key Features:
- ✅ License validation on application startup
- ✅ Periodic re-validation (configurable interval)
- ✅ Hardware ID generation and validation
- ✅ Critical operation protection
- ✅ Secure state management with thread locks
- ✅ Environment variables for sensitive data
- ✅ Proper error handling and logging
Usage:
# Set environment variablesexport LICENSECHAIN_API_KEY='your-api-key'export LICENSECHAIN_LICENSE_KEY='your-license-key'export LICENSECHAIN_APP_ID='your-app-id'# Optional# Run the secure integration example
python examples/secure_integration.pyKey Implementation Points:
- Startup Validation: Always validate license when application starts
- Periodic Re-validation: Re-validate license at regular intervals
- Hardware ID Binding: Generate and validate hardware ID to prevent sharing
- Critical Operations: Protect critical operations with license checks
- Secure Storage: Never hardcode API keys or license keys
See examples/secure_integration.py for the complete implementation.
We welcome contributions! Please see our Contributing Guide for details.
- Clone the repository
- Install Python 3.8 or later
- Install dependencies:
pip install -r requirements.txt - Build:
python setup.py build - Test:
pytest
This project is licensed under the Elastic 2.0 License - see the LICENSE file for details.
- Documentation: https://docs.licensechain.app/python
- Issues: GitHub Issues
- Discord: LicenseChain Discord
- Email: support@licensechain.app
Made with ❤️ for the Python community
The official Python SDK for LicenseChain - a comprehensive license management platform. This SDK provides full API access for license validation, user management, application management, and more.
- ✅ License Management - Create, validate, update, and revoke licenses
- ✅ User Authentication - Complete user management and authentication
- ✅ Application Management - Manage applications and API keys
- ✅ Webhook Support - Secure webhook verification and handling
- ✅ Analytics - Access usage statistics and analytics
- ✅ Error Handling - Comprehensive error handling with custom exceptions
- ✅ Type Safety - Strong typing with Pydantic models
- ✅ Async/Await - Full async support for all operations
- ✅ Documentation - Comprehensive documentation and examples
pip install licensechain-python-sdkpipenv install licensechain-python-sdkpoetry add licensechain-python-sdkimportasynciofromlicensechainimportLicenseChainClientasyncdefmain():
# Create a clientclient=LicenseChainClient("your_api_key_here")
# Validate a licenseresult=awaitclient.validate_license("license_key_here")
ifresult["valid"]:
print("License is valid!")
print(f"User: {result['user']['email']}")
print(f"Expires: {result['expires_at']}")
else:
print(f"License is invalid: {result['error']}")
# Create a new licenselicense=awaitclient.create_license(
app_id="app_123",
user_email="user@example.com",
user_name="John Doe",
expires_at="2024-12-31T23:59:59Z"
)
print(f"Created license: {license['key']}")
# Close the clientawaitclient.close()
# Run the async functionasyncio.run(main())importasynciofromlicensechainimportLicenseValidatorasyncdefmain():
# Create a validator instancevalidator=LicenseValidator("your_api_key_here")
# Validate a license (returns ValidationResult object)result=awaitvalidator.validate_license("license_key_here")
ifresult.valid:
print("License is valid!")
print(f"User: {result.user_email}")
print(f"App: {result.app_name}")
print(f"Features: {', '.join(result.features)}")
print(f"Days until expiration: {result.days_until_expiration}")
else:
print(f"License is invalid: {result.error}")
# Quick validation checkifawaitvalidator.is_valid("license_key_here"):
print("License is valid!")
# Check if expiredifawaitvalidator.is_expired("license_key_here"):
print("License has expired!")
# Close the validatorawaitvalidator.close()
asyncio.run(main())importasynciofromlicensechainimportLicenseChainClient, LicenseValidatorasyncdefmain():
# Using context managers for automatic cleanupasyncwithLicenseChainClient("your_api_key_here") asclient:
result=awaitclient.validate_license("license_key_here")
print(f"Valid: {result['valid']}")
asyncwithLicenseValidator("your_api_key_here") asvalidator:
is_valid=awaitvalidator.is_valid("license_key_here")
print(f"Valid: {is_valid}")
asyncio.run(main())# Register a new useruser=awaitclient.register_user(
email="user@example.com",
password="secure_password",
name="John Doe",
company="Acme Corp"
)
# Loginsession=awaitclient.login(
email="user@example.com",
password="secure_password"
)
# Get user profileprofile=awaitclient.get_user_profile()
# Update user profileawaitclient.update_user_profile({
"name": "John Smith",
"company": "New Company"
})
# Change passwordawaitclient.change_password(
current_password="old_password",
new_password="new_password"
)
# Password resetawaitclient.request_password_reset("user@example.com")
awaitclient.reset_password(
token="reset_token",
new_password="new_password"
)# Create an applicationapp=awaitclient.create_application(
name="My App",
description="A great application",
webhook_url="https://myapp.com/webhooks",
allowed_origins=["https://myapp.com"]
)
# List applicationsapps=awaitclient.list_applications(page=1, limit=20)
# Get application detailsapp=awaitclient.get_application("app_123")
# Update applicationawaitclient.update_application("app_123", {
"name": "Updated App Name",
"description": "Updated description"
})
# Regenerate API keynew_key=awaitclient.regenerate_api_key("app_123")
# Delete applicationawaitclient.delete_application("app_123")# Create a licenselicense=awaitclient.create_license(
app_id="app_123",
user_email="user@example.com",
user_name="John Doe",
expires_at="2024-12-31T23:59:59Z",
metadata={"plan": "premium", "features": ["api_access"]}
)
# List licenseslicenses=awaitclient.list_licenses(
app_id="app_123",
page=1,
limit=20,
status="active"
)
# Get license detailslicense=awaitclient.get_license("lic_123")
# Update licenseawaitclient.update_license("lic_123", {
"metadata": {"plan": "enterprise"}
})
# Validate licenseresult=awaitclient.validate_license("license_key_here", app_id="app_123")
# Revoke licenseawaitclient.revoke_license("lic_123", reason="Violation of terms")
# Activate licenseawaitclient.activate_license("lic_123")
# Extend licenseawaitclient.extend_license("lic_123", "2025-12-31T23:59:59Z")
# Delete licenseawaitclient.delete_license("lic_123")# Create webhookwebhook=awaitclient.create_webhook(
app_id="app_123",
url="https://myapp.com/webhooks",
events=["license.created", "license.updated"],
secret="webhook_secret"
)
# List webhookswebhooks=awaitclient.list_webhooks(app_id="app_123")
# Update webhookawaitclient.update_webhook("webhook_123", {
"events": ["license.created", "license.updated", "license.revoked"]
})
# Test webhookawaitclient.test_webhook("webhook_123")
# Delete webhookawaitclient.delete_webhook("webhook_123")# Get analyticsanalytics=awaitclient.get_analytics(
app_id="app_123",
start_date="2024-01-01",
end_date="2024-12-31",
metric="validations"
)
# Get license analyticslicense_analytics=awaitclient.get_license_analytics("lic_123")
# Get usage statisticsusage=awaitclient.get_usage_stats(app_id="app_123", period="30d")The SDK provides Pydantic models for type safety and validation:
fromlicensechainimportUser, Application, License, ValidationResult# User modeluser=User(
email="user@example.com",
name="John Doe",
company="Acme Corp"
)
print(user.is_active)
# Application modelapp=Application(
name="My App",
description="A great application"
)
print(app.is_active)
# License modellicense=License(
app_id="app_123",
user_email="user@example.com",
expires_at="2024-12-31T23:59:59Z"
)
print(license.is_expired)
print(license.days_until_expiration)
# Validation resultresult=ValidationResult(
valid=True,
user={"email": "user@example.com"},
app={"name": "My App"}
)
print(result.user_email)
print(result.app_name)fromlicensechainimportWebhookHandler, WebhookVerifierclassMyWebhookHandler(WebhookHandler):
asyncdefhandle_license_created(self, event_data):
print(f"License created: {event_data['data']['id']}")
return {"status": "processed"}
asyncdefhandle_license_revoked(self, event_data):
print(f"License revoked: {event_data['data']['id']}")
return {"status": "processed"}
# Handle webhookshandler=MyWebhookHandler("webhook_secret")
result=awaithandler.handle(payload, signature)
# Or verify signatures manuallyverifier=WebhookVerifier("webhook_secret")
ifverifier.verify_signature(payload, signature):
data=verifier.parse_payload(payload, signature)
print(f"Event: {data['type']}")fromlicensechainimport (
LicenseChainException,
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError,
ServerError,
NetworkError
)
try:
result=awaitclient.validate_license("invalid_key")
exceptAuthenticationErrorase:
print(f"Authentication failed: {e}")
exceptValidationErrorase:
print(f"Validation error: {e}")
exceptNotFoundErrorase:
print(f"Resource not found: {e}")
exceptRateLimitErrorase:
print(f"Rate limit exceeded: {e}")
exceptServerErrorase:
print(f"Server error: {e}")
exceptNetworkErrorase:
print(f"Network error: {e}")
exceptLicenseChainExceptionase:
print(f"LicenseChain error: {e}")| Parameter | Type | Default | Description |
|---|---|---|---|
api_key | str | Required | Your LicenseChain API key |
base_url | str | https://api.licensechain.app/v1 | API base URL |
timeout | int | 30 | Request timeout in seconds |
retry_attempts | int | 3 | Number of retry attempts |
retry_delay | float | 1.0 | Delay between retries in seconds |
| Error Type | HTTP Status | Description |
|---|---|---|
AuthenticationError | 401, 403 | Authentication or authorization failed |
ValidationError | 400 | Invalid request data |
NotFoundError | 404 | Resource not found |
RateLimitError | 429 | Rate limit exceeded |
ServerError | 500-599 | Server error |
NetworkError | N/A | Network connectivity issues |
- Python 3.8 or later
- asyncio support
- httpx for HTTP requests
- pydantic for data validation
- httpx>=0.24.0
- pydantic>=2.0.0
- typing-extensions>=4.5.0
- requests>=2.31.0 (optional)
- cryptography>=41.0.0 (optional)
- python-dateutil>=2.8.0 (optional)
# Clone the repository
git clone https://github.com/LicenseChain/LicenseChain-Python-SDK.git
cd LicenseChain-Python-SDK
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate# Install dependencies
pip install -e ".[dev]"# Run tests
pytest
# Run linting
black licensechain/
isort licensechain/
flake8 licensechain/
# Build package
python -m build- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the Elastic License 2.0 (ELv2) — see the LICENSE file for details.
- 📧 Email: support@licensechain.app
- 📚 Documentation: https://docs.licensechain.app
- 🐛 Issues: https://github.com/LicenseChain/LicenseChain-Python-SDK/issues
- 💬 Telegram: https://t.me/LicenseChainBot
Made with ❤️ by the LicenseChain team
This SDK targets the LicenseChain HTTP API v1 implemented by the LicenseChain API service.
- Production base URL:https://api.licensechain.app/v1
- API reference:docs.licensechain.app
- Baseline REST mapping (documented for integrators):
- GET /health
- POST /auth/register
- POST /licenses/verify
- PATCH /licenses/:id/revoke
- PATCH /licenses/:id/activate
- PATCH /licenses/:id/extend
- GET /analytics/stats