Python SDK
Official Python SDK for OutScope API - Complete security monitoring, asset inventory, and report generation.
Version: 0.3.0 | Coverage: 61% API | Resources: 6 | Methods: 38
Features
- ✅ Asset Inventory - Complete lifecycle management of monitored services
- ✅ Automated Scheduling - Recurring checks (hourly, daily, weekly)
- ✅ Security Checks - Manual and automated endpoint monitoring
- ✅ Multi-Tenant - Company-based organization
- ✅ Report Generation - Customizable PDF/HTML reports
- ✅ Worker Pools - Select execution environment
- ✅ Batch Operations - Automatic rate limit handling
Installation
pip install outscope-sdk
Or from source:
git clone https://github.com/outscope-io/outscope-sdk
cd outscope-sdk
pip install -e .
Quick Start
from outscope_sdk import Client
# Initialize client
client = Client(api_key="your_api_key_here")
# Create 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 run manual check
check = client.checks.create(
fqdn="example.com",
paths=["/", "/api"],
ports=[443]
)
# Monitor usage
usage = client.usage.get()
print(f"Checks: {usage['usage']['checks_used']}/{usage['usage']['checks_limit']}")
client.close()
Authentication
Generate an API key from your OutScope dashboard under Settings > API Keys.
from outscope_sdk import Client
import os
# Recommended: use environment variable
client = Client(api_key=os.getenv("OUTSCOPE_API_KEY"))
# With context manager (auto-cleanup)
with Client(api_key=os.getenv("OUTSCOPE_API_KEY")) as client:
# Your code here
pass
Asset Inventory Management
Create Asset
# Basic asset
asset = client.assets.create(
target="api.example.com",
name="Production API"
)
# Full configuration
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
# All assets
assets = client.assets.list(active_only=True)
# With filters
critical_assets = client.assets.list(
tags="critical",
search="api",
analyzability="analyzable",
company_id="company_123",
page=1,
per_page=50
)
for asset in assets['assets']:
print(f"{asset['name']}: {asset['target']}")
Automated Scheduling
# Set recurring checks
client.assets.set_schedule(
asset_id=asset['asset_id'],
schedule="daily" # Options: none, hourly, daily, weekly
)
# Trigger manual check
check = client.assets.trigger_check(asset['asset_id'])
print(f"Check started: {check['job_id']}")
Asset Analytics
# Inventory statistics
stats = client.assets.get_stats()
print(f"Total assets: {stats['total_assets']}")
print(f"Recent checks (24h): {stats['recent_checks']}")
# Check history for asset
history = client.assets.get_checks(
asset_id=asset['asset_id'],
page=1,
limit=20
)
Update & Delete
# Update asset
client.assets.update(
asset_id=asset['asset_id'],
name="Updated API Name",
tags=["production", "api", "updated"]
)
# Soft delete (keeps history)
client.assets.delete(asset['asset_id'])
Security Checks
Create Check
# Basic check
check = client.checks.create(
fqdn="example.com",
paths=["/"],
ports=[443]
)
# Advanced 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 Operations
# Create multiple checks
result = client.checks.create_batch(
domains=["site1.com", "site2.com", "site3.com"],
paths=["/"],
ports=[443],
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']}")
print(f"Duration: {result['duration']:.1f}s")
Check Status & Results
# Get check
check = client.checks.get("check_id_here")
if check['status'] == 'done':
print(f"Analyzable: {check['result']['analysis']['analyzable']}")
print(f"Service type: {check['result']['analysis']['kind']}")
# Latest check for domain
latest = client.checks.latest(fqdn="example.com")
# Cancel running check
client.checks.cancel(check_id="check_123")
Advanced Filtering
# Filter by multiple criteria
checks = client.checks.list(
company_id="company_123",
analyzability="not_analyzable",
category="Security Blocks",
reasons="blocked_by_security,no_http_response",
page=1,
limit=50
)
# Auto-pagination
for check in client.checks.list_all(analyzability="analyzable"):
print(f"{check['fqdn_normalized']}: ready for DAST")
Review Requests
# 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 with support team")
Multi-Tenant Organization
Companies
# Create company
company = client.companies.create(name="ACME Corp")
# List companies
companies = client.companies.list(active_only=True)
# Get company
company = client.companies.get(company_id="company_123")
# Update
client.companies.update(
company_id="company_123",
name="ACME Corporation",
active=True
)
# Delete
client.companies.delete(company_id="company_123")
Organize by Company
# Create asset for company
asset = client.assets.create(
target="acme-api.com",
company_id=company.id,
name="ACME API"
)
# Create check for company
check = client.checks.create(
fqdn="acme.com",
company_id=company.id
)
# List company assets
assets = client.assets.list(company_id=company.id)
# List company checks
checks = client.checks.list(company_id=company.id)
Report Generation
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"
)
Upload Logo
logo = client.reports.upload_logo("path/to/logo.png")
# Returns: {'logo_url': '/v1/reports/logos/...'}
# Update template with logo
client.reports.update_template(
template_id=template['template']['id'],
branding={
"company_name": "ACME",
"logo_url": logo['logo_url'],
"primary_color": "#0066cc"
}
)
Generate Report
# Start report generation
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",
"category": "Security Blocks"
},
company_id="company_123"
)
# Poll for completion
import time
while True:
status = client.reports.get(report['report_id'])
if status['report']['status'] == 'completed':
break
time.sleep(5)
# Download report
client.reports.download(
report['report_id'],
"security_assessment.pdf"
)
Worker Pools
# List available pools
pools = client.pools.list()
for pool in pools['pools']:
print(f"{pool.display_name} ({pool.type})")
print(f" Available: {pool.available}")
# Use specific pool for check
check = client.checks.create(
fqdn="critical-service.com",
pool_id="premium-pool" # Premium/faster execution
)
# Use pool in batch
result = client.checks.create_batch(
domains=["site1.com", "site2.com"],
pool_id="premium-pool"
)
Usage Monitoring
usage = client.usage.get()
# Tenant information
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")
# Check quota
remaining = usage['usage']['checks_limit'] - usage['usage']['checks_used']
if remaining < 100:
print(f"⚠️ Only {remaining} checks remaining this month")
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")
print(f"Retry in {e.retry_after} seconds")
time.sleep(e.retry_after)
elif e.code == "inflight_limit":
print(f"Too many concurrent checks: {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"Invalid request: {e.message}")
Complete Workflow Example
from outscope_sdk import Client
import os
import time
# Initialize
with Client(api_key=os.getenv("OUTSCOPE_API_KEY")) as client:
# 1. Create company
company = client.companies.create(name="Production Services")
# 2. Add assets to inventory
assets = []
for target in ["api.example.com", "app.example.com", "admin.example.com"]:
asset = client.assets.create(
target=target,
company_id=company.id,
tags=["production"]
)
assets.append(asset)
# 3. Set up automated monitoring
for asset in assets:
client.assets.set_schedule(
asset['asset_id'],
schedule="daily"
)
# 4. Trigger immediate checks
checks = []
for asset in assets:
check = client.assets.trigger_check(asset['asset_id'])
checks.append(check)
# 5. Wait for completion
print("Waiting for checks to complete...")
time.sleep(30)
# 6. Generate report
template = client.reports.create_template(
name="Production Report",
company_id=company.id
)
report = client.reports.generate(
template_id=template['template']['id'],
title="Production Security Assessment",
company_id=company.id
)
# 7. Check usage
usage = client.usage.get()
print(f"Checks used: {usage['usage']['checks_used']}/{usage['usage']['checks_limit']}")
CI/CD Integration
#!/usr/bin/env python3
import sys
import os
from outscope_sdk import Client
client = Client(api_key=os.getenv('OUTSCOPE_API_KEY'))
# Production endpoints to monitor
endpoints = [
"api.prod.example.com",
"app.prod.example.com",
"admin.prod.example.com"
]
# Create checks
result = client.checks.create_batch(
domains=endpoints,
wait_on_limits=True,
company_id=os.getenv('COMPANY_ID')
)
if result['stats']['failed'] > 0:
print(f"❌ Failed to create {result['stats']['failed']} checks")
sys.exit(1)
print(f"✅ Created {result['stats']['created']} checks successfully")
sys.exit(0)
Advanced Features
Custom Timeout
client = Client(
api_key="your_key",
timeout=120.0 # 2 minutes
)
Retry Configuration
# Automatic retry with exponential backoff
def create_with_retry(fqdn, max_attempts=3):
for attempt in range(max_attempts):
try:
return client.checks.create(fqdn=fqdn)
except RateLimitError as e:
if attempt == max_attempts - 1:
raise
time.sleep(e.retry_after or 60)
SDK Resources Overview
| Resource | Methods | Description |
|---|---|---|
| Assets | 10 | Complete inventory lifecycle |
| Checks | 10 | Security monitoring |
| Companies | 5 | Multi-tenant organization |
| Reports | 11 | Customizable reports |
| Pools | 1 | Worker pool selection |
| Usage | 1 | Limits and usage tracking |
| Total | 38 | 61% API Coverage |
Version History
v0.3.0 (Current)
- ✅ Assets resource - Complete inventory management
- ✅ Automated scheduling (hourly, daily, weekly)
- ✅ Asset lifecycle tracking
- ✅ Check history per asset
v0.2.1
- ✅ Reports resource - PDF/HTML generation
- ✅ Template management
- ✅ Logo upload
v0.2.0
- ✅ Companies resource - Multi-tenant support
- ✅ Worker pools - Pool selection
- ✅ Advanced check filtering
- ✅ Check lifecycle operations
Support & Resources
- GitHub: github.com/outscope-io/outscope-sdk
- Examples: See
/examplesdirectory in repository - Changelog: CHANGELOG.md
- Email: support@outscope.es