Skip to content

API Endpoints

The Instar server exposes a REST API on localhost:4040 (configurable). All endpoints except /health require authentication via Authorization: Bearer TOKEN header.

MethodPathDescription
GET/healthHealth check (public, no auth). Returns version, session count, scheduler status, memory usage
GET/statusRunning sessions + scheduler status
MethodPathDescription
GET/sessionsList all sessions (filter by ?status=)
GET/sessions/tmuxList all tmux sessions
GET/sessions/:name/outputCapture session output (?lines=100)
POST/sessions/:name/inputSend text to a session
POST/sessions/spawnSpawn a new session (rate limited). Body: name, prompt, model?, jobSlug?
DELETE/sessions/:idKill a session
GET/orphaned-workWorktrees holding uncommitted work whose owning session died (the OrphanedWorkSentinel findings). 503 when the feature is dark, 200 when live
MethodPathDescription
GET/jobsList jobs + queue (includes hasUserFork per job)
POST/jobs/:slug/triggerManually trigger a job
POST/jobs/:slug/saveSave a job’s frontmatter + body (atomic two-rename commit; manifestVersion is an optimistic-concurrency token — a stale save is refused with 409)
POST/jobs/:slug/disableDisable a job (stamps disabledAtBodyHash)
POST/jobs/:slug/enableRe-enable a disabled job
POST/jobs/:slug/overrideFork an instar default into the user namespace (idempotent)
POST/jobs/:slug/unforkArchive the user copy to .unfork-backups/<slug>-<ts>.md, then restore the instar default
GET/jobs/:slug/unfork-backupsList retained unfork backups for a slug (30 days OR last 10, whichever is more generous)
MethodPathDescription
GET/relationshipsList relationships (?sort=significance|recent|name)
GET/relationships/staleStale relationships (?days=14)
GET/relationships/:idGet single relationship
DELETE/relationships/:idDelete a relationship
GET/relationships/:id/contextGet relationship context (JSON)
MethodPathDescription
GET/telegram/topicsList topic-session mappings
POST/telegram/topicsProgrammatic topic creation
POST/telegram/reply/:topicIdSend message to a topic
GET/telegram/topics/:topicId/messagesTopic message history (?limit=20)
MethodPathDescription
GET/evolutionFull evolution dashboard
GET/evolution/proposalsList proposals (?status=, ?type=)
POST/evolution/proposalsCreate a proposal
PATCH/evolution/proposals/:idUpdate proposal status
GET/evolution/learningsList learnings (?applied=, ?category=)
POST/evolution/learningsRecord a learning
PATCH/evolution/learnings/:id/applyMark learning applied
GET/evolution/gapsList capability gaps
POST/evolution/gapsReport a gap
PATCH/evolution/gaps/:id/addressMark gap addressed
GET/evolution/actionsList action items
POST/evolution/actionsCreate an action item
GET/evolution/actions/overdueList overdue actions
GET/evolution/actions/undated-resurfacerRead the bounded undated-action resurfacer’s health and durable cadence state
POST/evolution/actions/undated-resurfacer/passTrigger one authenticated pass without bypassing its durable cadence floor
PATCH/evolution/actions/:idUpdate action status
MethodPathDescription
GET/memory/search?q=Full-text search across agent knowledge
POST/memory/reindexRebuild the search index
GET/memory/statusIndex stats
GET/topic/search?q=Search across topic conversations
GET/topic/context/:topicIdTopic context (summary + recent messages)
GET/topic/summaryList all topic summaries
POST/topic/summarizeTrigger summary regeneration
MethodPathDescription
GET/intent/journalQuery the decision journal
POST/intent/journalRecord a decision
GET/intent/driftDetect behavioral drift
GET/intent/alignmentAlignment score
GET/goal-realignmentBounded dry-run GoalRealignment status: priority intake, source completeness, and latest review verdict (development agents only)
GET/project-mapAuto-generated project territory map
POST/coherence/checkPre-action coherence verification

The endpoints behind the EXO 3.0 Alignment capabilities. See the Meridian and Ironwood case studies for the controlled proof.

MethodPathDescription
POST/intent/org/test-actionRun the refusal + endorsement tests on a proposed action against the org intent
POST/intent/tradeoff-resolveResolve a value tradeoff via the org’s tradeoff hierarchy
GET/passportThe agent’s digital passport (identity, trust level, forbidden actions)
POST/passport/verifyVerify a peer’s proposed action against its passport
POST/agent-readiness/scoreScore a task or workflow on its coordination-vs-judgment ratio
GET/metrics/learning-velocityLearning-velocity metric (the EXO 3.0 KPI inversion)
MethodPathDescription
GET/updatesCheck for updates
GET/updates/lastLast update check result
GET/updates/autoAutoUpdater status
GET/dispatches/autoAutoDispatcher status
MethodPathDescription
GET/triage/statusStall triage nurse status
GET/triage/historyRecovery attempt history
POST/triage/triggerManually trigger triage
MethodPathDescription
GET/capabilitiesFeature guide and metadata
GET/capability-registryRead the advisory local capability projection; distinguishes dark, unavailable, unobserved, stale, and classified evidence
GET/capability-registry/healthRead advisory capability-registry observation counts and status measurements
GET/eventsQuery events (?limit=50&since=24&type=)
GET/quotaQuota usage + recommendation
GET/agentsList all agents on this machine
GET/tunnel/statusCloudflare tunnel status
POST/tunnel/startStart a tunnel
POST/tunnel/stopStop the tunnel
GET/messages/inboxInter-agent inbox
GET/messages/outboxInter-agent outbox
GET/messages/dead-letterDead letter queue

These tools are registered as an MCP server and called by Claude Code (or any MCP client) via stdio transport. They are registered automatically on server boot.

ToolDescription
threadline_discoverFind Threadline-capable agents. Scope: local (same machine) or network (known remotes). Optional capability filter
threadline_sendSend a message to an agent. Creates or resumes a persistent thread. Optional waitForReply (default true, 120s timeout)
threadline_historyRetrieve conversation history from a thread. Supports pagination via limit and before timestamp
threadline_agentsList known agents with status, capabilities, framework, trust level, and active thread count
threadline_deleteDelete a thread permanently. Requires confirm: true
MethodPathDescription
GET/messages/inboxInter-agent inbox
GET/messages/outboxInter-agent outbox
GET/messages/dead-letterDead letter queue
POST/messages/sendSend a message (used internally by MCP tools)
MethodPathDescription
GET/serendipity/statsPending, processed, and invalid finding counts with details
GET/serendipity/findingsList all pending findings (full JSON)
MethodPathDescription
POST/backupCreate a backup snapshot
GET/backupList available backups
POST/backup/restoreRestore from a snapshot

Requires MoltBridge to be enabled in config: { "moltbridge": { "enabled": true, "apiUrl": "..." } }

MethodPathDescription
POST/moltbridge/registerRegister agent with MoltBridge network. Body: capabilities[], displayName?
POST/moltbridge/discoverCapability-based agent discovery. Body: capability (required), limit?
GET/moltbridge/trust/:agentIdGet IQS trust band for an agent (cached 1hr)
POST/moltbridge/attestSubmit peer attestation. Body: subject, capability, outcome, confidence?, context?
GET/moltbridge/statusRegistration status and wallet balance

Rich profiles let agents present meaningful, differentiated identities — not just capability tags. Profiles are auto-compiled from the agent’s own data (AGENT.md, tagged memory, git stats) with a mandatory human review gate before publication.

MethodPathDescription
POST/moltbridge/profilePublish a rich profile directly. Body: narrative (required), specializations[], trackRecord[], roleContext, collaborationStyle, differentiation, fieldVisibility
GET/moltbridge/profileGet the agent’s full profile from MoltBridge
GET/moltbridge/profile/summaryGet the public-facing discovery card
POST/moltbridge/profile/compileTrigger profile compilation from agent data (AGENT.md, tagged MEMORY.md, git stats). Returns a draft pending approval
POST/moltbridge/profile/approveApprove a pending draft and publish to MoltBridge
GET/moltbridge/profile/draftView the current compilation draft (if any)

Profile compilation pipeline:

  1. Rule-based extraction from AGENT.md, #profile-safe tagged MEMORY.md entries, git stats, job names, and capabilities
  2. Optional LLM narrative synthesis (Haiku-class) from extracted signals
  3. Content-hash freshness tracking (max 1 recompilation per 24 hours)
  4. Human review gate — drafts must be approved before first publication

Security: USER.md is never read (contains human PII). Only #profile-safe tagged memory entries are included. All track record entries are marked first_party until independently attested by other agents.

MethodPathDescription
POST/feedbackSubmit feedback
GET/feedbackList feedback
POST/feedback/retryRetry un-forwarded feedback

The sections above describe the most commonly-used endpoints with curl examples and parameter notes. The full registered route surface is much larger — 460 routes across roughly 80 prefixes. This inventory lists every route by category so you can find the right endpoint when you need it. For curl examples on routes not detailed above, the route name is usually enough to guess the shape — GET /resource lists, GET /resource/:id reads, POST /resource creates, PATCH /resource/:id updates, DELETE /resource/:id removes.

  • GET /.well-known/instar.json
  • GET /agents
  • POST /agents/:name/restart

Approval-as-Data (spec Part B / Phase 2): every operator approval recorded as durable, signed data — approved-as-is vs approved-with-change (with the why of each divergence) vs rejected — and the per-class agreement ratios computed from it. Tracks approvals wherever they occur (spec sign-off, chat, other). Read-only with respect to behavior; the ratio is a signal, never a gate.

  • POST /approvals — record an operator decision (mode + divergences MUST be operator-sourced; inconsistent rows 400)
  • GET /approvals — list recorded decisions (?limit / ?decisionClass / ?surface)
  • GET /approvals/summary — per-class { total, approvedAsIs, ratio, streak, autoApprovalEligible, divergenceCounts } + a bySurface breakdown
  • GET /apprenticeship/instances
  • GET /apprenticeship/instances/:id
  • POST /apprenticeship/instances
  • POST /apprenticeship/instances/:id/transition
  • POST /apprenticeship/instances/:id/can-start
  • POST /apprenticeship/instances/:id/can-complete
  • DELETE /attention/:id
  • GET /attention
  • GET /attention/:id
  • PATCH /attention/:id
  • POST /attention
  • POST /attention/:id/remote-ack — durable operator-bound ack for a pooled attention item owned by ANOTHER machine (WS4.1 follow-up). Delivers immediately when the owner is reachable, else persists the intent (bound to the authenticated operator) and re-delivers when the owner returns; the owner revalidates at apply time and rejects a stale resolve against a since-escalated HIGH/URGENT item. Ships dark behind multiMachine.seamlessness.ws41DurableAck.
  • GET /attention/_remote-ack/pending — list still-pending durable remote-acks (observability).
  • POST /attention/_remote-ack/drain — manually drain pending durable remote-acks to their owning machines.
  • POST /autonomous/register — server-side start snapshot for an autonomous run (scope-accretion R30): the server mints the runId, snapshots the scopeAccretion config + sweep base-root start-SHAs, and clamps endAt to now + maxDurationMs. One registration per active run (409 while the existing record is active).
  • POST /autonomous/:topic/run-end — every exit surface reports here (scope-accretion R44): runs the non-blocking advisory sweep and enumerates any unbuilt accreted work loudly; marks the run record ended.
  • POST /autonomous/:topic/ratify-deferral — dashboard-PIN-gated operator ratification of deferred accreted artifacts ({"artifacts": [...]} or {"all": true}; the response echoes exactly what was ratified).
  • POST /autonomous/:topic/scope-accretion-override — dashboard-PIN-gated live mid-run lever ({"enabled": false, "reason": "…"}): overrides the registration-time snapshot for the running session; audited.
  • GET /autonomy
  • GET /autonomy/elevation
  • GET /autonomy/elevation/acceptance
  • GET /autonomy/elevation/opportunities
  • GET /autonomy/evolution
  • GET /autonomy/evolution/notifications
  • GET /autonomy/history
  • GET /autonomy/summary
  • PATCH /autonomy/notifications
  • POST /autonomy/elevation/dismiss
  • POST /autonomy/elevation/dismiss-rubber-stamp
  • POST /autonomy/elevation/record
  • POST /autonomy/evolution/evaluate
  • POST /autonomy/evolution/notifications/drain
  • POST /autonomy/evolution/revert
  • POST /autonomy/evolution/sidecar
  • POST /autonomy/evolution/sidecar/apply
  • POST /autonomy/profile
  • GET /backups
  • POST /backups
  • POST /backups/:id/restore
  • POST /build/heartbeat
  • GET /capabilities
  • GET /capability-map
  • GET /capability-map/:domain
  • GET /capability-map/drift
  • POST /capability-map/refresh
  • GET /ci
  • GET /coherence/health
  • GET /coherence/proposals
  • POST /coherence/check
  • POST /coherence/proposals
  • POST /coherence/proposals/:id/approve
  • POST /coherence/proposals/:id/reject
  • POST /coherence/reflect
  • GET /commitments
  • GET /commitments/:id
  • GET /commitments/active-context
  • GET /commitments/context
  • PATCH /commitments/:id
  • POST /commitments
  • POST /commitments/:id/deliver
  • POST /commitments/:id/resume
  • POST /commitments/:id/withdraw
  • POST /commitments/verify
  • PATCH /config
  • POST /config/telemetry

Cutover-READINESS (coordination-mandate spec §7 G2.4, decision 1A): everything UP TO the cutover door, never the door. The two objective conditions resolve from REAL durable state — the persisted import IntegrityReport and the durable zero-divergence parity window (with a readiness-layer freshness bound). The flip itself is the operator’s manual click; there is no fire-cutover route by design.

  • GET /cutover-readiness{ ready, door: "manual-operator-click", integrity, parity, importDryRun } (read-only)
  • POST /cutover-readiness/parity-pass — trigger a server-side live parity check; the request contributes nothing to the result; a failed check records nothing
  • POST /cutover-readiness/import-dryrun — trigger a server-side import REHEARSAL (live source fetch → AS-IS import into an in-memory target → integrity gate over what the target reads back); zero durable data writes; persists to a separate dry-run report and never greens the canonical integrity condition
  • GET /cutover-readiness/import-dryrun — the last rehearsal’s verdict (read-only, informational — not a ready input)
  • GET /context
  • GET /context/:segmentId
  • GET /context/active-job
  • GET /context/dispatch
  • GET /context/working-memory
  • GET /decision-quality
  • POST /decision-quality/grade-pass
  • GET /benchmark-divergence
  • POST /benchmark-divergence/analyze
  • GET /benchmark-divergence/rollup-aggregates
  • GET /delivery-queue
  • GET /dispatches
  • GET /dispatches/applied
  • GET /dispatches/auto
  • GET /dispatches/context
  • GET /dispatches/pending
  • GET /dispatches/pending-approval
  • GET /dispatches/stats
  • POST /dispatches/:id/apply
  • POST /dispatches/:id/approve
  • POST /dispatches/:id/evaluate
  • POST /dispatches/:id/feedback
  • POST /dispatches/:id/reject
  • GET /episodes/recent
  • GET /episodes/sessions
  • GET /episodes/sessions/:sessionId
  • GET /episodes/sessions/:sessionId/activities
  • GET /episodes/stats
  • GET /episodes/themes/:theme
  • POST /episodes/scan
  • GET /events
  • POST /events/delivery-failed
  • GET /evolution
  • GET /evolution/actions
  • GET /evolution/actions/overdue
  • GET /evolution/gaps
  • GET /evolution/implicit
  • GET /evolution/learnings
  • GET /evolution/proposals
  • GET /evolution/traces
  • PATCH /evolution/actions/:id
  • PATCH /evolution/gaps/:id/address
  • PATCH /evolution/learnings/:id/apply
  • PATCH /evolution/proposals/:id
  • POST /evolution/actions
  • POST /evolution/gaps
  • POST /evolution/learnings
  • POST /evolution/proposals
  • DELETE /features/discovery-data
  • GET /features
  • GET /features/:id
  • GET /features/:id/consent-records
  • GET /features/analytics
  • GET /features/cooldowns
  • GET /features/digest
  • GET /features/evaluator-status
  • GET /features/events
  • GET /features/funnel
  • GET /features/summary
  • POST /features/:id/surface
  • POST /features/:id/transition
  • POST /features/evaluate-context
  • GET /feedback
  • POST /feedback
  • POST /feedback/retry
  • GET /flows/:flowId
  • GET /flows/waiting
  • POST /flows
  • POST /flows/:flowId/cancel-flow
  • POST /flows/:flowId/cancel-request
  • POST /flows/:flowId/fail
  • POST /flows/:flowId/finish
  • POST /flows/:flowId/mark-lost
  • POST /flows/:flowId/ping
  • POST /flows/:flowId/resume
  • POST /flows/:flowId/start-step
  • POST /flows/:flowId/wait
  • GET /git/log
  • GET /git/status
  • POST /git/commit
  • POST /git/pull
  • POST /git/push
  • GET /health
  • GET /health/coherence
  • GET /health/degradations
  • GET /health/probes
  • POST /health/coherence/check
  • POST /health/degradations/mark-reported
  • GET /homeostasis/check
  • POST /homeostasis/commit
  • POST /homeostasis/pause
  • POST /homeostasis/reset
  • PUT /homeostasis/thresholds
  • GET /hooks/events/:sessionId
  • GET /hooks/events/:sessionId/summary
  • GET /hooks/instructions/:sessionId
  • GET /hooks/plan-prompt/status
  • GET /hooks/sessions
  • GET /hooks/subagents/:sessionId
  • GET /hooks/worktrees
  • GET /hooks/worktrees/last-report
  • POST /hooks/events
  • POST /hooks/plan-prompt
  • POST /hooks/plan-prompt/resolve
  • GET /identity
  • GET /identity/soul
  • GET /identity/soul/drift
  • GET /identity/soul/integrity
  • GET /identity/soul/pending
  • PATCH /identity/soul
  • POST /identity/soul/pending/:id/approve
  • POST /identity/soul/pending/:id/reject
  • GET /imessage/chats
  • GET /imessage/chats/:chatId/history
  • GET /imessage/log-stats
  • GET /imessage/search
  • GET /imessage/status
  • POST /imessage/reply/:recipient
  • POST /imessage/validate-send/:recipient
  • DELETE /initiatives/:id
  • GET /initiatives
  • GET /initiatives/:id
  • GET /initiatives/digest
  • PATCH /initiatives/:id
  • POST /initiatives
  • POST /initiatives/:id/phase/:phaseId
  • GET /intent/alignment
  • GET /intent/drift
  • GET /intent/journal
  • GET /intent/journal/stats
  • GET /intent/org
  • GET /intent/validate
  • POST /intent/journal
  • GET /internal/stop-gate/annotations/:eventId
  • GET /internal/stop-gate/hot-path
  • GET /internal/stop-gate/kill-switch
  • GET /internal/stop-gate/log
  • POST /internal/compaction-resume
  • POST /internal/prompt-recall
  • POST /internal/slack-forward
  • POST /internal/stop-gate/annotations
  • POST /internal/stop-gate/evaluate
  • POST /internal/stop-gate/kill-switch
  • POST /internal/stop-gate/mode
  • POST /internal/stop-gate/reset-breaker — clear the authenticated authority breaker after provider repair.
  • POST /internal/telegram-callback
  • POST /internal/telegram-forward
  • GET /jobs
  • GET /jobs/:slug/history
  • GET /jobs/:slug/unfork-backups
  • GET /jobs/categories
  • GET /jobs/category-report/:category
  • GET /jobs/events
  • GET /jobs/history
  • GET /jobs/migration-status
  • GET /jobs/reconcile
  • PATCH /jobs/:slug
  • POST /jobs/:slug/disable
  • POST /jobs/:slug/enable
  • POST /jobs/:slug/override
  • POST /jobs/:slug/reset-state
  • POST /jobs/:slug/run
  • POST /jobs/:slug/save
  • POST /jobs/:slug/trigger
  • POST /jobs/:slug/unfork
  • POST /jobs/migration-abandon
  • POST /jobs/migration-confirm
  • GET /listener/health
  • GET /listener/metrics
  • POST /listener/restart

Coordination Mandate (spec: coordination-mandate.md): a deny-by-default authority gate for autonomous agent-to-agent actions. The operator’s bounded, expiring, revocable mandate — issued from the dashboard behind their PIN — is the authorizer, never the agent. With no mandate issued, every evaluation denies. Every decision (allow AND deny) lands in a hash-chained, tamper-evident audit.

  • POST /mandate/evaluate — check an intended action { action, params, agentFp, mandateId }{ decision, reason }
  • GET /mandate — list mandates (each with live authorshipValid)
  • GET /mandate/:id — one mandate + verification status
  • GET /mandate/audit — the chained audit (chain.ok:false = tampering)
  • POST /mandate/issue — PIN-GATED (operator only; Bearer alone is refused)
  • POST /mandate/:id/revoke — PIN-GATED (the operator kill switch)
  • GET /memory/entities/by-evidence
  • GET /memory/evidence/by-entity/:id
  • GET /memory/search
  • GET /memory/stats
  • POST /memory/reindex
  • POST /memory/sync
  • DELETE /messages/outbound/:machineId/:messageId
  • GET /messages/:id
  • GET /messages/agents
  • GET /messages/dead-letter
  • GET /messages/inbox
  • GET /messages/outbound
  • GET /messages/outbox
  • GET /messages/route-score
  • GET /messages/spawn/config
  • GET /messages/stats
  • GET /messages/summaries
  • GET /messages/thread/:threadId
  • GET /messages/threads
  • PATCH /messages/spawn/config
  • POST /messages/ack
  • POST /messages/relay-agent
  • POST /messages/send
  • POST /messages/spawn-request
  • POST /messages/thread/:threadId/resolve
  • GET /messaging/bridge
  • GET /monitoring/memory
  • GET /monitoring/processes
  • GET /monitoring/processes/last
  • GET /monitoring/telemetry
  • PATCH /monitoring/memory/thresholds
  • POST /monitoring/processes/kill
  • POST /monitoring/processes/kill-all-external
  • GET /operations/log
  • GET /operations/permissions/:service
  • POST /operations/classify
  • POST /operations/evaluate
  • DELETE /pastes/:id
  • GET /pastes
  • GET /pastes/:id
  • POST /pastes
  • GET /ping
  • GET /pool — the machine pool: router, nicknames, hardware, online status, load, quota state
  • GET /pool/placement — which machine owns a topic + the reason (pinned/placed/unowned) + the U4.1 verified pin state (pinState: actuated/pending/diverged/suspended-pending-owner-return, pinHeldSince, pendingReason, pinnedBy)
  • POST /pool/transfer — deterministic topic move to a nickname/machineId (the validated planner)
  • POST /pool/unpin — deliberately clear a topic’s placement pin; the clear replicates as a tombstone so a stale copy can never re-pin it (U4.1)
  • GET /pool/pin-quarantine — the sticky skew-quarantine set (clock-skewed pin records excluded from pin resolution) + fold status (503 when pin replication is dark)
  • POST /pool/pin-quarantine/readmit — the deliberate, explicit per-record re-admission of a quarantined pin record (dismissing the alert never re-admits)
  • GET /pool/queue — durable inbound-queue counts, tenure start, dry-run shadow-custody evidence, explicit durability-detection posture, and hold/flap state (503 while dark)
  • GET /pool/reconciler — WS1.3 ownership reconciler status (+ ?topic=N per-topic explain)
  • GET /pool/stale-owner-release — U4.2 stale-owner release telemetry: attempts, would-claims (dry-run), refusals by reason, evidence classes, P19 give-ups, probe-breaker state, open episodes (503 when dark; see Multi-machine)
  • GET /pool/lease-handback — U4.4 lease hand-back reconciler status: state, hysteresis window, operator-latch visibility, last episode, counters (503 when the mesh is dark)
  • POST /pool/lease-handback/latch — write the operator-flip latch marker (the captain-flip playbook’s POST step; suppresses automated hand-back — the human always wins)
  • DELETE /pool/lease-handback/latch — clear the latch early (PIN-gated: re-enables automation against a human decision, so the dashboard PIN is required)
  • GET /pool/poll-cache — the shared per-peer pool-scope poll cache (WS4.4(f))
  • GET /pool/duplicate-reconciler — ownership-gated-spawn unified status: duplicate-reconciler posture + substrate readiness, owner-dark notice episodes, spawn-admission counters, breaker state, audit-log locations (503 while dark; see Ownership-Gated Spawn)
  • GET /pool/ownership-view?key=<topic> — THIS machine’s own ownership record for a conversation (proxy-free; the reconciler’s peer-echo verification read)
  • GET /judgment-provenance — redacted judgment-provenance decision rows (?limit=, ?sinceHours=, ?scope=pool merges peers’ redacted rows as clamped untrusted data; full context never leaves the deciding machine)
  • GET /project-map
  • POST /project-map/refresh
  • DELETE /projects/:id
  • GET /projects
  • GET /projects/:id
  • GET /projects/:id/next
  • POST /projects
  • POST /projects/:id/abandon
  • POST /projects/:id/accept-partial
  • POST /projects/:id/ack
  • POST /projects/:id/advance
  • POST /projects/:id/claim-ownership
  • POST /projects/:id/drift-check
  • POST /projects/:id/halt
  • POST /projects/:id/resume
  • POST /projects/:id/run-round
  • POST /projects/validate
  • GET /prompt-gate/log
  • GET /prompt-gate/status
  • GET /prompt-gate/topic/:topicId/override
  • PUT /prompt-gate/topic/:topicId/override
  • GET /providers/cost-state/diff
  • GET /providers/framework-router/route
  • GET /providers/routing/decide
  • POST /publish
  • PUT /publish/:path
  • GET /published
  • GET /quota
  • GET /quota/migration
  • GET /quota/polling
  • POST /quota/migration/trigger
  • GET /reflection/metrics
  • POST /reflection/record
  • POST /reflection/session-start
  • PUT /reflection/thresholds
  • DELETE /relationships/:id
  • GET /relationships
  • GET /relationships/:id
  • GET /relationships/:id/context
  • GET /relationships/stale
  • POST /relationships/import
  • DELETE /review/history
  • GET /review/health
  • GET /review/history
  • GET /review/stats
  • POST /review/canary
  • POST /review/evaluate
  • POST /review/test

/routing-spend (money-layer enable surface)

Section titled “/routing-spend (money-layer enable surface)”

The six PRE-GATE routes of the money-layer operator enable surface (docs/specs/money-layer-operator-enable-surface.md). Unlike every other /routing-spend/* route, these answer 200 while the money layer is OFF — they are the door to turning it on, and a surface only reachable once the thing it enables is already enabled would be a switch inside the locked room. Served by MoneyLayerEnableSurface, backed by MoneyLayerEnableStore (the durable operator flag + failure record) and MoneyLayerAuditLog (two channels distinguished by interface, sharing one JSONL).

  • GET /routing-spend/enable-status — Bearer. { lifecycleState, enforcementReady, enableSources, configSnapshotAt, machineId, lastTransitionAt, failingComponent?, settlingCount, restartEligible, anyKeyFrozen, freezeRecordProvisional }. Genuinely read-only: no audit append, no nonce mint, no observed-state update. Cache-Control: no-store.
  • POST /routing-spend/plan-money-layer — Bearer. { action }money-layer-enable · money-layer-mirror-config · money-layer-disable · money-layer-disable-store-only. Returns { planId, nonce, renderedText, action, sourceStateAtRender, machineId, machineNickname, expiresAt }. Requires the single-instance lock. 400 for an action outside the enum (syntax); 409 without the lock or with nothing to mirror.
  • POST /routing-spend/money-layer/commit — Bearer + PIN. { pin, planId, nonce }{ lifecycleState, enforcementReady, enableSources, storeCleared, probe, message }. The action is read from the STORED plan and refused unless it is on the pre-gate allowlist. 401 bad PIN · 409 unknown/expired/consumed plan, wrong machine, source-state drift, or lock not held · 429 PIN lockout.
  • POST /routing-spend/money-layer/restart-nonce — Bearer. {}{ nonce, expiresAt, confirmationText }. 409 outside the three restartable states.
  • POST /routing-spend/money-layer/restart — Bearer + PIN. { pin, nonce, confirmationTextHash, force? }. Uses the server’s existing supervised-restart path; the restart-requested audit row is flushed BEFORE the handoff, and a failed flush returns 503 with the restart NOT initiated. 409 stale nonce / hash mismatch / wrong state / money still settling · 429 cooldown (durable across the restart it authorizes).
  • POST /routing-spend/config-inspect — Bearer; + PIN for the limit values. { pin? }{ differs, configSnapshotAt, fields, note }. Non-adopting: it mutates no authority, config or process state. There is deliberately no route that adopts on-disk config into the running process.

GET /routing-spend/caps/log is likewise reachable in every state, but a pre-gate reader sees only enable/disable/status rows plus redacted freeze reasons.

ReviewExchange (coordination-mandate spec §7 G2.3): one mutual, mandate-gated sign-off of a review artifact between the two agents named in a mandate. Both sign-offs run through the mandate gate’s sign-code-review authority; every accepted signature carries the audit hash of the gate decision that authorized it. Linear lifecycle: proposed → delivered → verdict-recorded → complete (or changes-requested, terminal). Deny-by-default inherited: no mandate → 403.

  • POST /review-exchange — create { mandateId, artifact, packageRef, packageSha256, parties:[ownerFp,peerFp] } (content-addressed)
  • GET /review-exchange — list exchanges
  • GET /review-exchange/:id — one exchange + signatures with audit hashes
  • POST /review-exchange/:id/delivered — record the Threadline delivery evidence
  • POST /review-exchange/:id/peer-verdict — the peer’s authenticated verdict; approve is their sign-off → mandate-gated (deny → 403)
  • POST /review-exchange/:id/sign — the owner’s countersignature → mandate-gated; completes the exchange
  • GET /scope-coherence
  • GET /scope-coherence/check
  • POST /scope-coherence/record
  • POST /scope-coherence/reset
  • DELETE /secrets/pending/:token
  • GET /secrets/drop/:token
  • GET /secrets/pending
  • POST /secrets/drop/:token
  • POST /secrets/request
  • POST /secrets/retrieve/:token
  • GET /self-knowledge/health
  • GET /self-knowledge/search
  • GET /self-knowledge/session-context — the boot self-knowledge block: vault secret NAMES (never values) + operational facts; ?full=1 bypasses display caps. Dark on the fleet (enabled ?? developmentAgent).
  • GET /self-knowledge/tree
  • GET /self-knowledge/validate
  • POST /self-knowledge/facts — append a durable operational fact (auto-stamped with date + machine)
  • DELETE /self-knowledge/facts — remove a fact by {match} or {index, expect}
  • DELETE /semantic/forget/:id
  • GET /semantic/context
  • GET /semantic/explore/:id
  • GET /semantic/export
  • GET /semantic/recall/:id
  • GET /semantic/search
  • GET /semantic/search/hybrid
  • GET /semantic/stale
  • GET /semantic/stats
  • POST /semantic/connect
  • POST /semantic/decay
  • POST /semantic/embeddings/migrate
  • POST /semantic/export-memory
  • POST /semantic/import
  • POST /semantic/migrate
  • POST /semantic/migrate/canonical-state
  • POST /semantic/migrate/decisions
  • POST /semantic/migrate/memory-md
  • POST /semantic/migrate/relationships
  • POST /semantic/rebuild
  • POST /semantic/remember
  • POST /semantic/snapshot
  • POST /semantic/supersede
  • POST /semantic/verify/:id
  • GET /sentinel/stats
  • POST /sentinel/classify
  • GET /serendipity/findings
  • GET /serendipity/stats
  • GET /session/context/:topicId
  • DELETE /sessions/:id
  • GET /sessions
  • GET /sessions/:name/output
  • GET /sessions/reaper — this machine’s live pressure and per-session reaper verdicts; ?scope=pool adds peer snapshots plus classified peer failures while preserving the local snapshot at the top level
  • GET /sessions/reaper/audit — the bounded decision-audit tail; ?includePage=1 adds local returned/truncated metadata, while ?scope=pool merges machine-tagged entries, lists that metadata per machine in pool.sources, and distinguishes a failed peer read from a genuinely empty trail
  • GET /sessions/reap-log — the bounded history of completed and refused shutoffs; ?includePage=1 adds local returned/truncated metadata, while ?scope=pool merges all answering machines chronologically, lists each bounded source in pool.sources, and classifies peer failures
  • GET /sessions/tmux
  • POST /sessions/:name/input
  • POST /sessions/:name/remote-close
  • POST /sessions/cleanup-stale
  • POST /sessions/create
  • POST /sessions/refresh
  • GET /sessions/resume-queue
  • POST /sessions/resume-queue/:id/cancel
  • POST /sessions/resume-queue/:id/requeue
  • POST /sessions/resume-queue/drain
  • POST /sessions/resume-queue/resume
  • POST /sessions/spawn
  • GET /shared-state/chain/:id
  • GET /shared-state/recent
  • GET /shared-state/render
  • GET /shared-state/sessions
  • GET /shared-state/stats
  • POST /shared-state/append
  • POST /shared-state/resolve/:id
  • POST /shared-state/session-bind
  • POST /shared-state/session-bind-confirm
  • POST /shared-state/session-bind-interactive
  • POST /shared-state/session-bind-rotate
  • POST /shared-state/sessions/:sid/revoke
  • GET /skip-ledger
  • GET /skip-ledger/workloads
  • POST /skip-ledger/workload
  • GET /slack/channels
  • GET /slack/channels/:channelId/messages
  • GET /slack/log-stats
  • GET /slack/search
  • POST /slack/channels
  • POST /slack/reply/:channelId
  • GET /state/anti-patterns
  • GET /state/projects
  • GET /state/quick-facts
  • GET /state/summary
  • GET /state/sync
  • POST /state/anti-patterns
  • POST /state/heartbeat
  • POST /state/projects
  • POST /state/quick-facts
  • POST /state/submit
  • GET /status
  • GET /system-review
  • GET /system-reviews/history
  • GET /system-reviews/latest
  • GET /system-reviews/trend
  • POST /system-reviews
  • GET /systems/capability/:id
  • GET /systems/status
  • GET /telegram/log-stats
  • GET /telegram/search
  • GET /telegram/topics
  • GET /telegram/topics/:topicId/messages
  • POST /telegram/dashboard-refresh
  • POST /telegram/post-update
  • POST /telegram/reply/:topicId
  • POST /telegram/topics
  • GET /telemetry/status
  • GET /telemetry/submissions
  • GET /telemetry/submissions/latest
  • POST /telemetry/disable
  • POST /telemetry/enable
  • GET /threadline/observability/search
  • GET /threadline/observability/threads
  • GET /threadline/observability/threads/:threadId
  • GET /threadline/status
  • GET /threadline/telegram-bridge/config
  • PATCH /threadline/telegram-bridge/config
  • POST /threadline/relay-discover
  • POST /threadline/relay-send
  • GET /tokens/by-project
  • GET /tokens/orphans
  • GET /tokens/sessions
  • GET /tokens/summary
  • GET /topic/context/:topicId
  • GET /topic/list
  • GET /topic/search
  • GET /topic/stats
  • POST /topic/rebuild
  • POST /topic/summarize
  • POST /topic/summary
  • GET /topic-bindings
  • POST /topic-bindings

Verified per-topic operator binding (Know Your Principal). The operator is established ONLY from the authenticated sender uid — a content name can never become the operator. See Know Your Principal.

  • POST /topic-operator — bind a topic operator from the AUTHENTICATED sender { topicId, platform?, uid (required), displayName? }; a blank uid is refused 400
  • GET /topic-operator — all bound operators (names + uids)
  • GET /topic-operator/:topicId — one topic’s verified operator (or null when unbound)
  • GET /topic-operator/session-context?topicId=N — the <topic-operator> session-start injection block ({ present:false } when unbound)
  • GET /triage/history
  • GET /triage/status
  • POST /triage/trigger
  • GET /trust
  • GET /trust/changelog
  • GET /trust/elevations
  • GET /trust/summary
  • POST /trust/grant
  • GET /tunnel
  • GET /updates
  • GET /updates/auto
  • GET /updates/config
  • GET /updates/last
  • GET /updates/status
  • PATCH /updates/config
  • POST /updates/apply
  • POST /updates/rollback
  • DELETE /view/:id
  • GET /view/:id
  • POST /view
  • POST /view/:id/unlock
  • PUT /view/:id

Multi-account subscription registry + per-account quota (the Subscription & Auth Standard). The registry stores each account’s login location (its config home), never tokens. These routes are operator/internal and ship dark — they do nothing until accounts are enrolled, and are not surfaced in /capabilities until the standard’s later phases (scheduler + enrollment wizard) make them user-usable.

MethodPathDescription
GET/subscription-poolList enrolled accounts (nickname, provider, framework, config home, status, last quota)
POST/subscription-poolAdd an account. Body: id, nickname, provider, framework, configHome
GET/subscription-pool/:idGet one account
PATCH/subscription-pool/:idUpdate mutable fields (nickname, framework, configHome, status)
DELETE/subscription-pool/:idRemove an account
POST/subscription-pool/pollPoll every account’s live quota now (writes each account’s lastQuota)
GET/subscription-pool/:id/quotaRead an account’s latest quota snapshot + measured burn rate
POST/subscription-pool/swapResume a session on another eligible account (continuity guarantee — never dies on a quota limit). Body: sessionName, exhaustedAccountId
GET/subscription-pool/proactive-swapPre-limit swap monitor status — thresholdPct, watchPct, maxSwapsPerCycle, cooldownMs, running, lastResult. 200 { enabled:false } when the monitor is dark.
POST/subscription-pool/proactive-swap/checkRun one proactive pass now (refresh the poll if near the wall, then pre-emptively swap at-pressure sessions). The deterministic “show me it works” lever.
POST/subscription-pool/enrollStart a mobile-first new-account login. Body: id, label, provider, framework, optional kind, configHome. Returns the pending login (public code/URL + TTL — never a token).
GET/subscription-pool/pending-loginsThe “Pending Logins” surface — active logins awaiting approval (code/URL + TTL).
POST/subscription-pool/enroll/:id/cancelSafely abandon a pending or expired login and best-effort stop its waiting login pane. Completed/already-abandoned logins return idempotently; an in-flight completion returns 409.
POST/subscription-pool/enroll/:id/completeMark a login completed once the operator approved + the account enrolled.
POST/subscription-pool/enroll/reissue-expiredSweep + auto-reissue every expired login with a fresh code/URL (the background tick calls the same path).
GET/subscription-pool/in-useWhich pooled accounts are currently serving a live session.

Account follow-me / account×machine matrix (WS5.2)

Section titled “Account follow-me / account×machine matrix (WS5.2)”

Cross-machine account setup from the dashboard’s Subscriptions-tab grid. Dark behind multiMachine.accountFollowMe. Each machine re-mints its OWN login (no token is copied between machines).

MethodPathDescription
POST/subscription-pool/matrix/start-cellPIN-gated orchestrator: the grid’s “Set up” tap. Issues the per-(account, targetMachine) account-follow-me mandate, then drives the enroll/start chain (self → loopback; peer → deliver the signed mandate + remote enroll). Body: accountId, machineId, pin.
POST/subscription-pool/follow-me/enroll/startMandate-gated: re-mint the login on THIS target machine (Mechanism B). Spawns the waiting claude auth login pane + records a pending login. Body: mandateId, accountId.
POST/subscription-pool/follow-me/enroll/:id/submit-codeTarget-local: type the operator’s verification code into the waiting login pane, then drive to a real outcome (S7 email-gate complete → add to pool).
POST/subscription-pool/follow-me/submit-codeFronting relay for the above — the operator’s single dashboard hop; self → loopback, peer → forward. Body: machineId, id, code.
POST/subscription-pool/follow-me/enroll/:id/cancelTarget-local: cancel a mis-tapped in-flight cell — abandon the pending login + tear down its login pane (raw tmux kill-session). Idempotent on a terminal record (200 alreadyTerminal); unknown/malformed id → 404; stands aside (409) while a code is mid-submit. Bearer-only.
POST/subscription-pool/follow-me/cancelFronting relay for cancel — dispatches to self/peer by machineId (offline peer → 502). The route the dashboard Cancel button calls. Body: machineId, id.
POST/subscription-pool/follow-me/enroll/:id/completeMark a follow-me login completed once the freshly-minted account passes the S7 email-gate.
GET/subscription-reloginList bounded assisted re-login episodes and their current state. Returns disabled state while the dev-gated feature is dark.
GET/subscription-relogin/:episodeId/eventsRead the bounded, redacted event history for one repair episode.
POST/subscription-relogin/:episodeId/approveApprove the exact immutable repair plan shown in the dashboard. Approval cannot broaden identity, origin, or requested scope.
POST/subscription-relogin/:episodeId/cancelCancel an active repair episode. Cancellation is durable and checked again before every side effect.
POST/subscription-relogin/:episodeId/retryRetry an eligible failed episode within its durable attempt, reissue, and wall-clock budgets. Uncertain non-idempotent outcomes remain operator-only.

Window lifecycle obligation ledger (Echo-local)

Section titled “Window lifecycle obligation ledger (Echo-local)”

The enforcement plane behind governance windows (core/WindowLifecycleObligationLedger): duties compiled from source documents, evidence-gated admission/closure, per-duty executor-liveness, maturation-gated enforcement. Echo-local by design — every route refuses a foreign agent/scope before state access. See the Window Lifecycle Obligation Ledger feature page.

MethodRouteDescription
GET/window-lifecycleLedger status: compiled obligations, per-instance statuses, lifecycle state, executor bindings.
POST/window-lifecycle/compileCompile the obligation ledger from the current source-document bytes (SHA-recorded, source-spanned; uncompiled operative clauses fail).
POST/window-lifecycle/evidenceSubmit instance-bound evidence for a duty (nonce-bound; wrong-window or replayed evidence rejected).
POST/window-lifecycle/evaluateEvaluate duty predicates and executor-liveness without mutating state.
POST/window-lifecycle/tickRun one lifecycle tick — re-query evidence and executors, surface open-unexecuted findings.
POST/window-lifecycle/transitionRequest a lifecycle state transition; refused while any gating duty lacks evidence.
POST/window-lifecycle/native-admissionRun the shipped between-window admission gate through the versioned adapter; exact input/output persisted, structural verdict never promoted to semantic proof.
POST/window-lifecycle/waiverApply an operator waiver — exact payload digest approved post-creation by the locally auth-bound operator; core duties non-waivable.
POST/window-lifecycle/rollbackAudited Echo-local rollback: ledger preserved read-only, manual ritual resumes, enforcement reported disabled.
POST/window-lifecycle/reenableRe-enable after rollback; requires repair evidence and a passing dry-run suite.
GET/window-lifecycle/enforcementEnforcement mode (off / dry-run / enforced) + maturation state.
POST/window-lifecycle/enforcement/record-shadowServer-derived graduation report from the stored ledger and adjudicated shadow audit (dry-run only; unadjudicated or hash-chain-broken rows refuse).
POST/window-lifecycle/enforcement/graduateGraduate dry-run → enforced on valid dual-lifecycle evidence; forged, reused, or caller-written provenance refused.
POST/window-lifecycle/enforcement/offTurn the enforcement plane off (neither ticks nor blocks).
MethodRouteDescription
POST/playwright-profiles/provisionRecent-dashboard-PIN route that creates a jailed, machine-local Chrome profile for one Google identity. The request accepts vault secret names, never secret values, and returns a phone-complete next step when password or MFA help is needed.

The quota-aware scheduler picks accounts reset-date-optimally (“use before reset”) and guarantees a long-lived session that hits its account’s quota resumes on another account (via claude --resume, which is account-agnostic, so the conversation is preserved) rather than dying. There are two automatic swap triggers, both dark by default in .instar/config.json: the reactive swap (subscriptionPool.autoSwapOnRateLimit) fires AFTER a rate-limit escalation, and the proactive pre-limit swap (subscriptionPool.proactiveSwap.enabled) moves a session OFF an account BEFORE it walls, at a lag-aware measured thresholdPct (default 80 — below the real limit because the polled reading trails real usage). The proactive monitor resolves an UNTAGGED session’s effective account from the default-config login, so the primary interactive session is swap-visible instead of wedging at the wall. The /subscription-pool/swap route is the manual lever; /subscription-pool/proactive-swap/check runs one proactive pass on demand.

These routes are backed by three core classes: SubscriptionPool (the durable account registry — login location only, never tokens), QuotaPoller (the background poller that measures each account’s live burn + reset windows), and QuotaAwareScheduler (reset-date-optimal account selection + the swap continuity guarantee). The swap itself drives SessionRefresh with an account-swap option so the resumed session launches under the new account’s CLAUDE_CONFIG_DIR.

The enrollment routes are backed by PendingLoginStore (a durable ledger of in-flight logins — public code/URL/TTL only, never a token), EnrollmentWizard (start a login + auto-reissue expired codes on a background sweep), and FrameworkLoginDriver (spawns the framework’s own login under the new account’s CLAUDE_CONFIG_DIR and scrapes the public code/URL). Enrollment ships dark — the routes answer 200 { enabled:false } until the wizard is wired.

Examples:

Terminal window
# List accounts and add one (login location only — never tokens)
curl -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool
curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool \
-d '{"id":"claude-personal","nickname":"personal","provider":"anthropic","framework":"claude-code","configHome":"~/.claude-personal"}'
# Inspect, update, remove a specific account
curl -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/claude-personal
curl -X PATCH -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/claude-personal -d '{"nickname":"personal-max"}'
curl -X DELETE -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/claude-personal
# Refresh live quota for all accounts, then read one account's snapshot + burn rate
curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/poll
curl -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/claude-personal/quota
# Manually swap a session off a quota-exhausted account (continuity preserved)
curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/swap \
-d '{"sessionName":"my-session","exhaustedAccountId":"claude-personal"}'
# Proactive pre-limit swap: check status, then run one pass on demand
curl -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/proactive-swap
curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:4040/subscription-pool/proactive-swap/check
  • GET /views
  • GET /watchdog/status
  • POST /watchdog/toggle
  • GET /whatsapp/qr
  • GET /whatsapp/status
  • POST /whatsapp/send/:jid

The Slack org permission gate (dark/observe-only by default — these routes are operator/internal, not surfaced in /capabilities until the enforce path is enabled in a later phase).

  • GET /permissions/decisions — recent permission-gate verdicts from the observe ledger (operator review).
  • GET /permissions/scenario-suite — the worked-example verdict suite (deploy-allow, junior-deny, ambiguous-clarify, social-engineering-deny, compromised-CEO step-up) with expected vs actual verdicts.
  • GET /permissions/registrations/pending — list pending self-registration requests awaiting admin approval.
  • POST /permissions/registrations/register — admin registers a Slack user with an org role ({ slackUserId, displayName, role }).
  • POST /permissions/registrations/approve — approve a pending registration ({ slackUserId, role }).
  • POST /permissions/registrations/deny — deny/drop a pending registration ({ slackUserId }).
  • GET /whoami

The unified work-intake and prioritization registry (WorkQueue — see the Work Intake & Prioritization Queue feature page). Development-agent gated; 503 when dark.

  • GET /work-queue — the current deterministic ranked list of normalized work items.
  • POST /work-queue/rescore — recompute the ranking from live sources (pure compute, no durable writes).