Skip to main content

Documentation Index

Fetch the complete documentation index at: https://solo-09d10f60.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Every endpoint in Enoch is served by the FastAPI application running on the control VM (default port 8787) and the worker (also port 8787). All endpoints except root GET /healthz, GET /dashboard, and GET /control/dashboard require a bearer token. The control-plane health endpoint is GET /control/health and does require authentication. The two dashboard HTML endpoints are unauthenticated for the initial page load; the dashboard itself prompts for a bearer token and stores it in localStorage for subsequent API calls. Read the Authentication section below before making your first request. This page maps the main endpoint groups present in the local source snapshot. It is not a generated OpenAPI reference; verify request and response models against the code before building clients.

Authentication

Unauthenticated routes include GET /healthz, GET /dashboard, and GET /favicon.ico. Dashboard data APIs and most control-plane routes require a bearer token or an explicit token bootstrap path where the dashboard code supports it.
Authorization: Bearer <omx_inbound_bearer_token>
Pass the token in every request:
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8787/control/api/status
The dashboard also accepts the token as a ?token= URL query parameter on first load, after which it is stored in localStorage.

GET /healthz

No authentication required. Returns a minimal app-level liveness check. Use authenticated GET /control/health when you need the control-plane database path and control-plane service timestamp.
curl -fsS http://127.0.0.1:8787/healthz
Response:
{"ok": true, "service": "omx_wake_gate", "timestamp": "2025-05-01T12:00:00+00:00"}

GET /control/health

Requires bearer authentication. Returns control-plane health and the configured SQLite database path.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8787/control/health

GET /control/api/status

Returns the full dispatch safety and queue state aggregated from the control-plane database. Add ?refresh_worker=true to trigger a fresh worker preflight before responding.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/status?refresh_worker=true" \
  | python3 -m json.tool
Key response fields:
FieldDescription
dispatch_safetrue when no blockers exist and no critical conflicts are present
dispatch_blockersList of human-readable blocker strings
flags.queue_pausedtrue when the queue is paused
flags.maintenance_modetrue when maintenance mode is active
countsPer-status item counts plus papers and queue_total
active_itemsQueue rows currently in an active dispatch/run state
source_freshnessStaleness of each evidence source
warnings / conflictsStructured findings with severity, source, and suggested actions

GET /control/api/queue-health

Returns queue health with worker freshness details, active run detail, latest alert check results, and recent worker callbacks. Add ?refresh_worker=true to refresh the worker preflight observation first.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/queue-health?refresh_worker=true" \
  | python3 -m json.tool

GET /control/api/queues/{queue}

Returns a paginated list of queue rows filtered to one logical queue group.
queue valueDescription
activeItems in dispatching, running, awaiting_wake, wake_received, or reconciling status
queuedItems waiting to be dispatched
blockedItems in blocked, needs_review, or dispatch_error status, or any item with manual_review_required set
pausedItems in paused status
completedItems in completed or canceled status
allAll rows regardless of status
Query parameters:
ParameterDefaultDescription
page1Page number (≥ 1)
page_size50Rows per page (1–500)
search""Full-text filter across all string fields
status""Exact QueueStatus value filter
sortdispatch_prioritySort column; prefix with - for descending (e.g. -updated_at)
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/queues/queued?page_size=20&search=my-project"

POST /control/dispatch-next

Selects and dispatches the next eligible candidate from the queue. Always use dry_run: true first to verify the candidate before committing a live dispatch.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dry_run": true, "requested_by": "operator"}' \
  http://127.0.0.1:8787/control/dispatch-next \
  | python3 -m json.tool
Request body (DispatchNextRequest):
{
  "dry_run": true,
  "requested_by": "operator",
  "force_preflight": true
}
Response action values: "paused", "noop", "dry_run_dispatch", "live_dispatch", "dispatch_blocked".

POST /control/api/preflight

Runs an explicit worker preflight check without committing a dispatch. Use this to verify worker connectivity, bearer token validity, and GPU/memory headroom before live dispatch.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "wake_gate_url": "http://worker.example:8787",
    "bearer_token": "worker-api-token",
    "require_paused": false,
    "strict": false
  }' \
  http://127.0.0.1:8787/control/api/preflight \
  | python3 -m json.tool
Request body (WorkerPreflightRequest):
{
  "wake_gate_url": "http://worker.example:8787",
  "bearer_token": "",
  "require_paused": true,
  "strict": false,
  "max_gpu_pct": 5.0,
  "min_memory_available_mib": 16384
}
Response (WorkerPreflightResponse):
{
  "ok": true,
  "target": "http://worker.example:8787",
  "summary": "...",
  "checks": [
    {"name": "wake_gate_healthz", "ok": true, "detail": "...", "data": {}},
    {"name": "worker_no_live_runs", "ok": true, "detail": "...", "data": {}}
  ]
}

GET /control/api/projects/{project_id}

Returns project detail aggregating the project record, current queue item, all run records, associated papers, recent events, and cached worker observations.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8787/control/api/projects/my-project-id \
  | python3 -m json.tool
Returns 404 if neither a project record nor a queue item is found for {project_id}.

GET /control/api/papers

Returns the full paper queue as a paginated list.Query parameters:
ParameterDefaultDescription
page1Page number
page_size50Rows per page (1–500)
search""Full-text filter
status""Exact paper_status filter
sort-updated_atSort column; prefix with - for descending (e.g. paper_status)
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/papers?page_size=100"

GET /control/api/paper-reviews

Returns the publication review queue sorted by rank_score descending by default.Query parameters:
ParameterDefaultDescription
page1Page number
page_size50Rows per page (1–500)
search""Full-text filter
review_status""One of triage_ready, unreviewed, in_review, changes_requested, blocked, approved_for_finalization, finalized, rejected
paper_status""One of eligible, draft_generating, draft_review, publication_generating, publication_draft, human_review_required, archived
include_rank_reasonstrueInclude per-item rank reason arrays
sort-rank_scoreSort column; prefix with - for descending (e.g. rank_score)
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/paper-reviews?paper_status=publication_draft&include_rank_reasons=true"

GET /control/api/paper-reviews/next

Returns the highest-ranked paper review detail item matching the given filters. Defaults to paper_status=publication_draft, excluding finalized and rejected items.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/paper-reviews/next?paper_status=publication_draft"
Returns 404 if no matching item exists.

POST /control/api/paper-reviews/{paper_id}/rewrite-draft

Rewrites the paper draft artifacts for the given paper using the configured AI writer (e.g. GLM-5.1 via Synthetic.new). If paper_evidence_sync_enabled is true, the control plane syncs evidence from the worker before rewriting.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "rewrite-my-paper-001",
    "requested_by": "operator",
    "force": true
  }' \
  http://127.0.0.1:8787/control/api/paper-reviews/my-paper-id/rewrite-draft
Request body (PaperReviewRewriteDraftRequest):
{
  "idempotency_key": "paper-review-rewrite:<timestamp>",
  "requested_by": "operator",
  "force": true
}

POST /control/api/paper-reviews/rewrite-batch

Rewrites up to limit papers in a single synchronous batch call. The request stays open until all papers are processed; a 10-paper batch may take several minutes.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "bulk-rewrite-001",
    "requested_by": "operator",
    "paper_status": "publication_draft",
    "limit": 10,
    "force": true,
    "dry_run": false,
    "skip_rewritten": true
  }' \
  http://127.0.0.1:8787/control/api/paper-reviews/rewrite-batch
Request body (PaperReviewBulkRewriteRequest):
{
  "idempotency_key": "paper-review-bulk-rewrite:<timestamp>",
  "requested_by": "ai-publication-pipeline",
  "paper_status": "publication_draft",
  "review_status": "",
  "search": "",
  "limit": 10,
  "force": true,
  "dry_run": false,
  "skip_rewritten": true
}
limit is capped at 200 by the model, but the dashboard uses a default of 10. Set dry_run: true to preview which papers would be selected without triggering any rewrites.

POST /control/api/paper-reviews/{paper_id}/prepare-finalization-package

Assembles the finalization package for an approved paper review. Use dry_run: true to preview the package manifest without writing the package. Use only after the review checklist and approval gates have passed.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "package-my-paper-001",
    "requested_by": "operator",
    "target_label": "public-release",
    "dry_run": true
  }' \
  http://127.0.0.1:8787/control/api/paper-reviews/my-paper-id/prepare-finalization-package

POST /control/api/paper-reviews/{paper_id}/approve-finalization

Marks a paper as approved for finalization. Requires idempotency_key and requested_by.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "approve-my-paper-001",
    "requested_by": "operator",
    "note": ""
  }' \
  http://127.0.0.1:8787/control/api/paper-reviews/my-paper-id/approve-finalization

POST /control/api/paper-reviews/{paper_id}/status

Updates the review_status for a paper review item.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "status-my-paper-001",
    "requested_by": "operator",
    "review_status": "in_review",
    "note": "",
    "blocker": ""
  }' \
  http://127.0.0.1:8787/control/api/paper-reviews/my-paper-id/status
Valid review_status values: unreviewed, triage_ready, in_review, changes_requested, blocked, approved_for_finalization, finalized, rejected.

POST /control/api/paper-reviews/{paper_id}/checklist/{item_id}

Updates the status of a single checklist item for a paper review.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "checklist-my-paper-item1-001",
    "requested_by": "operator",
    "status": "pass",
    "note": ""
  }' \
  http://127.0.0.1:8787/control/api/paper-reviews/my-paper-id/checklist/item1
Valid status values: pending, pass, fail, accepted_risk, not_applicable.

GET /control/api/events

Returns the append-only audit event log. Supports filtering by entity_type, entity_id, event_type, and full-text search.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1:8787/control/api/events?page_size=200"
Query parameters:
ParameterDefaultDescription
page1Page number
page_size100Rows per page (1–500)
entity_type""Filter by entity type (e.g. paper_review)
entity_id""Filter by entity ID
event_type""Filter by event type (e.g. paper_review.draft_rewritten)
search""Full-text filter

GET /control/api/intake/notion

Returns the latest Notion intake sync observation, the current queued-project projection, skipped-row reason counts, and recent intake events.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8787/control/api/intake/notion
These endpoints are served by the worker process and are called by the agent runtime and by the control plane during live dispatch.

POST /omx/event

Receives OMX/Codex lifecycle events from the agent runtime. The wake gate uses these events to track process state and determine when a quiet window has been reached.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "session-end",
    "run_id": "my-project-20250501T120000Z",
    "session_id": "sess-abc123",
    "project_id": "my-project",
    "project_name": "My Project"
  }' \
  http://worker.example:8787/omx/event
Request body (OmxEvent) key fields:
{
  "event": "session-end",
  "run_id": "...",
  "session_id": "...",
  "project_id": null,
  "project_name": null,
  "question": null,
  "root_pid": null,
  "process_group_id": null,
  "timestamp": "2025-05-01T12:00:00+00:00",
  "tmux_session": null,
  "message": null
}
Valid event values: session-start, session-idle, session-stop, session-end, ask-user-question.

POST /prepare-project

Prepares the project workspace on the worker before dispatch. Called automatically by the control plane’s live dispatch path.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "run_id": "my-project-20250501T120000Z",
    "project_id": "my-project",
    "project_name": "My Project",
    "project_dir": "my-project",
    "prompt_file": "my-project/prompts/initial.md",
    "prompt_text": "# Enoch Research Action...",
    "overwrite": true
  }' \
  http://worker.example:8787/prepare-project

POST /dispatch

Dispatches an agent run to the worker. Called automatically by the control plane’s live dispatch path after a successful prepare.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "run_id": "my-project-20250501T120000Z",
    "project_id": "my-project",
    "project_dir": "my-project",
    "prompt_file": "my-project/prompts/initial.md",
    "mode": "exec",
    "model": "gpt-5.5",
    "reasoning_effort": "medium",
    "sandbox": "danger-full-access"
  }' \
  http://worker.example:8787/dispatch
Valid mode values: exec, resume. Valid reasoning_effort values: low, medium, high, xhigh.

GET /dashboard

Returns the browser-based Enoch Control Status Dashboard as an HTML page. No authentication is required to load the page; the dashboard prompts for a bearer token and stores it in localStorage.
open http://127.0.0.1:8787/dashboard

GET /dashboard/api

Returns the full dashboard snapshot as JSON. Used by the worker dashboard for polling.Query parameters:
ParameterDefaultDescription
limitMaximum run rows to include
event_limitMaximum event rows to include
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  "http://worker.example:8787/dashboard/api?limit=50&event_limit=100"
Enoch Core endpoints are prefixed /enoch-core and all require authentication.

GET /enoch-core/health

Returns the current Enoch Core mode and database path.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8787/enoch-core/health
Response (HealthResponse):
{
  "ok": true,
  "service": "enoch_core",
  "mode": "shadow",
  "db_path": "/var/lib/enoch-control-plane/state/enoch_core.sqlite3",
  "timestamp": "2025-05-01T12:00:00+00:00"
}
Valid mode values: off, shadow, compare, enforce.

POST /enoch-core/snapshots/n8n-queue

This endpoint retains its legacy n8n-queue name for backward compatibility, but n8n is no longer used. Any source can post queue snapshots.
Ingests a queue snapshot from any compatible source. The idempotency_key is required; the same key with the same payload is accepted idempotently, but the same key with a different payload returns 409.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "idempotency_key": "snapshot-2025-05-01T120000Z",
    "source": "n8n",
    "mode": "shadow",
    "queue_rows": [],
    "paper_rows": [],
    "captured_at": "2025-05-01T12:00:00+00:00"
  }' \
  http://127.0.0.1:8787/enoch-core/snapshots/n8n-queue
Response (SnapshotIngestResponse):
{
  "ok": true,
  "mode": "shadow",
  "inserted": true,
  "event_id": 42,
  "snapshot_id": 7,
  "queue_rows": 0,
  "paper_rows": 0,
  "would_apply": false,
  "message": "snapshot recorded locally only; no external side effects performed"
}

GET /enoch-core/projections/queue

Returns the queue projection computed from the latest ingested snapshot.
curl -fsS \
  -H "Authorization: Bearer $TOKEN" \
  http://127.0.0.1:8787/enoch-core/projections/queue
Response (QueueProjection) key fields:
{
  "ok": true,
  "mode": "shadow",
  "projection_version": "enoch-core.queue.v1",
  "total_queue_rows": 0,
  "total_paper_rows": 0,
  "status_counts": {},
  "active_rows": [],
  "draft_candidate_count": 0,
  "polish_candidate_count": 0,
  "warnings": []
}