Skip to main content

QuantumAPI Python SDK

PyPI version Python Support License Documentation

Official Python SDK for QuantumAPI - The European quantum-safe encryption and identity platform.

Features

  • 🔐 Quantum-Safe Encryption - ML-KEM-768, ML-DSA-65, and hybrid encryption
  • 🔑 Key Management - Generate, rotate, and manage cryptographic keys
  • 🗄️ Secret Vault - Securely store and manage secrets with versioning
  • 👤 User Management - Create and manage end-users with roles
  • 🔍 Audit Logs - Query comprehensive audit trails
  • 💳 Billing Integration - Access subscription and usage metrics
  • 🚀 Async/Await Support - Full async support with httpx
  • ⚡ Automatic Retries - Exponential backoff for transient failures
  • 📊 Rate Limiting - Client-side rate limit tracking
  • 🎯 Type Safety - Complete type hints with Pydantic models

Installation

pip install quantumapi

For development:

pip install quantumapi[dev]

Quick Start

from quantumapi import QuantumAPIClient

# Initialize client with API key
client = QuantumAPIClient(api_key="qapi_xxx")

# Encrypt data
ciphertext = await client.encryption.encrypt(
    plaintext="secret data",
    key_id="550e8400-e29b-41d4-a716-446655440000"
)

# Store a secret
secret = await client.secrets.create(
    name="database_password",
    value="super_secret_password",
    labels=["production", "database"]
)

# Generate a new key pair
key = await client.keys.generate(
    name="encryption-key-2024",
    algorithm="ML-KEM-768",
    key_type="encryption"
)

# Retrieve secret
secret_value = await client.secrets.get(secret.id)
print(f"Secret: {secret_value.value}")

Synchronous API

If you prefer synchronous code, use the QuantumAPISyncClient:

from quantumapi import QuantumAPISyncClient

client = QuantumAPISyncClient(api_key="qapi_xxx")

# All methods work the same without await
ciphertext = client.encryption.encrypt(plaintext="secret data")

Configuration

The SDK can be configured via environment variables or constructor arguments:

client = QuantumAPIClient(
    api_key="qapi_xxx",              # Or set QUANTUMAPI_API_KEY
    base_url="https://api.quantumapi.eu",  # Optional, defaults to production
    timeout=30.0,                     # Request timeout in seconds
    max_retries=3,                    # Max retry attempts for failed requests
    enable_logging=True,              # Enable detailed logging
)

Environment Variables

  • QUANTUMAPI_API_KEY - Your API key
  • QUANTUMAPI_BASE_URL - API base URL (default: https://api.quantumapi.eu)
  • QUANTUMAPI_TIMEOUT - Request timeout in seconds (default: 30)
  • QUANTUMAPI_MAX_RETRIES - Maximum retry attempts (default: 3)

Core Modules

Encryption Client

# Encrypt data
result = await client.encryption.encrypt(
    plaintext="sensitive data",
    key_id="key-id",  # Optional, uses default key if not specified
    encoding="utf8"   # or "base64" for binary data
)

# Decrypt data
plaintext = await client.encryption.decrypt(
    encrypted_payload=result.encrypted_payload
)

# Sign data
signature = await client.encryption.sign(
    data="message to sign",
    key_id="signing-key-id"
)

# Verify signature
is_valid = await client.encryption.verify(
    data="message to sign",
    signature=signature.signature,
    key_id="signing-key-id"
)

Keys Client

# Generate key pair
key = await client.keys.generate(
    name="my-encryption-key",
    key_type="encryption",
    algorithm="ML-KEM-768",
    set_as_default=True
)

# List keys
keys = await client.keys.list(
    key_type="encryption",
    page=1,
    page_size=50
)

# Get key details
key = await client.keys.get(key_id="key-id")

# Rotate key
new_key = await client.keys.rotate(key_id="key-id")

# Delete key
await client.keys.delete(key_id="key-id")

# Set default key
await client.keys.set_default(key_id="key-id", key_type="encryption")

Secrets Client

# Create secret
secret = await client.secrets.create(
    name="api-key",
    value="secret_value",
    content_type="api-key",
    labels=["prod", "stripe"],
    expires_at="2025-12-31T23:59:59Z"
)

# List secrets
secrets = await client.secrets.list(
    content_type="password",
    label="production",
    page=1
)

# Get secret
secret = await client.secrets.get(secret_id="secret-id")

# Update secret value
await client.secrets.update_value(
    secret_id="secret-id",
    value="new_secret_value"
)

# Update secret metadata
await client.secrets.update(
    secret_id="secret-id",
    name="new-name",
    labels=["staging"]
)

# Delete secret
await client.secrets.delete(secret_id="secret-id")

Users Client

# Create user
user = await client.users.create(
    email="user@example.com",
    name="John Doe",
    role="developer"
)

# List users
users = await client.users.list(active_only=True)

# Update user
await client.users.update(
    user_id="user-id",
    name="Jane Doe",
    role="admin"
)

# Deactivate user
await client.users.deactivate(user_id="user-id")

End-Users Client

End-users are the people who sign in through one of your OIDC applications (not your tenant's team members).

# List the users in an application's pool
pool = await client.end_users.list(app_id)

# Clear the automatic sign-in lockout (distinct from an administrative block)
await client.end_users.unlock(app_id, user_id)

# Generate a one-time temporary password; the user must change it at next login
temp = await client.end_users.generate_temporary_password(app_id, user_id)
print(f"Hand this to {temp.email} over a secure channel: {temp.temporary_password}")
# The plaintext is returned once and is never stored in clear text.

Applications Client

# Create OIDC application
app = await client.applications.create(
    name="My App",
    redirect_uris=["https://myapp.com/callback"],
    scopes=["openid", "profile", "email"]
)

# List applications
apps = await client.applications.list()

# Update application
await client.applications.update(
    app_id="app-id",
    redirect_uris=["https://myapp.com/callback", "https://myapp.com/callback2"]
)

Audit Client

# Query audit logs
logs = await client.audit.list(
    action="secret_accessed",
    resource_type="Secret",
    start_date="2024-01-01",
    end_date="2024-12-31",
    page=1
)

# Export audit logs
csv_data = await client.audit.export(
    format="csv",
    start_date="2024-01-01",
    end_date="2024-12-31"
)

Billing Client

# Get subscription details
subscription = await client.billing.get_subscription()

# Get usage metrics
usage = await client.billing.get_usage(
    start_date="2024-01-01",
    end_date="2024-01-31"
)

# List invoices
invoices = await client.billing.list_invoices()

Health Client

# Check API health
health = await client.health.check()
print(f"API Status: {health.status}")

# Get API version
version = await client.health.version()
print(f"API Version: {version.version}")

# Get rate limit status
rate_limit = await client.health.rate_limit()
print(f"Remaining: {rate_limit.remaining}/{rate_limit.limit}")

Error Handling

The SDK provides typed exceptions for all error scenarios:

from quantumapi import (
    QuantumAPIClient,
    AuthenticationError,
    PermissionError,
    NotFoundError,
    RateLimitError,
    ValidationError,
    ServerError,
    NetworkError,
)

try:
    secret = await client.secrets.get("invalid-id")
except NotFoundError as e:
    print(f"Secret not found: {e.message}")
except AuthenticationError as e:
    print(f"Authentication failed: {e.message}")
except RateLimitError as e:
    print(f"Rate limit exceeded. Retry after {e.retry_after} seconds")
except ServerError as e:
    print(f"Server error: {e.message}")
except NetworkError as e:
    print(f"Network error: {e.message}")

Pagination

List methods support automatic pagination:

# Manual pagination
secrets = await client.secrets.list(page=1, page_size=100)

# Iterate through all pages
all_secrets = []
page = 1
while True:
    result = await client.secrets.list(page=page, page_size=100)
    all_secrets.extend(result.secrets)
    if not result.has_more:
        break
    page += 1

Webhook Verification

Verify webhook signatures from QuantumAPI:

from quantumapi.webhooks import verify_signature

# Verify webhook payload
is_valid = verify_signature(
    payload=request.body,
    signature=request.headers["X-QuantumAPI-Signature"],
    secret="your_webhook_secret"
)

if is_valid:
    # Process webhook event
    pass

Logging

Enable detailed logging for debugging:

import logging

logging.basicConfig(level=logging.DEBUG)

client = QuantumAPIClient(
    api_key="qapi_xxx",
    enable_logging=True
)

Examples

Check out the examples/ directory for more comprehensive examples:

Basic Examples:

Advanced Secret Management:

Run any example with:

export QUANTUMAPI_API_KEY="qapi_your_key_here"
python examples/01_encryption_basics.py

Framework Integrations

Django

pip install quantumapi[django]
# settings.py
QUANTUMAPI = {
    'API_KEY': 'qapi_xxx',
    'BASE_URL': 'https://api.quantumapi.eu',
}

# Use in views
from quantumapi.integrations.django import get_client

async def my_view(request):
    client = get_client()
    secret = await client.secrets.get('secret-id')
    return JsonResponse({'value': secret.value})

Flask

pip install quantumapi[flask]
from flask import Flask
from quantumapi.integrations.flask import QuantumAPIFlask

app = Flask(__name__)
app.config['QUANTUMAPI_API_KEY'] = 'qapi_xxx'
qapi = QuantumAPIFlask(app)

@app.route('/secret/<secret_id>')
async def get_secret(secret_id):
    secret = await qapi.secrets.get(secret_id)
    return {'value': secret.value}

Testing

Run tests:

pytest

Run tests with coverage:

pytest --cov=quantumapi --cov-report=html

Development

# Clone repository
git clone https://github.com/quantumapi/quantumapi-python
cd quantumapi-python

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black quantumapi tests
isort quantumapi tests

# Type checking
mypy quantumapi

# Linting
flake8 quantumapi tests

Requirements

  • Python 3.9 or higher
  • httpx >= 0.27.0
  • pydantic >= 2.0.0
  • python-dotenv >= 1.0.0
  • cryptography >= 42.0.0

License

MIT License - see LICENSE file for details.

Support

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

Changelog

See CHANGELOG.md for a history of changes to this SDK.

Security

For security concerns, please email it@kovimatic.ie. Do not create public issues for security vulnerabilities.

Metadata

Release files for quantumapi 0.21.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for quantumapi 0.21.0
File Size Uploaded
quantumapi-0.21.0.tar.gz 44.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for quantumapi 0.21.0
File Interpreter ABI Platform
quantumapi-0.21.0-py3-none-any.whl Python 3 none any Details

Total release size: 87.9 kB

Release files / quantumapi-0.21.0.tar.gz

Download URL quantumapi-0.21.0.tar.gz
Size 44.3 kB
Tags Source
SHA-256 checksum
How to use checksums
4a26778212c1ea1645c2a1e2a13c77fc46bd683119dcb93cb16e3bfa29d4599b
BLAKE2b-256 checksum
How to use checksums
3dbb4bea588dd23dfaa2a72ed3a65cc0e9b60d1f1519dba9d652fd6a6ed6189f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / quantumapi-0.21.0-py3-none-any.whl

Download URL quantumapi-0.21.0-py3-none-any.whl
Size 43.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f0f1142bd98bf0bbcb2d90955140fff536ba649698b58b24fb056169a6ca7444
BLAKE2b-256 checksum
How to use checksums
1ea476762c87287686df5e0c53b33bf5f42803aa0670f5642eb7581d7bc1f3e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page