The local API

The HarmFlow window is one client of the daemon, the background process that runs your tasks; a script of yours can be another. Everything the window does goes through this API. The authority is the OpenAPI description in harmflow-app, contracts/api/openapi.yaml, version v1: where this page and it differ, it wins.

Reaching the daemon

Authenticating

From a terminal on the Mac, with jq installed:

dir=~/Library/Application\ Support/HarmFlow
port=$(jq .port "$dir/run/daemon.json")
token=$(security find-generic-password \
  -s com.harmflow.local-api -a token -w)
curl -H "Authorization: Bearer $token" \
  "http://127.0.0.1:$port/api/v1/tasks"

Conventions

The resources

Tasks

Executions

The daemon and its harnesses

An example

GET /api/v1/tasks

200 OK
[
  {
    "id": "weekly-notes",
    "name": "Weekly notes",
    "type": "general",
    "enabled": true,
    "revision": "3f9c2a7d1e4b8a60",
    "harness": "claude-code",
    "fallbackHarnesses": ["codex"],
    "schedule": "0 9 * * 1",
    "timezone": "America/New_York",
    "nextFireAt": "2026-11-09T14:00:00Z",
    "running": false,
    "queued": false,
    "repositories": [],
    "warnings": []
  }
]

revision identifies the task file's content: an update sends it back as baseRevision.

The event stream

Errors

Every error answers with one object, error, which holds a code and a message in English, and may hold messageKey and params to translate the message, validation with each problem a task has, and currentRevision on a conflict over a task file.

404 Not Found
{
  "error": {
    "code": "not_found",
    "message": "no task weekly-report"
  }
}

The codes are bad_request, unauthorized, forbidden, not_found, conflict, validation_failed, task_disabled, executions_running, and internal. A task that fails validation answers with 422, and nothing is written.