Framework-agnostic Python SDK for DevPayr โ License enforcement, injectables, project & license management
Project description
๐ Introduction
DevPayr Python SDK is the official framework-agnostic client for integrating with DevPayr โ a modern licensing, domain enforcement, and injectable delivery system for SaaS and software products.
This SDK enables Python developers to:
- โ Validate license keys securely (with or without payment enforcement)
- ๐ Stream and decrypt encrypted injectables from the DevPayr backend
- ๐ Enforce domain/subdomain access using DevPayr's project-bound policies
- โ๏ธ Manage projects, licenses, domains, API keys, and more
- ๐ Handle automatic revalidation or failover behavior for expired or revoked licenses
It is designed to work with any Python environment, including:
- ๐ Flask, Django, FastAPI, or any other Python web framework
- ๐งฉ CLI scripts, background jobs, or system-level services
- ๐ฏ Desktop software or headless backend processors
You remain fully in control of what happens when a license is invalid โ show a modal, redirect users, log silently, or define a custom error handler.
Get started in minutes and enforce your license policies with confidence.
๐ฆ Installation
You can install the DevPayr Python SDK using either pip or by cloning the repository.
โ
Option 1: Install via pip (recommended)
If you're using PyPi (when published):
pip install devpayr-python-sdk
๐ง Option 2: Install via source (for local development)
- Clone the repository:
git clone https://github.com/xultech/devpayr-python-sdk.git
cd devpayr-python-sdk
- Install in editable mode:
pip install -e .
This allows you to edit the SDK source locally and test changes instantly without reinstalling.
๐ Optional Dependencies
If you want to enable encryption or validation features, the SDK automatically includes:
requestscryptography
To install these manually (if needed):
pip install requests cryptography
You're now ready to initialize
DevPayr.bootstrap()and begin validating license keys or streaming injectables.
๐ Getting Started
This section walks you through how to quickly set up and use the DevPayr SDK in your Python application.
๐ Basic Usage
from devpayr import DevPayr
DevPayr.bootstrap({
"license": "your-test-license-key", # Required if using license mode
"api_key": "your-api-key", # Optional if using API key mode
"base_url": "https://api.devpayr.dev/api/v1/", # Or your custom/self-hosted URL
"secret": "your-shared-secret", # For decrypting injectables
"injectables": True,
"handleInjectables": True,
"injectablesVerify": True,
"injectablesPath": "./dev_injectables",
"invalidBehavior": "modal", # Can be: modal, redirect, log, silent
"redirectUrl": "https://yourdomain.com/upgrade",
"customInvalidMessage": "License check failed. Please contact support.",
"onReady": lambda data: print("โ
Validated:", data)
})
โ ๏ธ Note: If using injectables, you must specify
secretandinjectablesPath. In fact, secret is always required
๐งช Validate License Before Execution
When using license validation (license key), the SDK will automatically:
- Contact DevPayrโs API
- Validate payment or subscription
- Optionally fetch and decrypt injectables
- Trigger a failure behavior (modal, redirect, log, or silent)
๐ Behavior on Invalid License
You can control what happens when the license is invalid via:
| Mode | Description |
|---|---|
modal |
Displays a styled HTML page to block app usage (default) |
redirect |
Opens a browser tab to a custom upgrade/payment URL |
log |
Prints an error message to stderr |
silent |
Does nothing (silent failure โ use with caution) |
๐ Injectables Handling
If injectables = True, the SDK will:
- Stream encrypted files for that license
- Decrypt and verify using
secret - Write them to
injectablesPath - Support modes like
append, prepend, replace
You can also override the default handler via a custom InjectableProcessor.
Now that you're set up, you can start accessing DevPayr's API through built-in service classes like:
from devpayr import DevPayr
DevPayr.projects().create({...})
DevPayr.licenses().list(project_id)
DevPayr.injectables().stream()
โ๏ธ Usage Examples
Here are some common examples of how to use the DevPayr Python SDK:
โ Basic License Validation
from devpayr import DevPayr
DevPayr.bootstrap({
"license": "your-license-key",
"secret": "your-shared-secret",
"injectables": True,
"onReady": lambda data: print("โ
License valid:", data),
"invalidBehavior": "modal", # Options: modal, redirect, log, silent
})
Alternatively, if you want more control:
from devpayr import Config, RuntimeValidator
config = Config({
"license": "your-license-key",
"secret": "your-shared-secret",
"injectables": True
})
validator = RuntimeValidator(config)
result = validator.validate()
print("โ
License valid:", result)
๐ Project Creation
from devpayr import DevPayr
DevPayr.bootstrap({ "api_key": "your-api-key" })
project = DevPayr.projects().create({
"name": "My App",
"description": "A sample project",
"is_active": True
})
print("๐ Project created:", project)
Or manually:
from devpayr import Config, ProjectService
config = Config({ "api_key": "your-api-key" })
project_service = ProjectService(config)
project = project_service.create({
"name": "My App",
"description": "A sample project",
"is_active": True
})
print("๐ Project created:", project)
๐ License Management
from devpayr import DevPayr
DevPayr.bootstrap({ "api_key": "your-api-key" })
licenses = DevPayr.licenses().list(project_id=1)
print("๐ Licenses:", licenses)
Or:
from devpayr import Config, LicenseService
config = Config({ "api_key": "your-api-key" })
license_service = LicenseService(config)
licenses = license_service.list(project_id=1)
๐ Domain Management
from devpayr import DevPayr
DevPayr.bootstrap({ "api_key": "your-api-key" })
domain = DevPayr.domains().create(project_id=1, data={
"domain": "example.com"
})
๐ฆ Injectable Streaming
from devpayr import DevPayr
DevPayr.bootstrap({
"license": "your-license-key",
"secret": "your-shared-secret",
"injectables": True
})
# Injectables are automatically processed and written to file.
You can also fetch them manually:
from devpayr import Config, InjectableService
config = Config({
"license": "your-license-key",
"secret": "your-shared-secret"
})
service = InjectableService(config)
injectables = service.stream()
print("๐ฆ Injectables:", injectables)
๐ Runtime Validation & Injectables
The DevPayr Python SDK supports runtime license validation and secure injectable management. When configured, the SDK automatically validates your license and handles injectables securely.
๐งช How It Works
-
License Validation
WhenDevPayr.bootstrap()is called with alicenseandsecret, the SDK makes a call to the DevPayr backend to validate the license using yoursecret. -
Injectable Fetching
Ifinjectables=True, the SDK will request the encrypted injectables associated with your license. -
Decryption & Signature Verification
Each injectable is:- Decrypted using AES-256-CBC with the
secret - Verified using HMAC-SHA256 signature
- Decrypted using AES-256-CBC with the
-
Writing Injectables
IfhandleInjectables=True, verified injectables are written to your filesystem using thetarget_pathandmode(append,prepend,replace).
๐ Example Configuration
from devpayr import DevPayr
DevPayr.bootstrap({
"license": "your-license-key",
"secret": "your-shared-secret",
"injectables": True,
"handleInjectables": True,
"injectablesVerify": True,
"injectablesPath": "runtime/",
"onReady": lambda data: print("โ
All good:", data)
})
๐ก Notes
- All written files are placed in
injectablesPath(defaults to current directory). - Signature verification ensures content has not been tampered with.
- You can set
injectablesVerify=Falseto skip HMAC verification (not recommended).
๐งฐ Custom Injectable Processor
You can define your own custom injectable processor by implementing the InjectableProcessorInterface. This allows you to take full control of how injectables are decrypted, verified, and saved (e.g., storing in a DB, writing to disk, or injecting into memory).
To use a custom processor, simply pass it via the injectablesProcessor key in the DevPayr.bootstrap() config.
๐ง Example: Custom Processor Implementation
from devpayr.contracts.injectable_processor import InjectableProcessorInterface
from devpayr.crypto.crypto_helper import CryptoHelper
from devpayr.crypto.hash_helper import HashHelper
import os
class MyInjectableProcessor(InjectableProcessorInterface):
@staticmethod
def handle(injectable: dict, secret: str, base_path: str, verify_signature: bool = True) -> str:
encrypted = injectable.get("encrypted_content")
signature = injectable.get("signature")
if verify_signature:
expected = HashHelper.signature(encrypted, secret)
if signature != expected:
raise Exception("Invalid injectable signature")
decrypted = CryptoHelper.decrypt(encrypted, secret)
target_path = os.path.join(base_path, injectable.get("target_path"))
os.makedirs(os.path.dirname(target_path), exist_ok=True)
with open(target_path, "w", encoding="utf-8") as f:
f.write(decrypted)
return target_path
โ๏ธ Using the Processor
from devpayr import DevPayr
DevPayr.bootstrap({
"license": "your-license-key",
"secret": "your-shared-secret",
"injectables": True,
"handleInjectables": True,
"injectablesProcessor": MyInjectableProcessor,
})
โ With this setup, your injectables will be processed using your custom logic instead of the default built-in handler.
โ Failure Modes & Behavior
When the SDK fails to validate a license (e.g., expired, revoked, or invalid), the invalidBehavior config key determines how the SDK should respond. This is useful for preventing unauthorized access while offering flexible handling strategies.
๐ ๏ธ Supported invalidBehavior Options
| Mode | Description |
|---|---|
modal |
Prints a styled HTML message to the screen (for CLI or frontend display). This is the default behavior. |
redirect |
Opens the provided redirectUrl in the browser and exits. Useful in desktop or GUI apps. |
log |
Logs the error message to stderr without exiting the program. |
silent |
Suppresses all error output and continues execution (not recommended). |
๐งพ Example
DevPayr.bootstrap({
"license": "your-license-key",
"secret": "your-shared-secret",
"invalidBehavior": "redirect",
"redirectUrl": "https://yourapp.com/license-error"
})
๐งฉ Custom Error Message or View
You can customize the modal output by using:
customInvalidMessage: A string to override the default error message.customInvalidView: A path to your own .html file to render instead of the default modal.
DevPayr.bootstrap({
"license": "your-license-key",
"secret": "your-shared-secret",
"invalidBehavior": "modal",
"customInvalidMessage": "Your license is no longer valid. Please contact support.",
"customInvalidView": "/path/to/custom_error.html"
})
๐ Note: If using modal, the SDK will attempt to render a default HTML view (resources/unlicensed.html) if no custom view is provided.
๐งช Testing
The DevPayr Python SDK includes direct test scripts within the tests/ directory for validating various components such as license validation, injectables handling, encryption, and service APIs.
These tests can be run individually without any test runner like pytest โ just using standard Python.
โ Running Tests
To run a test file, use:
python tests/test_runtime_validator.py
Or any other test file in the tests/ folder, for example:
python tests/test_crypto_and_hash.py
python tests/test_config.py
๐ Credits / Acknowledgments
The DevPayr Python SDK was developed by the team at XulTech as part of the broader DevPayr ecosystem.
๐จโ๐ป Lead Developer
- Erastus U. (XulTech) โ Conceptualized and led development of the SDK.
๐ง Built With
requestsโ HTTP communicationcryptographyโ AES-256-CBC encryptionunittest.mockโ Testing utilities
๐ Inspired By
- Common SDK patterns in the open-source community.
- Feedback from real developers who wanted license protection without complexity.
Thank you for supporting DevPayr.
Together, weโre building a safer world for developers and digital product creators.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file devpayr_python_sdk-0.1.2.tar.gz.
File metadata
- Download URL: devpayr_python_sdk-0.1.2.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c82d05d763d902cffedffcf678ada67dc213da8156fcaf765af84d089fd24961
|
|
| MD5 |
d86f477c2275ff265417cb694f10b28e
|
|
| BLAKE2b-256 |
f263e160d81f530982038529bd4e174305eb4596eee4f2ce6fa4eb25c714ec35
|
File details
Details for the file devpayr_python_sdk-0.1.2-py3-none-any.whl.
File metadata
- Download URL: devpayr_python_sdk-0.1.2-py3-none-any.whl
- Upload date:
- Size: 20.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2a3101a23336145b8d055e71b6608c3c04071a8d17e074b0b0d5eba41f41d3c
|
|
| MD5 |
fe4dcda45e8e0a39da4712952b813677
|
|
| BLAKE2b-256 |
4a9818eb2f66234f4219d3b972b17ef24f3c96f2d6c87d6fd2e86b0903bf8e95
|