API reference

Routes and JSON of the OpenWAF Tasks management API under dash.openwaf.dev, the CLI commands and the MCP tools.

On this page

API

All routes are under https://dash.openwaf.dev/v1/orgs/{org} and take an OpenWAF API token (owf_…) or the dashboard session. Reads need readonly; writes need an admin of the whole organization, take X-Change-Reason (recorded in the audit log) and accept ?dry_run=true to validate without saving.

RouteWhat it does
GET /tasksOverview: enabled, requirements, quota, usage, kill and every task. Readable before access is approved.
POST /tasksCreate a task; 201 {"task", "webhook_secret"} (the secret only when a webhook is set, once)
GET /tasks/{task}Read a task ({task} is its id or name)
PATCH /tasks/{task}Change any writable field; "rotate_webhook_secret": true for a new secret
DELETE /tasks/{task}Delete it (204)
POST /tasks/{task}/runRun it now; 202 with the run
GET /tasks/{task}/runs?limit=&before=Runs, newest first: {"items", "next"}
GET /tasks/browser-profiles?key_id=Profiles of a browser key: {"items": [{"id", "name"}]}
GET /task-runs/{run}One run with its approvals and artifacts
GET /task-runs/{run}/logs?after=<seq>Log lines after seq: {"items": [{"seq", "at", "level", "type", "message"}]}
GET /task-runs/{run}/artifacts/{id}A screenshot (image/jpeg or image/png)
GET /task-runs/{run}/recording302 to the recording file, when the run recorded one
POST /task-runs/{run}/cancelCancel a run; answers the run
GET /task-approvals?status=&task=Approvals: {"items"}; status is pending, approved, rejected, expired, executed or failed
GET /task-approvals/{id}One approval
POST /task-approvals/{id}/approve{"payload_sha256", "reason"}; answers the approval
POST /task-approvals/{id}/reject{"reason"}; answers the approval

Overview

{"enabled": true,
 "requirements": {"browsers": true, "egress": true, "email_verified": true, "two_factor": true},
 "quota": {"runs_per_month": 200, "max_tasks": 5, "max_concurrent": 1},
 "usage": {"period_start": "2026-10-01T00:00:00Z", "period_end": "2026-11-01T00:00:00Z",
           "runs": 14, "active": 0, "pending_approvals": 1},
 "kill": false,
 "tasks": [ … ]}

kill is true while the service is paused for every organization: no runs start.

Task

{"id": "…", "name": "guestbook", "description": "", "kind": "script",
 "schedule": {"cron": "0 9 * * *", "timezone": "Europe/Madrid"},
 "paused": false,
 "browser": {"key_id": "…", "key_name": "ci-agent", "profile": "", "recording": false},
 "allow": ["example.com"],
 "script": "export default async function ({ page, task }) { … }",
 "input": {}, "state": {},
 "max_run_minutes": 10,
 "approval": {"policy": "required", "expire_minutes": 120, "relaxed_domains": []},
 "action_limits": [{"domain": "example.com", "min_interval_minutes": 30, "max_per_day": 4}],
 "webhook": {"url": "https://hooks.example.com/openwaf", "secret_set": true},
 "pool": "browsers", "egress_agent": null,
 "next_run_at": "2026-10-30T08:00:00Z",
 "last_run": {"id": "…", "status": "succeeded", "finished_at": "2026-10-29T08:00:41Z"},
 "created_at": "…", "updated_at": "…"}
FieldRules
nameLowercase letters, digits and hyphens, up to 63, unique in the organization
kindscript or agent; cannot change
schedule{"cron", "timezone"} (5 fields, IANA zone, at most every 15 minutes) or {"at"} for one run
browserkey_id of a browser key of the organization, profile name (empty for a clean browser), recording
allow1 to 20 domains: example.com or *.example.com
scriptscript only: ES module up to 256 KiB. See the script quickstart.
agentagent only: {"goal", "egress_target", "model", "max_steps"}. See the agent quickstart.
inputJSON up to 64 KiB, given to the script or the agent
max_run_minutes1 to 30
approvalexpire_minutes 10 to 1440. policy and relaxed_domains are read-only; see policies.
action_limitsStricter per-domain limits
webhook{"url"} to set, null to remove. See webhook.

state, pool, egress_agent, next_run_at and last_run are read-only.

Run

{"id": "…", "task_id": "…", "task_name": "guestbook", "number": 12, "trigger": "schedule",
 "status": "awaiting_approval",
 "created_at": "…", "started_at": "…", "finished_at": null, "error": "",
 "output": {"posted": "pending approval"},
 "steps": 0, "browser_seconds": 38, "model_calls": 0, "prompt_tokens": 0, "completion_tokens": 0,
 "blocked_requests": 0, "live_url": null, "recording_available": false, "egress_agent": null,
 "approvals": [ … ],
 "artifacts": [{"id": "…", "name": "before", "content_type": "image/jpeg", "size": 81234, "created_at": "…"}]}

status is one of queued, running, awaiting_approval, executing, succeeded, failed, rejected, expired, timed_out and canceled. trigger is schedule or manual. live_url is only set while the run has a browser.

Approval

{"id": "…", "task_id": "…", "task_name": "guestbook", "run_id": "…", "status": "pending",
 "summary": "Sign the guestbook with \"Hello from Example Inc.\"",
 "target": "https://example.com/guestbook", "domain": "example.com",
 "payload": {"steps": [{"op": "goto", "url": "https://example.com/guestbook"}, … ]},
 "payload_sha256": "9c1e…", "screenshot_id": "…",
 "requested_at": "…", "expires_at": "…", "decided_at": null, "decided_by": null, "reason": null,
 "not_before": null, "executed_at": null, "result": null}

After the act phase, result is {"ok", "final_url", "error", "screenshot_id"}. Steps are described in approvals.

Errors

StatuscodeWhen
403feature_disabledOpenWAF Tasks is not enabled for the organization
403forbiddenThe role is too low, or the member or token is limited to a client or a zone
404not_foundNo such task, run, artifact or approval
409payload_changedThe payload_sha256 you sent is not the approval's
409not_pendingThe approval was already decided or expired
422invalidA field breaks the rules above; field names it

CLI

openwaf-cloud ctl tasks … calls the API above. See get started with the CLI.

The organization comes from --org or OPENWAF_ORG. Changes show what they will do and ask before applying (--yes skips the question, --dry-run only validates).

CommandWhat it does
tasks listOverview and tasks
tasks get <task>One task
tasks create <task.json|-> --reason "…"Create a task from a JSON body
tasks update <task> <patch.json|-> --reason "…"Change a task
tasks delete <task> --reason "…"Delete a task
tasks run <task> --reason "…"Run it now
tasks runs <task> [--limit n]Runs of a task
tasks run-get <run>One run with its approvals and artifacts
tasks cancel <run> --reason "…"Cancel a run
tasks approvals [--status pending] [--task <task>]Approvals
tasks approve <approval> --sha256 <hash> --reason "…"Approve the exact payload
tasks reject <approval> --reason "…"Reject it

MCP tools

The OpenWAF MCP server has 12 tools for OpenWAF Tasks. Writes need a reason and take two steps: confirm=false only checks, confirm=true applies.

ToolRole
tasks_listreadonly
tasks_getreadonly
task_runs_listreadonly
task_runs_getreadonly
task_approvals_listreadonly
tasks_createadmin
tasks_updateadmin
tasks_deleteadmin
tasks_runadmin
task_runs_canceladmin
task_approveadmin. The check step shows the exact payload, its payload_sha256 and the screenshot id; the apply step needs that payload_sha256.
task_rejectadmin

An assistant can prepare an approval for you, but read the steps yourself before you confirm it.

Last updated:

↑↓ to navigate↵ to openesc to close