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.
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).
dry_run defaults to true, so a new rule audits what it would do and
executes nothing until an operator flips it live. max_executions_per_window
defaults to 100 (1 to 100000) and window_seconds to 3600 (1 to 604800). A
name already used by another rule in the project returns 409.
conditions is either one flat object, whose keys are AND-ed, or a single
one-level {"all": [...]} / {"any": [...]} group of at most 20 flat
members. task_name_pattern and exception_pattern are fnmatch globs capped
at 200 chars, five */? wildcards, and three character classes. actions
holds 1 to 10 entries, and the serialised conditions plus actions must fit
in 64 KiB; either limit fails with 422.
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/settingsGET needs viewer. PUT needs admin and a CSRF token; turning the switch
on from a browser session also requires a fresh second factor, because it
re-arms every destructive rule in the project at once (turning it off does
not). Each change writes an automation.kill_switch.updated audit row.
The 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.