Automation API
All automation endpoints are project-scoped. The concept docs live at Automation rules; this page is the REST surface the dashboard's Automation area uses.
Mutating endpoints require a CSRF token (see
Authentication). Role enforcement is
destructiveness-aware: a rule whose actions are only notify needs project
operator, while a rule carrying a destructive action (retry, cancel)
needs project admin plus a fresh second-factor check (the same step-up
gate as the other sensitive actions; expect 403 mfa_reverify_required when
the sudo window has lapsed). Actions the grammar knows but the runner does not execute
(webhook, revoke, purge, pause_schedule) are rejected fail-closed with
422 at create and update time.
List rules
Section titled “List rules”GET /api/v1/projects/{slug}/automation/rulesRole: viewer. Returns {"items": [Rule, ...]}.
A rule object:
{ "id": "5f0b7f2e-...", "project_id": "6b2d25e3-...", "name": "Retry failed invoice runs", "is_enabled": true, "dry_run": false, "trigger": "task.failed", "conditions": {"task_name": "billing.run_daily_invoices"}, "actions": [{"type": "retry", "max_retries": 2}], "max_executions_per_window": 20, "window_seconds": 300, "cb_tripped": false, "cb_execution_count": 3, "created_by": "26573b1a-...", "created_at": "2026-07-16T12:00:00Z", "updated_at": "2026-07-16T12:00:00Z"}cb_tripped / cb_execution_count expose the rolling-window circuit breaker:
when a rule exceeds max_executions_per_window inside window_seconds, the
breaker trips and the rule degrades to notify-only. It clears itself: each
admission attempt ages out executions older than the window, and once fewer
than the limit remain the next admission both executes and resets the flag.
There is no operator reset control, so do not go looking for one.
Get one rule
Section titled “Get one rule”GET /api/v1/projects/{slug}/automation/rules/{rule_id}Role: viewer.
Create a rule
Section titled “Create a rule”POST /api/v1/projects/{slug}/automation/rulesRole: operator for notify-only rules and admin when any action is
destructive. A browser-session request for a destructive rule also requires a
fresh second factor; bearer-authenticated callers follow their API-key
authority. Returns 201 with the created rule.
Body fields mirror the rule object: name, trigger (task.failed,
task.succeeded, task.retried, task.orphaned, worker.offline,
schedule.misfired), optional conditions (engine, queue, task name,
exception, priority, runtime, or an issue
fingerprint), actions, dry_run, is_enabled, and the
breaker window (max_executions_per_window, window_seconds).
Update a rule
Section titled “Update a rule”PATCH /api/v1/projects/{slug}/automation/rules/{rule_id}Same role rules as create, evaluated against both the old and post-update rule
shape. An edit that touches or introduces a destructive action requires
admin; browser-session calls also require a fresh second factor.
Delete a rule
Section titled “Delete a rule”DELETE /api/v1/projects/{slug}/automation/rules/{rule_id}Role: operator for notify-only rules, admin for rules with destructive
actions. Returns 204.
Reset a tripped circuit breaker
Section titled “Reset a tripped circuit breaker”POST /api/v1/projects/{slug}/automation/rules/{rule_id}/reset-circuitClears the breaker so the rule can fire again, and writes an
automation.rule.circuit_reset audit row. Re-arming a destructive rule
requires admin; browser-session calls also require a fresh second factor.
Returns the refreshed rule.
Project kill switch
Section titled “Project kill switch”GET /api/v1/projects/{slug}/automation/settingsPUT /api/v1/projects/{slug}/automation/settingsThe settings object carries the per-project kill switch:
{"automation_enabled": true}When false, the rule engine loads no rules for the project, so nothing
fires regardless of each rule's own is_enabled state. Every firing (and
every breaker trip, skip, and auto-disable) lands on the HMAC-chained
audit log.