Skip to main content

Python SDK for OutScope API

Project description

OutScope SDK

Python client library for the OutScope API - Complete security monitoring and assessment automation.

Python Version License Version

Features

  • Complete API Coverage - 6 resources, 38 methods, 61% API coverage
  • Asset Inventory - Full lifecycle management of monitored services
  • Automated Scheduling - Recurring checks (hourly, daily, weekly)
  • Multi-Tenant - Company-based organization
  • Report Generation - Customizable security reports
  • Worker Pools - Select execution environment
  • Batch Operations - Automatic rate limit handling
  • Type Hints - Full type annotation support
  • Error Handling - Detailed error information with retry capabilities

Installation

pip install outscope-sdk

Or install from source:

cd sdk
pip install -e .

Quick Start

from outscope_sdk import Client

# Create a client
client = Client(api_key="your_api_key_here")

# Create an asset in inventory
asset = client.assets.create(
    target="api.example.com",
    name="Production API",
    tags=["production", "critical"]
)

# Set up automated daily checks
client.assets.set_schedule(asset['asset_id'], schedule="daily")

# Or trigger a manual check
check = client.checks.create(
    fqdn="example.com",
    paths=["/", "/api"],
    ports=[443]
)

# Check usage
usage = client.usage.get()
print(f"Used: {usage['usage']['checks_used']}/{usage['usage']['checks_limit']}")

client.close()

Table of Contents


Authentication

Generate an API key from your OutScope dashboard.

from outscope_sdk import Client
import os

# Option 1: Direct in code (not recommended for production)
client = Client(api_key="osk_...")

# Option 2: From environment variable (recommended)
client = Client(api_key=os.getenv("OUTSCOPE_API_KEY"))

# Option 3: Context manager (automatic cleanup)
with Client(api_key=os.getenv("OUTSCOPE_API_KEY")) as client:
    # Your code here
    pass

Resources

Assets

Manage your service inventory with full lifecycle tracking.

Create Asset

# Create asset with full metadata
asset = client.assets.create(
    target="api.example.com",
    company_id="company_123",
    name="Production API Server",
    description="Main REST API backend",
    tags=["production", "api", "critical"],
    metadata={
        "environment": "production",
        "owner": "platform-team",
        "sla": "99.9%"
    }
)

List Assets

# List with filters
assets = client.assets.list(
    company_id="company_123",
    tags="critical",
    search="api",
    analyzability="analyzable",
    active_only=True,
    page=1,
    per_page=50
)

for asset in assets['assets']:
    print(f"{asset['name']}: {asset['target']}")

Schedule Automated Checks

# Set up recurring checks
client.assets.set_schedule(
    asset_id=asset['asset_id'],
    schedule="daily"  # Options: none, hourly, daily, weekly
)

Trigger Manual Check

# Manually trigger a check for an asset
check = client.assets.trigger_check(asset['asset_id'])
print(f"Check started: {check['job_id']}")

Get Asset Statistics

# Inventory overview
stats = client.assets.get_stats()
print(f"Total assets: {stats['total_assets']}")
print(f"Manual: {stats['manual_assets']}")
print(f"Auto-discovered: {stats['auto_discovered']}")

Get Check History

# View all checks for an asset
history = client.assets.get_checks(
    asset_id=asset['asset_id'],
    page=1,
    limit=20
)

for check in history['checks']:
    print(f"{check['created_at']}: {check['status']}")

Update Asset

# Update asset properties
client.assets.update(
    asset_id=asset['asset_id'],
    name="Updated API Name",
    tags=["production", "api", "critical", "updated"],
    metadata={"version": "2.0"}
)

Deactivate Asset

# Soft delete (keeps history)
client.assets.delete(asset['asset_id'])

Checks

Execute security checks and monitor results.

Create Check

# Basic check
check = client.checks.create(
    fqdn="example.com",
    paths=["/"],
    ports=[443]
)

# Advanced check with all options
check = client.checks.create(
    fqdn="api.example.com",
    paths=["/", "/api/v1", "/health"],
    ports=[80, 443, 8080],
    max_redirects=1,
    collect_content_sample=True,
    content_sample_retention_days=7,
    pool_id="premium",
    company_id="company_123"
)

Batch Create

# Create multiple checks with automatic rate limiting
result = client.checks.create_batch(
    domains=["site1.com", "site2.com", "site3.com"],
    paths=["/"],
    ports=[443],
    pool_id="general",
    company_id="company_123",
    check_usage_first=True,
    wait_on_limits=True,
    max_retries=5,
    progress_callback=lambda cur, tot, stats: print(f"{cur}/{tot}")
)

print(f"Created: {result['stats']['created']}")
print(f"Failed: {result['stats']['failed']}")

Get Check

check = client.checks.get("check_id_here")
print(f"Status: {check['status']}")

if check['status'] == 'done':
    print(f"Analyzable: {check['result']['analysis']['analyzable']}")

List Checks

# With advanced filters
checks = client.checks.list(
    company_id="company_123",
    analyzability="not_analyzable",
    category="Security Blocks",
    fqdn="example.com",
    page=1,
    limit=50
)

# Auto-pagination
for check in client.checks.list_all(analyzability="analyzable"):
    print(f"{check['fqdn_normalized']}: analyzable")

Latest Check

# Get latest completed check for a domain
latest = client.checks.latest(fqdn="example.com")

Cancel Check

# Cancel running or queued check
client.checks.cancel(check_id="check_123")

Request Review

# Submit false positive review
client.checks.send_review(
    check_id="check_123",
    reason="false_positive",
    comments="This endpoint should be marked as analyzable"
)

# Check review status
status = client.checks.get_review_status(check_id="check_123")
if status['has_pending_review']:
    print("Review pending")

Companies

Organize assets and checks by company (multi-tenant).

Create Company

company = client.companies.create(name="ACME Corp")

List Companies

companies = client.companies.list(active_only=True)
for company in companies:
    print(f"{company.name} (ID: {company.id})")

Get Company

company = client.companies.get(company_id="company_123")

Update Company

client.companies.update(
    company_id="company_123",
    name="ACME Corporation",
    active=True
)

Delete Company

client.companies.delete(company_id="company_123")

Reports

Generate customizable security assessment reports.

Create Template

template = client.reports.create_template(
    name="Security Assessment Report",
    description="Comprehensive security report",
    branding={
        "company_name": "ACME Security",
        "primary_color": "#0066cc",
        "secondary_color": "#00cc66"
    },
    sections=[
        {"type": "executive_summary", "enabled": True},
        {"type": "security_findings", "enabled": True},
        {"type": "recommendations", "enabled": True}
    ],
    output_format="pdf",
    is_default=True
)

Upload Logo

logo = client.reports.upload_logo("path/to/logo.png")
# Returns: {'logo_url': '/v1/reports/logos/...'}

Generate Report

report = client.reports.generate(
    template_id=template['template']['id'],
    title="Monthly Security Assessment",
    description="Q1 2026 Report",
    filters={
        "analyzability": "not_analyzable",
        "date_range": "last_30_days"
    },
    company_id="company_123"
)

# Check status
status = client.reports.get(report['report_id'])
if status['report']['status'] == 'completed':
    # Download
    client.reports.download(
        report['report_id'],
        "security_report.pdf"
    )

List Reports

reports = client.reports.list(
    company_id="company_123",
    status="completed",
    page=1,
    per_page=20
)

Pools

Select worker pools for check execution.

# List available pools
pools = client.pools.list()

for pool in pools['pools']:
    print(f"{pool.display_name} ({pool.type}): {'Available' if pool.available else 'Unavailable'}")

# Use pool in check
check = client.checks.create(
    fqdn="example.com",
    pool_id="premium-pool"
)

Usage

Monitor limits and usage.

usage = client.usage.get()

# Tenant info
print(f"Tenant: {usage['tenant']['name']}")
print(f"Plan: {usage['tenant']['plan']}")

# Current usage
print(f"Checks: {usage['usage']['checks_used']}/{usage['usage']['checks_limit']}")
print(f"In progress: {usage['usage']['inflight']}/{usage['limits']['max_inflight']}")

# Limits
print(f"Rate: {usage['limits']['rate_per_minute']}/min")
print(f"Retention: {usage['limits']['retention_days']} days")

Advanced Usage

Complete Workflow Example

from outscope_sdk import Client

with Client(api_key=os.getenv("OUTSCOPE_API_KEY")) as client:
    # 1. Create company
    company = client.companies.create(name="Production Services")
    
    # 2. Create asset
    asset = client.assets.create(
        target="api.example.com",
        company_id=company.id,
        name="Production API",
        tags=["production", "critical"]
    )
    
    # 3. Set up daily checks
    client.assets.set_schedule(asset['asset_id'], schedule="daily")
    
    # 4. Trigger immediate check
    check = client.assets.trigger_check(asset['asset_id'])
    
    # 5. Generate report
    template = client.reports.create_template(
        name="Production Report",
        output_format="pdf"
    )
    
    report = client.reports.generate(
        template_id=template['template']['id'],
        title="Production Security Report",
        company_id=company.id
    )
    
    # 6. Monitor usage
    usage = client.usage.get()
    print(f"Remaining: {usage['usage']['checks_limit'] - usage['usage']['checks_used']}")

Error Handling

from outscope_sdk.exceptions import (
    RateLimitError,
    AuthenticationError,
    NotFoundError,
    ValidationError
)

try:
    check = client.checks.create(fqdn="example.com", ports=[443])
    
except RateLimitError as e:
    if e.code == "rate_limit_exceeded":
        print(f"Rate limited: {e.limit}/min, retry in {e.retry_after}s")
        time.sleep(e.retry_after)
    elif e.code == "inflight_limit":
        print(f"Too many checks in progress: {e.current}/{e.limit}")
    elif e.code == "checks_limit":
        print(f"Monthly quota exceeded: {e.used}/{e.limit}")
        
except AuthenticationError as e:
    print(f"Authentication failed: {e.message}")
    
except NotFoundError as e:
    print(f"Resource not found: {e.message}")
    
except ValidationError as e:
    print(f"Validation error: {e.message}")

API Reference

See CHANGELOG.md for complete version history.

Client

Client(
    api_key: str,
    base_url: Optional[str] = None,
    timeout: float = 30.0
)

Resources:

  • client.assets - AssetsResource (10 methods)
  • client.checks - ChecksResource (10 methods)
  • client.companies - CompaniesResource (5 methods)
  • client.reports - ReportsResource (11 methods)
  • client.pools - PoolsResource (1 method)
  • client.usage - UsageResource (1 method)

Total: 38 methods across 6 resources


Examples

See the examples/ directory for complete working examples:

  • examples/advanced_usage.py - All features demo
  • examples/assets_usage.py - Asset inventory management
  • examples/reports_usage.py - Report generation

Changelog

See CHANGELOG.md

Current Version: v0.3.0

  • ✅ Assets resource (complete inventory management)
  • ✅ Automated scheduling (hourly, daily, weekly)
  • ✅ Reports resource (customizable reports)
  • ✅ Companies resource (multi-tenant)
  • ✅ Worker pools support
  • ✅ Advanced filtering
  • ✅ 61% API coverage

Support


License

MIT License - see LICENSE file for details.


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

outscope_sdk-0.3.1.tar.gz (29.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

outscope_sdk-0.3.1-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file outscope_sdk-0.3.1.tar.gz.

File metadata

  • Download URL: outscope_sdk-0.3.1.tar.gz
  • Upload date:
  • Size: 29.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for outscope_sdk-0.3.1.tar.gz
Algorithm Hash digest
SHA256 026118869b162b375103030cba12f776c09aa6b429ff3720c74a1c56b54a727b
MD5 640bc2049a4837fb218cd289330ca2a5
BLAKE2b-256 630a2c0c8cf7cf7c04f8c9bc81fde803d4c86067da5a7e4597bd901ff42ef254

See more details on using hashes here.

File details

Details for the file outscope_sdk-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: outscope_sdk-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for outscope_sdk-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 94520ee81d7d8263765fc2019e0c4d9d55074389e1e521eeec169fa714165386
MD5 3af2f280af355745ecae86dd884d9bd5
BLAKE2b-256 63023696b839bc51a342b89e1b4e3edc515e554e0199786e2947856b24d06a0f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page