HTTP API reference

REST endpoints exposed by nitpick serve.

Start the server:

nitpick serve --port 3737

Base URL: http://localhost:3737.

v1.3+: the API is fully async. POST /jobs returns 202 Accepted immediately with a job_id; the run executes in the background. Poll GET /jobs/:id for status (state is authoritative on disk under runs/<id>/job-state.json). Human-in-the-loop answers go through POST /jobs/:id/input.

GET /health

Liveness check.

curl http://localhost:3737/health

Response 200 OK:

{"ok": true,"timestamp":"2026-04-16T14:32:05.112Z" }

GET /status

Knowledge base summary.

curl http://localhost:3737/status

Response:

{"project": {"name":"Brooklyn","base_url":"https://..." },"pages_known": 15,"flows_configured": 1,"last_crawl":"2026-04-16T14:32:05.112Z"
}

POST /crawl

Rebuild the page graph.

curl -X POST http://localhost:3737/crawl

Response:

{"success": true,"pages": 15,"duration_ms": 100234 }

POST /jobs (async — v1.3+)

Start a QA run. Returns 202 Accepted immediately; the run executes in the background.

curl -X POST http://localhost:3737/jobs \
 -H"Content-Type: application/json" \
 -d '{"trigger":"manual","scope":"iterative","change_description":"I modified the task creation form"
 }'

Request body:

FieldTypeDescription
triggerstringmanual / pr / deploy / schedule / incident / webhook
scopestringfull / iterative / smoke / targeted
target_urlsstring[]Required for targeted scope
change_descriptionstringRequired for iterative scope
resumestringOptional run_id to resume (see --resume in the CLI)

Response (202 Accepted):

{"job_id":"2026-04-22T06-18-01-manual","status":"queued","run_dir":"./runs/2026-04-22T06-18-01-manual","poll":"/jobs/2026-04-22T06-18-01-manual"}

GET /jobs (v1.3+)

List every run on disk, newest first. Handy for dashboards.

curl http://localhost:3737/jobs

Response: { jobs: [{ job_id, run_dir, status, started_at, updated_at }, ...] }.

GET /jobs/:job_id

Current job state — read from disk (runs/<id>/job-state.json) on every call, so polling is cheap and survives a server restart.

curl http://localhost:3737/jobs/2026-04-16-14-32-05-manual

Response: full JobState object. Key fields to watch on a poll loop:

  • status: pendingdiscoveringawaiting_scope_confirmationexploringreportingcompleted | failed | cancelled
  • pending_user_input: set when the workflow is waiting on a Phase 3.5 approval or similar. Answer via POST /jobs/:id/input.
  • page_statuses, flow_statuses: per-page / per-flow progress.

GET /jobs/:job_id/report

Fetch the unified report (reports/data.json) for a completed job.

curl http://localhost:3737/jobs/2026-04-16-14-32-05-manual/report

Returns 404 until the reporter has written the file — poll GET /jobs/:id until status === "completed" first.

POST /jobs/:job_id/input (v1.3+)

Supply a response to a pending human-in-the-loop prompt. The workflow must have pending_user_input set when you POST; otherwise you get 409.

curl -X POST http://localhost:3737/jobs/2026-04-22T06-18-01-manual/input \
 -H "Content-Type: application/json" \
 -d '{"response":"Approved"}'

Response { ok: true } when the answer was stored. The orchestrator picks it up and resumes within a few seconds.

POST /jobs/:job_id/cancel (v1.3+)

Best-effort cancellation. Transitions the job to cancelled if the workflow state machine allows it (you can’t cancel a run that already reached completed or failed).

curl -X POST http://localhost:3737/jobs/2026-04-22T06-18-01-manual/cancel