How to Add License Key Validation to Your Flask Application
Flask's lightweight, modular design makes it perfect for building APIs and microservices — but when you need to monetize your Flask application, you need license key validation. This guide shows you how to integrate Traffic Orchestrator into Flask with minimal boilerplate.
Why License Your Flask Application?
Flask powers REST APIs, webhook handlers, internal tools, and SaaS backends. License keys help you:
- Monetize your API with tiered access levels
- Enforce rate limits tied to license tiers
- Track which customers are using which features
- Prevent unauthorized access to premium endpoints
Step 1: Install the SDK
pip install traffic-orchestrator flask
Step 2: Initialize the Client
Create a shared client instance in your Flask application factory:
# app.py
from flask import Flask
from traffic_orchestrator import Client
to_client = Client( base_url="https://api.trafficorchestrator.com/api/v1", grace_period=True, grace_period_ttl=86400, )
def create_app(): app = Flask(__name__) app.config["TO_CLIENT"] = to_client return app ```
Step 3: Create a License Decorator
Flask decorators are the idiomatic way to protect routes:
# auth.py
from functools import wraps
from flask import request, jsonify, current_app
def require_license(feature=None): def decorator(f): @wraps(f) def decorated(args, *kwargs): key = request.headers.get("X-License-Key") if not key: return jsonify(error="License key required"), 401
client = current_app.config["TO_CLIENT"] result = client.validate_license( key=key, domain=request.host )
if not result["valid"]: return jsonify(error="Invalid license", reason=result.get("error")), 403
if feature and feature not in result.get("features", []): return jsonify(error=f"Feature '{feature}' not in your plan"), 403
request.license = result return f(args, *kwargs) return decorated return decorator ```
Step 4: Protect Your Routes
Apply the decorator to any Flask route:
# routes.py
from flask import Blueprint, jsonify, request
from .auth import require_license
api = Blueprint("api", __name__)
@api.route("/api/data") @require_license() def get_data(): return jsonify(data="Premium content", license=request.license["key"])
@api.route("/api/analytics") @require_license(feature="analytics") def get_analytics(): return jsonify(analytics={"views": 1234}, plan=request.license.get("plan"))
@api.route("/api/export") @require_license(feature="export") def export_data(): return jsonify(export="CSV data here") ```
Step 5: Add a License Validation Blueprint
Create a reusable blueprint to organize license-related endpoints:
# license_bp.py
from flask import Blueprint, request, jsonify, current_app
import hmac, hashlib, time
license_bp = Blueprint("license", __name__, url_prefix="/license")
@license_bp.route("/validate", methods=["POST"]) def validate(): data = request.get_json() client = current_app.config["TO_CLIENT"] result = client.validate_license( key=data.get("key", ""), domain=data.get("domain", request.host) ) return jsonify(result)
@license_bp.route("/webhook", methods=["POST"]) def webhook(): signature = request.headers.get("X-TO-Signature", "") timestamp = request.headers.get("X-TO-Timestamp", "0")
if time.time() - int(timestamp) > 300: return jsonify(error="Expired"), 401
body = request.get_data(as_text=True) expected = hmac.new( current_app.config["WEBHOOK_SECRET"].encode(), f"{timestamp}.{body}".encode(), hashlib.sha256 ).hexdigest()
if not hmac.compare_digest(signature, expected): return jsonify(error="Invalid signature"), 401
event = request.get_json() # Process event return jsonify(received=True) ```
Step 6: Error Handling and Grace Periods
Handle network failures gracefully:
# Production-ready validation with error handling
from traffic_orchestrator import Client
client = Client( base_url="https://api.trafficorchestrator.com/api/v1", grace_period=True, grace_period_ttl=86400, )
def validate_with_fallback(key, domain): try: result = client.validate_license(key=key, domain=domain) if result.get("from_cache"): print("Using cached validation (API unreachable)") return result except Exception as e: print(f"Validation error: {e}") return {"valid": False, "error": "Service unavailable"} ```
Next Steps
- Read the full Python SDK documentation
- Set up webhook integration for real-time events
- Explore domain binding for SaaS protection
- Learn about offline verification for edge deployments
Traffic Orchestrator's edge-native architecture means license validation adds less than 10ms of latency to your Flask API responses — faster than a database query.
Ship licensing in your next release
5 licenses, 500 validations/month, full API access. Set up in under 5 minutes — no credit card required.