Skip to content
Docs/SDK/Python
Edit on GitHub

Python SDK

The Python client provides typed clients for APIGuard, NIS2 Compass, and CITADEL, plus dataclasses for all opensecstack SDK & Contracts integration contracts. It requires Python 3.11+. Both synchronous and async clients are available.

Installation

Install the package from PyPI:

Bash
pip install opensecstack

Import the clients you need:

Bash
from opensecstack import APIGuardClient, NIS2CompassClient
from opensecstack.citadel import CITADELClient, Kerkese, Action, Principal, Evidence

Client construction

Clients accept a base_url and an api_key. An optional timeout (in seconds) can be passed; the default is 30 s. Clients support use as context managers to ensure the underlying session is closed.

Bash
from opensecstack import APIGuardClient

"cm"># Standard usage
client = APIGuardClient(
    base_url="https://apiguard.internal",
    api_key="ag_key_...",
    timeout=30,
)

"cm"># Context manager — session closed automatically on exit
with APIGuardClient(base_url="https://apiguard.internal", api_key="ag_key_...") as client:
    result = client.get_scan(scan_id)

Running a scan

Start an APIGuard scan and use the blocking wait_for_scan helper to poll until the scan completes, then iterate over the findings.

Bash
from opensecstack import APIGuardClient

client = APIGuardClient(base_url="https://apiguard.internal", api_key="ag_key_...")

"cm"># Start scan with selected OWASP modules
scan = client.start_scan(
    target="https://api.example.com",
    spec_url="https://api.example.com/openapi.json",
    modules=["bola", "broken_auth", "injection"],
    metadata={"project": "my-project-001"},
)
print(f"Scan ID: {scan.id}")

"cm"># Block until complete (polls every 5 s, times out after 600 s)
result = client.wait_for_scan(
    scan_id=scan.id,
    poll_interval=5,
    timeout=600,
)

for finding in result.findings:
    print(f"[{finding.severity}] {finding.owasp} — {finding.title}")

An async client is also available for non-blocking workflows:

Bash
from opensecstack import AsyncAPIGuardClient

async with AsyncAPIGuardClient(
    base_url="https://apiguard.internal",
    client_id="...",
    client_secret="...",
) as client:
    scan = await client.create_scan(spec_url="https://api.example.com/openapi.json")
    result = await client.get_scan(scan["id"])

NIS2 Compass client

Create an assessment, list its controls, and mark a NIS2 Article 21 measure as compliant after uploading evidence from an APIGuard scan.

Bash
from opensecstack import NIS2CompassClient

nis2 = NIS2CompassClient(base_url="https://nis2compass.internal", api_key="nc_key_...")

"cm"># Create organisation
org = nis2.create_organisation(
    name="Acme Corp",
    industry="finance",
    country="AL",
    size="large",
    entity_type="essential",
)

"cm"># Create assessment
assessment = nis2.create_assessment(
    org_id=org.id,
    title="Q1 2026 NIS2 Assessment",
    framework_version="NIS2-2022/0383",
)

"cm"># List controls and print current status
assessment = nis2.get_assessment(org.id, assessment.id)
for control in assessment.controls:
    print(f"{control.measure_ref}: {control.status}")

"cm"># Mark control art21_e as compliant
updated = nis2.patch_control(
    org_id=org.id,
    assessment_id=assessment.id,
    measure_ref="art21_e",
    status="compliant",
    notes="APIGuard scan completed — zero critical findings",
    evidence_refs=["sha256:abc123..."],
)

CITADEL client

Submit a governance Kerkese request to the MARSHAL 5-gate engine and check the outcome before proceeding with a privileged action.

Bash
from opensecstack.citadel import CITADELClient, Kerkese, Action, Principal, Evidence

client = CITADELClient(
    base_url="https://citadel.internal",
    key_id=KEY_ID,
    secret=SECRET,
)

"cm"># Check for active advisories before acting
advisory = client.get_advisory("my-project-001", "deploy_change")
if advisory.has_critical():
    print(f"CITADEL advisory: {advisory.advisories}")

"cm"># Submit a governance request and evaluate
result = client.evaluate(Kerkese(
    project_id="my-project-001",
    action=Action(type="deploy_change", description="Deploy v2.1.0"),
    actor=Principal(user_id="alice@example.com", role="group_sig_operator"),
    verifier=Principal(user_id="bob@example.com", role="group_sig_verifier"),
    evidence=Evidence(change_id="CHG-001"),
))

if result["outcome"] != "EXECUTE":
    raise RuntimeError(f"Governance denied: {result['reasons']}")

Error handling

Import exception types from opensecstack.exceptions to handle specific failure modes. RateLimitError carries a retry_after attribute (seconds) to guide back-off logic.

Bash
from opensecstack.exceptions import RateLimitError, AuthError, NotFoundError
import time

try:
    result = client.start_scan(
        target="https://api.example.com",
        spec_url="https://api.example.com/openapi.json",
    )
except RateLimitError as e:
    time.sleep(e.retry_after)
    result = client.start_scan(...)  "cm"># retry
except AuthError:
    raise  "cm"># re-raise — fix the API key
except NotFoundError:
    raise
ExceptionHTTP statusMeaning
AuthError401Invalid API key
NotFoundError404Resource not found
RateLimitError429Rate limited; has retry_after attribute
ServerError5xxServer-side error

Full documentation

Other SDK language clients: Go SDK, TypeScript SDK, Rust SDK.

The complete Python client reference — including all method signatures, dataclass definitions, and type hints — is available in the SDK repository:

https://github.com/opensecstack/opensecstack/tree/main/sdk

SIN — Security Intelligence Network — Open-source cybersecurity & compliance for the EU Digital Decade.

Apache-2.0 & AGPL-3.0 · GitHub · Contribute