What Oak Creek checks, and how it tells you
Every feature is built around one question: did this job run when it should have, and did it finish cleanly? Here is how schedules, signals, alerts and the API work.
Two kinds of schedule
Period checks expect a ping every N minutes or hours, which suits queue workers and loops. Cron checks take a standard five-field expression plus an IANA time zone, so a job set for 02:15 in America/Los_Angeles is expected at 02:15 local time all year.
The grace period is how long Oak Creek waits after the expected time before marking the check Late. A second threshold marks it Down and triggers escalation.
- Checks
- Runs
- Integrations
- API keys
- Settings
Checks
Project: client-sites
| Check | Type | Grace | Status |
|---|---|---|---|
| queue-worker-heartbeat | every 5m | 2m | Up |
| client-acme-wp-cron | */15 * * * * | 10m | Up |
| weekly-sales-report Europe/Berlin | 0 7 * * 1 | 1h | Paused |
| restic-nas-backup | 30 1 * * * | 45m | Late |
Signals your job can send
Each check has one ping URL. Append a suffix to say what happened. GET, HEAD and POST all work; POST bodies are stored as the run log.
- /start
- Job began. Starts the duration timer and catches jobs that start but never finish.
- / (empty) or /0
- Job finished successfully.
- /fail or /1–255
- Job failed. The exit code is stored with the run.
- /log
- Attach output to the current run without changing status.
run_export.py
import subprocess, requests
PING = "https://ping.oakcreekventures.xyz/b41e09d2"
requests.get(f"{PING}/start", timeout=10)
result = subprocess.run(["/opt/etl/export_orders.sh"], capture_output=True, text=True)
# Exit code becomes the status; the last 10 KB of output is kept with the run
requests.post(f"{PING}/{result.returncode}", data=result.stdout[-10000:], timeout=10) Illustrative example
- Checks
- Runs
- Integrations
- API keys
- Settings
restic-nas-backup
Alert route: infra
- Late: no ping since 01:30 (grace 45m) 02:15
- Oak Creek posted to Microsoft Teams, IT Ops channel 02:15
- Oak Creek emailed oncall@ (quiet hours: Teams only until 07:00) 07:00
- Admin acknowledged from email 07:12
Alert routes and escalation
An alert route is a list of channels with delays. Attach routes to checks directly or by tag.
- Channels: Slack, Microsoft Teams, PagerDuty, email and signed JSON webhooks
- Escalation steps after 15, 30 or 60 minutes, or a custom delay
- Quiet hours per route, and maintenance windows per tag
- Recovery notices sent to the same channels that got the alert
Manage checks from code
The REST API uses JSON and project-scoped bearer keys. Create a check in the same Terraform run or deploy script that creates the job, pause it during migrations, and pull run history into your own dashboards. Starter includes read-only keys; Team and Business add read-write keys.
POST /api/v1/checks
201 Created
{
"name": "client-acme-wp-cron",
"schedule": "*/15 * * * *",
"tz": "America/New_York",
"grace": 600,
"tags": ["client-acme", "wordpress"],
"channels": ["slack:#client-acme", "email:oncall"],
"status": "new",
"ping_url": "https://ping.oakcreekventures.xyz/c93a51f0"
} Illustrative example
Works wherever a job can make an HTTPS request
- Linux crontab and /etc/cron.d
- systemd timers (ExecStartPre / ExecStartPost)
- Kubernetes CronJob
- GitHub Actions schedule triggers
- Windows Task Scheduler with PowerShell
- Laravel Scheduler (pingBefore / thenPing)
- Celery beat and Sidekiq scheduled jobs
- WordPress WP-Cron via WP-CLI
- AWS EventBridge Scheduler and Lambda
- Any HTTP client: curl, wget, fetch, requests