Integration Guide

How to embed MeshOptixIQ licensing in a Python application — including key setup, reading plan data, gating features, and handling offline scenarios.

1. License Key Setup

MeshOptixIQ resolves the license key from the following sources, in order:

  1. Environment variableMESHOPTIXIQ_LICENSE_KEY
  2. License file~/.meshoptixiq/license.key (one key per line; first non-empty line is used)

Environment Variable (Docker / CI)

export MESHOPTIXIQ_LICENSE_KEY="mq-pro-xxxxxxxx"

License File (Persistent Installations)

mkdir -p ~/.meshoptixiq
echo "mq-pro-xxxxxxxx" > ~/.meshoptixiq/license.key
chmod 600 ~/.meshoptixiq/license.key

Community Plan

The Community plan requires no license key. If neither the environment variable nor the license file is present, the application automatically operates in Community tier with a 1-device limit.

2. How Verification Works

License verification is multi-layered to ensure reliability in both online and offline environments.

  1. Key resolution — The verifier reads the license key from the environment variable or license file at startup.
  2. Server validation (24h cache) — On first use and every 24 hours, the verifier sends an HMAC-signed request to the licensing API. The server checks expiry, device binding, and plan status, then returns an RSA-signed response containing the plan and feature flags.
  3. Local state cache — The signed response is written to an encrypted local state file. On subsequent calls within the 24-hour window, the verifier reads from this cache without hitting the network.
  4. 72-hour grace period — If the server is unreachable during a scheduled check, the cached state remains valid for up to 72 hours. The application continues operating normally; a warning is printed on every command.
  5. Grace expiry — After 72 hours without a successful server contact, the application enters restricted mode. All Pro/Enterprise features are disabled until connectivity is restored. Community-tier features always remain available.

3. Reading Plan and Features

CLI

meshq license info
# Example output:
Plan:    Pro
Status:  Active
Expires: 2027-06-30 (491 days remaining)
Device:  a3f8c1d2e4b5... (1/5 registered)

Feature Flags:
  api_access          true
  firewall_queries    true
  whatif_simulation   true
  mcp_server          true
  redis_clustering    true
  rbac                true
  netbox_sync         true
  audit_logging       true
  oidc_sso            false
  soar_webhooks       false

Device Limits:
  max_managed_devices    5
  max_network_devices    750

Python API

The verifier module exposes two public functions:

from network_discovery.licensing import verifier

# Current plan name (str): "community" | "starter" | "pro" | "enterprise"
plan = verifier.get_plan()

# Feature flags and device limits (dict)
features = verifier.get_features()
print(features["max_network_devices"])  # e.g. 750 for Pro
print(features["api_access"])           # True / False

Note: verifier.py is compiled to a Cython .so module in production builds. Do not import it directly by path — use from network_discovery.licensing import verifier to ensure the compiled module takes precedence over the source file.

4. Feature Gating Pattern

Use check_feature() from gates.py to gate functionality at runtime. The function raises FeatureNotAvailableError when the current plan does not include the requested feature.

from network_discovery.licensing.gates import check_feature, FeatureNotAvailableError

plan = verifier.get_plan()

try:
    check_feature(plan, "api_access")
    # proceed with API operation
except FeatureNotAvailableError as exc:
    print(f"Upgrade required: {exc}")
    sys.exit(1)

Demo Mode Bypass

When MESHOPTIXIQ_DEMO_MODE=true is set, all feature gates return True regardless of plan. Always check the environment variable before calling check_feature() to avoid stale compiled-module behaviour:

import os

if not os.environ.get("MESHOPTIXIQ_DEMO_MODE"):
    check_feature(plan, "firewall_queries")

Feature Flag Reference

Flag Available on Description
api_access Pro, Enterprise REST Query API access (/queries/*)
firewall_queries Pro, Enterprise Firewall policy query set (5 queries)
whatif_simulation Pro, Enterprise What-if change simulation (POST /graph/whatif)
mcp_server Pro, Enterprise MCP server for AI assistant integration
redis_clustering Pro, Enterprise Horizontal Redis clustering support
rbac Pro, Enterprise Role-based access control
netbox_sync Pro, Enterprise Bidirectional NetBox synchronisation
audit_logging Pro, Enterprise Tamper-evident audit log to SIEM
oidc_sso Enterprise OIDC/SSO identity provider integration
soar_webhooks Enterprise Automated SOAR webhook dispatch

5. Device Fingerprinting

Each paid plan has a maximum number of registered devices (distinct machines that have validated the same license key). The verifier generates a hardware fingerprint from a combination of:

This fingerprint is sent with every validation request. If the device is new and the plan limit has not been reached, it is registered automatically. If the limit is already reached, the validation returns a 409 Device Limit Exceeded error.

Device Limit Behaviour

The device count is visible in meshq license info (e.g., 1/5 registered). Administrators can deregister devices via the customer portal or by contacting support.

Container environments (Docker, Kubernetes) each count as a separate device if they have distinct MAC addresses. Use the MESHOPTIXIQ_LICENSE_KEY environment variable to share one key across replicas that share the same underlying host.

6. Offline / Grace Period

The verifier's behaviour when it cannot reach the licensing server:

Diagnosing Grace Period Issues

meshq license info

# If in grace period:
# Status:  WARNING — Offline grace period active (48h 12m remaining)
# Last validated: 2026-02-22 09:14 UTC (23h 48m ago)

# Trigger an immediate validation check:
meshq license info --refresh

Common causes of unexpected grace period activation:

7. Troubleshooting

Error / Symptom Cause Resolution
LicenseNotFoundError The license key does not exist in the database, or has been deleted after revocation TTL expiry. Verify the key is correct. Log in to the portal to confirm the license is active. Contact support if needed.
LicenseExpiredError The expiration_date has passed and the key has not been renewed. Renew the license via the portal. The application will pick up the new expiry on the next validation cycle.
Device limit exceeded (409) The maximum number of devices for this plan is already registered. Deregister unused devices in the portal under License → Devices, or upgrade to a higher plan.
Clock skew / HMAC failure The system clock is more than 5 minutes from UTC. The server rejects the signed request. Synchronise the system clock with an NTP server: timedatectl set-ntp true (Linux).
Grace period expires unexpectedly Network outage, firewall, DNS, or proxy issue preventing server contact. Test connectivity: curl -I https://api.meshoptixiq.com/health. Check outbound firewall rules for port 443.
FeatureNotAvailableError in code Calling a feature that is not included in the current plan. Check the feature flag table above. Upgrade to Pro or Enterprise, or guard the call with a plan check before invoking check_feature().
LicenseInvalidError: "invalid" Key was revoked or the server returned a 403. Often seen with test keys that were removed from the database. Issue a new key from the admin portal. Do not reuse revoked keys.