Installation
bash
pip install opshiftRequires Python 3.9 or later. No third-party runtime dependencies.
Initialise the client
python
import os
from opshift import OpShift
opshift = OpShift(secret=os.environ["OPSHIFT_SECRET"])Constructor options
| Field | Type | Description |
|---|---|---|
secretrequired | str | Team webhook secret (64-char hex). Find it in Settings → Webhook Secret. |
base_url | str | Override the API root. Defaults to https://www.opshift.io. |
timeout | float | Per-request timeout in seconds. Defaults to 30. |
transport | Callable | Inject a custom HTTP transport for testing. Signature: (url, body_bytes, headers, timeout) -> (status_code, body_bytes). |
opshift.ping(ping_token, *, status, reason, group_key, metadata)
Send a heartbeat ping to a monitor.
python
opshift.ping("payments-worker", status="up", metadata={"batch": 1247})
opshift.ping(
"payments-worker",
status="down",
reason="stripe-timeout",
)Keyword arguments
| Field | Type | Description |
|---|---|---|
status | "up" | "down" | Defaults to "up" server-side. |
reason | str | Short reason string, max 200 chars. |
group_key | str | Alert grouping key, max 200 chars. |
metadata | dict | Arbitrary metadata stored on the ping row. |
Return value
python
{
"message": str,
"monitor": {"name": str, "status": str, "monitoringActive": bool},
"pingStatus": "up" | "down",
}opshift.alert(webhook_url, *, title, ...)
Trigger a webhook alert.
python
res = opshift.alert(
"deploy-failures",
title="Deploy failed: api-gateway",
severity="sev1",
description="Migration step exited with code 137",
metadata={"commit": "a1b2c3", "environment": "production"},
group_key="deploy:api-gateway",
)
if res["status"] == "filtered":
print("Suppressed:", res.get("reason"))Keyword arguments
| Field | Type | Description |
|---|---|---|
titlerequired | str | Alert title, max 200 chars. |
description | str | Long-form context, max 2000 chars. |
severity | "sev0".."sev4" | Overrides the webhook default. |
metadata | dict | Max 100 KB, max 10 nesting levels. |
group_key | str | Max 200 chars. |
Return value
python
{
"alertId": str | None,
"status": "created" | "filtered" | "occurrence_added" | "reopened",
"message": str,
"occurrenceCount": int | None,
"reason": str | None,
}Error handling
All failures raise OpShiftError. Network-level failures (DNS, connection refused, timeout) surface with status_code == 0.
python
from opshift import OpShift, OpShiftError
try:
opshift.ping("monitor-id")
except OpShiftError as error:
print(error.status_code) # 0, 401, 404, 429, ...
print(str(error)) # human-readable
print(error.body) # parsed JSON body if available
raiseAsync usage
The client is synchronous. To call it from async code, dispatch to a thread:
python
import asyncio
from opshift import OpShift
opshift = OpShift(secret=...)
async def heartbeat():
await asyncio.to_thread(opshift.ping, "your-ping-token")Kept in sync with the TS SDK
The Python and TypeScript SDKs share the same public surface. If a new field lands in one, the other follows in the same release.