Build on Scrubbe
Official clients for the Scrubbe Operational Intelligence Platform — across five runtimes and the command line. Create incidents, stream live events, run governed playbooks, and query the knowledge base against api.scrubbe.com.

The four stages of Scrubbe adoption
Connect
Authenticate, read incidents, and open your first one. No writes to production systems.
Instrument
Ingest signals, enrich timelines, and stream live events into your own tooling.
Automate
Run governed playbooks behind named-operator approval. Gates surface as typed errors.
Operate
Close the loop at scale: audit, postmortems, and knowledge queries across the corpus.

Choose the SDK that matches
your stack
Installation
Install from PyPI. No build step required.
| 1 | pip install scrubbe-sdk |
Quick start
An async client built on httpx. Paginate lazily and subscribe to live event streams.
| 1 | import asyncio |
| 2 | from scrubbe import Scrubbe |
| 3 | |
| 4 | async def main(): |
| 5 | async with Scrubbe(api_key="sk-...") as client: |
| 6 | # Create an incident |
| 7 | incident = await client.incident.create( |
| 8 | title="Payment gateway degraded", |
| 9 | priority="P1", |
| 10 | service="payment-api", |
| 11 | ) |
| 12 | print(incident["incident_id"]) # SI-000042 |
| 13 | |
| 14 | # List open incidents (lazy pagination) |
| 15 | async for inc in client.incident.list(state="INVESTIGATING"): |
| 16 | print(inc["incident_id"], inc["title"]) |
| 17 | |
| 18 | # Subscribe to live events |
| 19 | async for event in client.incident.subscribe(incident["incident_id"]): |
| 20 | print(event["type"], event["data"]) |
| 21 | |
| 22 | asyncio.run(main()) |
Authentication
Resolution paths: explicit key, OAuth2 client credentials, or environment configs.
| 1 | # 1. Explicit API key |
| 2 | client = Scrubbe(api_key="sk-...") |
| 3 | |
| 4 | # 2. OAuth2 client credentials (auto-refresh) |
| 5 | client = Scrubbe(client_id="...", client_secret="...") |
| 6 | |
| 7 | # 3. Environment variables (recommended for CI) |
| 8 | client = Scrubbe() |
| 9 | |
| 10 | # 4. Named profile in ~/.scrubbe/credentials |
| 11 | client = Scrubbe(profile="production") |
Configuration
Tune connection timeouts and jitter retry distributions.
| 1 | from scrubbe import Scrubbe |
| 2 | from scrubbe.utils.retry import RetryOptions |
| 3 | |
| 4 | client = Scrubbe( |
| 5 | api_key="sk-...", |
| 6 | base_url="https://api.scrubbe.com", # default |
| 7 | connect_timeout_ms=5_000, |
| 8 | read_timeout_ms=30_000, |
| 9 | retry=RetryOptions( |
| 10 | max_attempts=3, |
| 11 | base_delay_ms=500, |
| 12 | max_delay_ms=30_000, |
| 13 | respect_retry_after=True, # honour 429 headers |
| 14 | ), |
| 15 | ) |
Error handling
Governance gates raise GovernanceApprovalRequiredError — never a silent null.
| 1 | from scrubbe import ( |
| 2 | GovernanceApprovalRequiredError, |
| 3 | RateLimitedError, |
| 4 | UnauthenticatedError, |
| 5 | ScrubbeAPIError, |
| 6 | ) |
| 7 | |
| 8 | try: |
| 9 | await client.playbook.run("PB-0001", incident_id="SI-000042") |
| 10 | except GovernanceApprovalRequiredError as e: |
| 11 | print(f"Approval required: {e.approval_id}") |
| 12 | print(f"Approve at: {e.approval_url}") |
| 13 | except RateLimitedError as e: |
| 14 | print(f"Rate limited. Retry after {e.retry_after}s") |
Incident operations
The full core lifecycle: create, annotate timeline logs, and resolve.
| 1 | async with Scrubbe(api_key="sk-...") as client: |
| 2 | inc = await client.incident.create( |
| 3 | title="DB replica lag spike", |
| 4 | priority="P2", |
| 5 | service="orders-db", |
| 6 | ) |
| 7 | await client.timeline.add( |
| 8 | incident_id=inc["incident_id"], |
| 9 | message="Replica lag reached 42s at 14:03 UTC", |
| 10 | source="monitoring", |
| 11 | ) |
| 12 | await client.incident.resolve( |
| 13 | incident_id=inc["incident_id"], |
| 14 | resolution="Replica re-synced after network blip.", |
| 15 | ) |
MCP queries
Ask the knowledge base in natural language; responses cite source incidents.
| 1 | async with Scrubbe(api_key="sk-...") as client: |
| 2 | answer = await client.mcp.query( |
| 3 | q="What caused the payment outages in Q2?", |
| 4 | ) |
| 5 | print(answer["answer"]) |
Development
Set up local developer orchestration packages safely.
| 1 | pip install -e ".[dev]" |
| 2 | ruff check src/ tests/ # lint |
| 3 | mypy src/scrubbe # type-check |
| 4 | pytest --cov=scrubbe tests/ # tests |
Scrubbe pushes real-time event payloads to any HTTPS endpoint you register . Signatures are verified securely with HMAC-SHA256 filters using your generated webhook secret .
| 1 | import hashlib, hmac |
| 2 | |
| 3 | def verify_signature(payload: bytes, sig: str, secret: str) -> bool: |
| 4 | expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() |
| 5 | return hmac.compare_digest(f"sha256={expected}", sig) |
| Event Name | Description Context | Payload Schema |
|---|---|---|
| incident.created | A new incident was opened. | IncidentCreatedPayload |
| incident.updated | Priority, state, or service assignment changed. | IncidentUpdatedPayload |
| incident.resolved | Incident marked resolved with an optional summary. | IncidentResolvedPayload |
| playbook.executed | A playbook run completed (executed, parked, blocked). | PlaybookExecutedPayload |
| playbook.approval_required | Execution gated pending human approval. | ApprovalRequiredPayload |
| approval.granted | A pending approval was approved by an operator. | ApprovalGrantedPayload |
| handover.created | A new shift handover was generated. | HandoverCreatedPayload |
| postmortem.published | A post-mortem was finalised and published. | PostmortemPublishedPayload |
| agent.investigation_completed | An AI investigation finished. | InvestigationPayload |
SDK Comparison.
Capability matrix across clients
Cookie preferences
We use essential cookies to keep Scrubbe secure and functional. You can choose whether to allow analytics, preferences, and marketing cookies, and update your choices at any time.
Essential cookies
Required for security, session continuity, consent state, and core site functionality. These are always on.
Analytics cookies
Help us understand usage patterns so we can improve product pages, onboarding paths, and documentation quality.
Preference cookies
Remember selected settings such as region, UI preferences, and previously chosen site options.
Marketing cookies
Enable campaign measurement and more relevant follow-up communications across trusted channels.
Your choices are stored locally in this browser and can be updated at any time from the cookie settings button.
