Python SDK

Monitor scheduled jobs from your Python code with the official SteadyCron SDK. Wrap a job with @steadycron.job and get alerted on missed, failed, and stuck runs — the monitor is declared as code in YAML or Terraform.

The steadycron Python package is the official code-monitoring SDK. Wrap a scheduled job with @steadycron.job and SteadyCron will know when it started, succeeded, or failed — and alert you when it doesn’t run on time or starts but never finishes.

The SDK never creates monitors. You declare the heartbeat monitor as code — in a YAML manifest or with the Terraform provider — and reference it from your application by its stable key. The cron schedule, the alert rules, and the instrumentation all live in the same repository.

Install

pip install steadycron

No runtime dependencies — the SDK uses Python’s standard library only.

Quick start

import steadycron

steadycron.api_key = "sc_ro_..."  # read-only key; or set STEADYCRON_API_KEY

@steadycron.job("nightly-db-backup")   # the monitor key, as declared in code
def backup():
    run_backup()   # start on entry, success on return, fail (+re-raise) on exception

The string "nightly-db-backup" is the same key you set on the steadycron_heartbeat_monitor resource (Terraform) or the heartbeat job id (YAML manifest). That is the only contract between your schedule-as-code and your application.

Context manager

with steadycron.monitor("nightly-db-backup"):
    run_backup()

Manual pings

For finer control, send pings yourself:

m = steadycron.Monitor("nightly-db-backup")
m.ping()                              # success heartbeat
m.ping(state="start")
m.ping(state="fail", message="disk full")

Authentication

The SDK uses a read-only API key to resolve a monitor key to its ping token at startup. Create one under Settings → API keys → New key → Scope: Read-only.

Provide it via any of:

  • Environment variable: STEADYCRON_API_KEY=sc_ro_...
  • Module attribute: steadycron.api_key = "sc_ro_..."
  • steadycron.configure(api_key="sc_ro_...")

Configuration

import steadycron

steadycron.configure(
    api_key="sc_ro_...",
    environment="production",   # optional — sent on every ping
    capture_errors=True,        # include the exception message on fail pings (default False)
    ping_timeout=5.0,           # seconds (default 5)
    resolve_cache_ttl=3600.0,   # seconds (default 3600 = 1 hour)
)
SettingDefaultEnv var fallback
api_keyNoneSTEADYCRON_API_KEY
api_urlhttps://api.steadycron.comSTEADYCRON_API_URL
ping_urlhttps://ping.steadycron.comSTEADYCRON_PING_URL
environmentNoneSTEADYCRON_ENVIRONMENT
capture_errorsFalse
ping_timeout5.0 s
resolve_cache_ttl3600.0 s

How it works

  1. On first use, the SDK calls GET /api/monitors/resolve?key=<your-key> with the read-only API key to retrieve the ping token. The token is cached for one hour (configurable via resolve_cache_ttl).
  2. All pings are fire-and-forget: a bounded ping_timeout is applied, and any error is logged via logging.getLogger("steadycron") at WARNING and discarded. Pings never raise.
  3. Resolution errors — 404 (unknown key), 409 (ambiguous key), or wrong kind — raise immediately on first use. They indicate misconfiguration.
  4. On an exception inside the wrapped job, a fail ping is sent and the original exception is re-raised unchanged.

Direct / token mode

If you cannot use API-key resolution (for example, in an air-gapped environment), set the ping token directly and skip the resolve call:

steadycron.monitors = {"nightly-db-backup": "hRkmWz8oZtlMFzvTAUdnRE"}

The token is visible in the dashboard under Job detail → Code monitoring → Reveal ping token.

Reliability contract

  • Ping failures are never raised. A transport error, timeout, or non-2xx response is logged and discarded — a monitoring outage never takes down your job.
  • Resolution errors always raise. A 404 or 409 from the resolve endpoint raises on first use; fix the key or remove the decorator.
  • Original exceptions pass through unchanged. The decorator and context manager do not wrap your exceptions.
  • No runtime dependencies. The SDK uses urllib.request from the standard library.