Python SDK¶
Complete guide for using the SPOT Contracts Python SDK.
Installation¶
Requirements¶
- Python 3.11+
- pydantic >= 2.0.0
- httpx >= 0.25.0
- typing-extensions >= 4.8.0
Quick Start¶
from spot_sdk.api_gateway import Email, EmailHeader
from spot_sdk.api_gateway import AnalysisResult, AnalysisIndicator, AnalysisMetadata
# Create email object
email = Email(
id="test-123",
headers=EmailHeader(
subject="Test email",
sender="test@example.com",
recipients=["user@company.com"]
),
body_text="Email content here"
)
# Create analysis result
result = AnalysisResult(
is_phishing=True,
threat_level="high",
confidence=0.85,
explanation="Found suspicious indicators",
indicators=[
AnalysisIndicator(
type="suspicious_links",
description="Suspicious domain detected",
severity="high",
confidence=0.9
)
],
metadata=AnalysisMetadata(
analyzer_id="my-analyzer",
analyzer_version="1.0.0",
analysis_duration_ms=250
)
)
# Serialize to JSON (Pydantic v2)
json_data = result.model_dump_json()
print(json_data)
Available Models¶
Email Models¶
Module: spot_sdk.email
from spot_sdk.api_gateway import Email
email = Email(
id="unique-id",
headers=EmailHeader(...),
body_text="Plain text body",
body_html="<html>HTML body</html>",
attachments=[Attachment(...)]
)
EmailHeader
from spot_sdk.api_gateway import EmailHeader
headers = EmailHeader(
subject="Email subject",
sender="sender@example.com",
recipients=["recipient@example.com"],
cc=["cc@example.com"],
bcc=["bcc@example.com"],
date="2024-01-15T10:30:00Z",
message_id="<unique-message-id>",
in_reply_to="<parent-message-id>",
references=["<ref1>", "<ref2>"]
)
Attachment
from spot_sdk.api_gateway import Attachment
attachment = Attachment(
filename="document.pdf",
content_type="application/pdf",
size=1024,
content="base64-encoded-content",
content_id="unique-content-id"
)
Analysis Models¶
Module: spot_sdk.results
AnalysisResult
from spot_sdk.api_gateway import AnalysisResult, AnalysisMetadata
result = AnalysisResult(
is_phishing=True, # bool: Is this email phishing?
threat_level="high", # str: safe|low|medium|high|critical
confidence=0.85, # float: 0.0-1.0
explanation="Detailed explanation",
indicators=[...], # List[AnalysisIndicator]
metadata=AnalysisMetadata(...),
raw_output={"custom": "data"} # Optional: any additional data
)
AnalysisIndicator
from spot_sdk.api_gateway import AnalysisIndicator, IndicatorType
indicator = AnalysisIndicator(
type=IndicatorType.SUSPICIOUS_LINKS, # or use string
description="Found shortened URL: bit.ly/xyz",
severity="high", # low|medium|high
confidence=0.9, # 0.0-1.0
evidence="bit.ly/xyz123", # Optional: what triggered this
location="body" # Optional: where in email
)
IndicatorType Enum
from spot_sdk.api_gateway import IndicatorType
# Available indicator types:
IndicatorType.SUSPICIOUS_LINKS # Malicious/shortened URLs
IndicatorType.DOMAIN_SPOOFING # Sender domain mismatch
IndicatorType.URGENT_LANGUAGE # Pressure tactics
IndicatorType.SPELLING_GRAMMAR_ERRORS # Poor grammar/typos
IndicatorType.SOCIAL_ENGINEERING # Social engineering tactics
IndicatorType.SUSPICIOUS_ATTACHMENTS # Dangerous file types
IndicatorType.CONTEXT_MISMATCH # Content doesn't match sender
IndicatorType.HEADER_ANOMALIES # Email header issues
AnalysisMetadata
from spot_sdk.api_gateway import AnalysisMetadata
metadata = AnalysisMetadata(
analyzer_id="my-analyzer",
analyzer_version="1.0.0",
analysis_duration_ms=245,
model_version="optional-model-version",
timestamp="2024-01-15T10:30:00Z"
)
Workflow Models¶
Module: spot_sdk.workflow
Workflow
from spot_sdk.api_gateway import Workflow, WorkflowStage
workflow = Workflow(
id="workflow-id",
name="Default Workflow",
description="Standard phishing detection workflow",
stages=[WorkflowStage(...)],
enabled=True
)
Orchestrator Models¶
Module: spot_sdk.orchestrator
OrchestrationResult
from spot_sdk.api_gateway import OrchestrationResult, AnalyzerResult
result = OrchestrationResult(
job_id="unique-job-id",
email_id="email-id",
workflow_id="workflow-id",
overall_verdict="phishing",
overall_confidence=0.85,
analyzer_results=[AnalyzerResult(...)],
timestamp="2024-01-15T10:30:00Z"
)
API Client Example¶
import httpx
from spot_sdk.api_gateway import Email, EmailHeader
from spot_sdk.api_gateway import AnalysisResult
class SpotApiClient:
def __init__(
self,
base_url: str = "http://localhost:8001",
token: str = None
):
headers = {"Content-Type": "application/json"}
if token:
headers["Authorization"] = f"Bearer {token}"
self.client = httpx.AsyncClient(
base_url=base_url,
headers=headers,
timeout=30.0
)
async def analyze_email(self, email: Email) -> AnalysisResult:
"""Analyze an email for spear-phishing indicators."""
response = await self.client.post(
"/api/v1/analyze",
json=email.model_dump()
)
response.raise_for_status()
return AnalysisResult(**response.json())
async def get_status(self, job_id: str) -> dict:
"""Check analysis job status."""
response = await self.client.get(f"/api/v1/analyze/{job_id}")
response.raise_for_status()
return response.json()
async def close(self):
"""Close the HTTP client."""
await self.client.aclose()
# Usage example
async def main():
async with SpotApiClient(token="your-token") as client:
# Create email
email = Email(
id="test-123",
headers=EmailHeader(
subject="Urgent: Verify your account",
sender="noreply@suspicious-domain.com",
recipients=["user@company.com"]
),
body_text="Click here to verify: http://bit.ly/xyz123"
)
# Analyze email
result = await client.analyze_email(email)
print(f"Phishing: {result.is_phishing}")
print(f"Threat Level: {result.threat_level}")
print(f"Confidence: {result.confidence}")
print(f"Indicators: {len(result.indicators)}")
for indicator in result.indicators:
print(f" - {indicator.type}: {indicator.description}")
# Run
import asyncio
asyncio.run(main())
Validation and Serialization¶
Pydantic v2 provides powerful validation and serialization:
from spot_sdk.api_gateway import AnalysisResult
# Create with validation
result = AnalysisResult(
is_phishing=True,
threat_level="high",
confidence=0.85,
explanation="Test",
indicators=[],
metadata=AnalysisMetadata(...)
)
# Serialize to dict
data = result.model_dump()
# Serialize to JSON
json_str = result.model_dump_json(indent=2)
# Parse from dict
result2 = AnalysisResult(**data)
# Parse from JSON
result3 = AnalysisResult.model_validate_json(json_str)
# Exclude fields
data = result.model_dump(exclude={"raw_output"})
# Include only specific fields
data = result.model_dump(include={"is_phishing", "threat_level"})
Error Handling¶
from pydantic import ValidationError
from spot_sdk.api_gateway import AnalysisResult
try:
result = AnalysisResult(
is_phishing="invalid", # Should be bool
threat_level="unknown", # Invalid threat level
confidence=1.5, # Out of range
explanation="test"
)
except ValidationError as e:
print("Validation errors:")
for error in e.errors():
print(f" Field: {error['loc']}")
print(f" Error: {error['msg']}")
print(f" Type: {error['type']}")
Testing with SDK¶
import pytest
from spot_sdk.api_gateway import Email, EmailHeader
from spot_sdk.api_gateway import AnalysisResult, AnalysisIndicator
def test_email_creation():
"""Test creating an email object."""
email = Email(
id="test-1",
headers=EmailHeader(
subject="Test",
sender="test@example.com",
recipients=["user@example.com"]
),
body_text="Test content"
)
assert email.id == "test-1"
assert email.headers.subject == "Test"
def test_analysis_result_validation():
"""Test analysis result validation."""
with pytest.raises(ValueError):
AnalysisResult(
is_phishing=True,
threat_level="invalid", # Should fail
confidence=0.5,
explanation="test"
)
@pytest.mark.asyncio
async def test_api_client(mock_api_response):
"""Test API client integration."""
client = SpotApiClient()
email = Email(...)
result = await client.analyze_email(email)
assert isinstance(result, AnalysisResult)
await client.close()
Configuration¶
Using with Poetry¶
[tool.poetry.dependencies]
python = "^3.11"
spot-sdk = {version = "^2.0.0", source = "gitlab"}
[[tool.poetry.source]]
name = "gitlab"
url = "https://pypi.org/simple/"
priority = "supplemental"
Using with pip¶
Troubleshooting¶
Cannot find package¶
Ensure pip is configured to use the GitLab registry:
Import errors¶
Check that you're using the correct module paths:
# Correct
from spot_sdk.api_gateway import Email
from spot_sdk.api_gateway import AnalysisResult
# Incorrect
from spot_sdk.api_gateway Email # Module not found
Validation errors¶
Check the error details to see which field failed validation:
Support¶
- Issues: GitLab Issues
- Documentation: Main Documentation
- SPOT Platform: Platform Docs