Engineering

How to Add License Key Validation to Your Python Application

TOT
Traffic Orchestrator Team
Engineering
April 7, 2026 7 min read 757 words
Share

How to Add License Key Validation to Your Python Application

Whether you're building a CLI tool, a Django web app, or a desktop application with PyQt, adding license key validation protects your revenue. This tutorial walks you through the complete implementation using Python.

Prerequisites

  • Python 3.8+
  • A Traffic Orchestrator account (sign up free)
  • An API key from your dashboard
Try it yourself

Validate your first license key in under 5 minutes — free plan, no credit card required.

Installation

pip install traffic-orchestrator

The traffic-orchestrator package is published on PyPI and supports Python 3.8+.

Basic License Validation

The simplest integration is a single validation call:

from traffic_orchestrator import TrafficOrchestrator

Initialize with your API key client = TrafficOrchestrator(api_key="to_live_xxxxxxxxxxxx")

Validate a license key result = client.licenses.validate( key="LIC-XXXX-XXXX-XXXX", domain="app.example.com" # Optional: for domain-bound licenses )

if result.valid: print(f"License active — Plan: {result.plan}") print(f"Expires: {result.expires_at}") else: print(f"License invalid: {result.error}") ```

That's the entire integration. Three lines of real code.

Handling Edge Cases

Production code needs to handle more than the happy path:

import sys
from traffic_orchestrator import TrafficOrchestrator
from traffic_orchestrator.exceptions import (
    NetworkError,
    RateLimitError,
    InvalidKeyError
)

client = TrafficOrchestrator(api_key="to_live_xxxxxxxxxxxx")

def check_license(license_key: str) -> bool: """Validate license with graceful error handling.""" try: result = client.licenses.validate(license_key) if not result.valid: print(f"License expired or revoked: {result.error}") return False # Check if approaching expiration if result.days_remaining and result.days_remaining < 14: print(f"Warning: License expires in {result.days_remaining} days") return True except NetworkError: # Network is down — fall back to cached validation # or allow a grace period print("Network unavailable — using cached validation") return check_cached_license(license_key) except RateLimitError: # Too many validation requests print("Rate limited — using cached result") return check_cached_license(license_key) except InvalidKeyError: # Key format is wrong print("Invalid license key format") return False

def check_cached_license(key: str) -> bool: """Check locally cached validation result.""" import json from pathlib import Path from datetime import datetime, timedelta cache_file = Path.home() / ".myapp" / "license_cache.json" if not cache_file.exists(): return False cache = json.loads(cache_file.read_text()) if cache.get("key") != key: return False # Allow 7-day offline grace period cached_at = datetime.fromisoformat(cache["validated_at"]) if datetime.now() - cached_at > timedelta(days=7): return False return cache.get("valid", False) ```

Django Integration

For Django applications, create a middleware that checks the license on startup:

# myapp/middleware.py
from traffic_orchestrator import TrafficOrchestrator
from django.conf import settings
from django.http import HttpResponse

client = TrafficOrchestrator(api_key=settings.TO_API_KEY) _license_valid = None # Cache the result

class LicenseMiddleware: def __init__(self, get_response): self.get_response = get_response self._check_license() def _check_license(self): global _license_valid try: result = client.licenses.validate( key=settings.LICENSE_KEY, domain=settings.ALLOWED_HOSTS[0] ) _license_valid = result.valid except Exception: # On error, use previous cached state if _license_valid is None: _license_valid = False def __call__(self, request): if not _license_valid: return HttpResponse( "License validation failed. Please check your license key.", status=403 ) return self.get_response(request) ```

# settings.py
MIDDLEWARE = [
    'myapp.middleware.LicenseMiddleware',
    # ... other middleware
]

TO_API_KEY = os.environ.get('TRAFFIC_ORCHESTRATOR_API_KEY') LICENSE_KEY = os.environ.get('APP_LICENSE_KEY') ```

Flask Integration

For Flask, use a before_request hook:

from flask import Flask, abort
from traffic_orchestrator import TrafficOrchestrator

app = Flask(__name__) client = TrafficOrchestrator(api_key=app.config['TO_API_KEY'])

@app.before_first_request def validate_license(): result = client.licenses.validate(app.config['LICENSE_KEY']) if not result.valid: raise RuntimeError(f"Invalid license: {result.error}")

@app.route('/') def index(): return "Application running with valid license" ```

CLI Tool Protection

For command-line tools distributed via PyPI:

# cli.py
import click
from traffic_orchestrator import TrafficOrchestrator

client = TrafficOrchestrator(api_key="to_live_xxxxxxxxxxxx")

@click.group() def cli(): """My awesome CLI tool.""" pass

@cli.command() @click.argument('license_key') def activate(license_key: str): """Activate your license.""" result = client.licenses.validate(license_key) if result.valid: # Store the key locally config_dir = Path.home() / ".mytool" config_dir.mkdir(exist_ok=True) (config_dir / "license").write_text(license_key) click.echo("License activated successfully!") else: click.echo(f"Invalid license: {result.error}", err=True) sys.exit(1)

@cli.command() def run(): """Run the tool (requires valid license).""" license_file = Path.home() / ".mytool" / "license" if not license_file.exists(): click.echo("No license found. Run: mytool activate YOUR-KEY", err=True) sys.exit(1) key = license_file.read_text().strip() result = client.licenses.validate(key) if not result.valid: click.echo(f"License invalid: {result.error}", err=True) sys.exit(1) # Your actual tool logic here click.echo("Running with valid license...") ```

Best Practices

  1. Cache validation results — Don't validate on every function call. Cache for 1-24 hours.
  2. Handle offline gracefully — Allow a grace period (7-30 days) using cached results.
  3. Don't block the UI — Validate in a background thread for desktop apps.
  4. Store keys securely — Use the OS keyring, not plain text files, for production.
  5. Log validation failures — But never log the full license key itself.

Next Steps


Published by Traffic Orchestrator Team

Related Articles

TOT
Traffic Orchestrator Team
Engineering

The engineering team behind Traffic Orchestrator, building enterprise-grade software licensing infrastructure used by developers worldwide.

Was this article helpful?
Get licensing insights delivered

Engineering deep-dives, security advisories, and product updates. Unsubscribe anytime.

Share this article
Free Plan Available

Ship licensing in your next release

5 licenses, 500 validations/month, full API access. Set up in under 5 minutes — no credit card required.

2-minute setup No credit card Cancel anytime