Last updated: 2026-04-26
This file is the route-level contract for OrbitDock's Rust server.
It is intentionally boring:
- HTTP owns bootstrap reads, pagination, settings/config reads, uploads, and mutation responses.
- WebSocket owns realtime deltas, replay, heartbeats, and explicit refetch hints.
- Clients should apply authoritative HTTP mutation responses immediately, then let WebSocket reconcile.
This doc was rewritten against the real router in:
orbitdock-server/crates/server/src/transport/http/router.rsorbitdock-server/crates/server/src/transport/http/*OrbitDockNative/OrbitDock/Services/Server/API/*
- Use REST for all initial reads and all heavy payloads.
- Use
GET /wsonly after bootstrapping the surface over HTTP. - Treat WebSocket invalidations as refetch hints, not as a second bootstrap path.
- Successful mutations often include an authoritative snapshot. Apply that snapshot immediately.
Everything except GET /health requires the normal OrbitDock bearer token:
Authorization: Bearer <token>Workspace sync uses the same header name but a different token class. POST /api/sync expects a workspace sync token, not the normal app token.
{
"code": "string_code",
"error": "human readable message"
}Used by many fire-and-forget session mutations.
{
"accepted": true,
"session_detail_snapshot": {
"revision": 123,
"session": { "...": "..." }
}
}session_detail_snapshot is optional. When present, it is authoritative and should be applied immediately.
Used by POST /api/sessions/{session_id}/conversation/messages.
{
"accepted": true,
"row": { "...ConversationRowEntry..." },
"session_detail_snapshot": { "...optional SessionDetailSnapshot..." }
}Used by POST /api/sessions/{session_id}/conversation/steer.
{
"accepted": true,
"row": { "...ConversationRowEntry..." },
"session_detail_snapshot": { "...optional SessionDetailSnapshot..." }
}Used by GET /api/sessions/{session_id}/detail and several session mutations.
Top-level fields:
revisionsession
session is the authoritative session shell for detail/control-deck style UI. It does not include the full conversation timeline.
Important control-deck fields:
work_status— display status only; do not use it as a proxy for individual actions.connector_attached— true when the live connector action channel is attached.accepts_user_input— true when a direct/open session can receive a new user turn through the attached connector.steerable— true when the current turn can receive steering feedback through the attached connector.can_interrupt— true only when the server knows an active turn can be interrupted through the attached connector.current_turn_id— current active turn identity, when one exists.
Used by GET /api/missions/{mission_id} and most mission mutations.
Top-level fields:
summaryissuescleanup_promptsettingsmission_file_existsmission_file_pathworkflow_migration_available
Returns:
{"status":"ok"}Returns Prometheus-style metrics text.
Internal Claude hook-forward ingestion endpoint.
- Not intended for normal UI clients.
- Accepts forwarded hook JSON with an injected
type. - Returns
200 OKwith an acknowledgement payload.
There is no GET /api/sessions list route.
Clients should use the explicit surface routes below:
Compact global session shell for quick switcher, menu bar, and attention UI.
Returns:
revisioncountsactive_sessionsrecent_sessions
Authoritative dashboard surface.
Returns:
revisionconversationscountsproject_groups
Authoritative library/archive surface.
Returns:
revisionsessionsnext_offsettotal_count
Returns the authoritative SessionDetailSnapshot.
Updates stored session config and returns the authoritative SessionDetailSnapshot.
This is the only session config mutation route. There is no separate PATCH /api/sessions/{session_id}/detail mutation alias.
Marks the session as read.
Returns:
{
"session_id": "od-...",
"unread_count": 0
}Conversation bootstrap surface.
Returns:
sessiontotal_row_counthas_more_beforeoldest_sequencenewest_sequence
session includes the first page of typed ConversationRowEntry values in rows.
Returns an older paged slice of conversation rows.
Searches conversation rows within a session.
Supported query params:
qfamilystatuskind
Returns aggregate conversation/session metrics used by detail/review surfaces.
Returns expanded content for a single row, such as tool input/output or diff content.
Returns the review surface bootstrap for a session.
Top-level fields include:
session_idrevisioncurrent_diffcumulative_diffturn_diffscomments
Creates a direct session.
Returns:
session_idsessionas aSessionSummary
Resumes a persisted session.
Returns:
session_idsessionas aSessionSummary- optional
session_detail_snapshot
Takes over a passive session.
Returns:
session_idaccepted- optional
session_detail_snapshot
Ends a session.
Returns AcceptedResponse.
Forks a session.
Returns:
source_session_idnew_session_idsessionas aSessionSummary
Creates a worktree, then forks into it.
Returns the fork payload plus:
worktree
Forks into an existing tracked worktree.
Returns the same fork payload as POST /lifecycle/fork.
Queues a user turn.
Returns 202 Accepted with SendMessageResponse.
Queues a steer message for the active turn.
Returns 202 Accepted with SteerTurnResponse.
Runs a Codex thread/shellCommand against the active session thread.
- This is a session-shell mutation, not the generic OrbitDock shell executor.
- It returns
202 AcceptedwithAcceptedResponse. - Progress and output arrive through the normal conversation websocket stream as Codex command-execution items.
- The command runs with Codex's
thread/shellCommandsemantics, which are unsandboxed and do not inherit the session sandbox policy.
Returns the normalized session control capability surface for the active provider.
Returns:
session_idprovidercontrols
controls includes:
shell_commandstop_active_turncompact_contextundo_last_turnrollback_turnsstop_targetrewind_to_message
Each control advertises:
supportedavailable- optional
target_kind - optional
max_count
This is the preferred bootstrap path for control availability. Clients should use it instead of inferring support from provider names.
Returns the normalized session runtime snapshot for the active provider.
Returns:
session_idprovidercontrolsinstructionscollaboration_modes
This is the preferred bootstrap path when the UI needs the session's control surface, prompt/instruction state, and collaboration preset catalog together.
Use the narrower routes when only one slice is needed:
GET /api/sessions/{session_id}/controlsGET /api/sessions/{session_id}/instructionsGET /api/sessions/{session_id}/collaboration-modes
Stops the active turn for the current provider.
Returns AcceptedResponse.
Requests context compaction using the current provider's native mechanism.
Returns AcceptedResponse.
Requests the provider's native "undo last turn" behavior.
Returns AcceptedResponse.
Requests rollback of the most recent N turns.
Request body:
{"num_turns": 2}Returns AcceptedResponse.
Stops a provider-specific execution target when supported.
Request body:
{"target_id":"task-..."}Returns AcceptedResponse.
If the current provider does not support targeted stop controls, the route returns 422 unsupported_control.
Rewinds to a provider-specific message boundary when supported.
Request body:
{"message_id":"msg-..."}Returns AcceptedResponse.
If the current provider does not support message-targeted rewind, the route returns 422 unsupported_control.
Uploads an image attachment.
- Request body is raw image bytes.
Content-Typeis required.- Query params:
display_namepixel_widthpixel_height
Returns:
{
"image": {
"input_type": "attachment",
"value": "attachment-...",
"mime_type": "image/png",
"display_name": "diagram.png"
}
}detail may be present on image references restored from Codex history (auto, low, high, or original).
Returns raw attachment bytes with the stored image content type.
Starts a shell command in the session context.
Returns:
{
"request_id": "shell-...",
"accepted": true
}Shell output streams over WebSocket.
Cancels an active shell request.
Returns AcceptedResponse with session_detail_snapshot omitted.
Sets or clears a custom session name.
Returns AcceptedResponse.
Sets or clears a custom session summary.
Returns AcceptedResponse.
Returns:
session_idapprovals
Deletes one approval row.
Returns:
{
"approval_id": 42,
"deleted": true
}Applies a tool approval decision.
Answers a question request.
Responds to a permission grant request.
All three routes return the same shape:
session_idrequest_idoutcomeactive_request_idapproval_version- optional
session_detail_snapshot
Returns:
session_idreview_revisioncomments
Creates a review comment.
Returns:
session_idreview_revisioncomment_idcommentdeletedok
Updates a review comment.
Returns the same review comment mutation payload as create.
Deletes a review comment.
Returns the same review comment mutation payload with:
comment: nulldeleted: true
These routes are still grouped under capabilities, but the intended client model is simple:
- use HTTP to read or mutate session support/config state
- use WebSocket only for follow-up deltas or refetch hints
Returns:
session_idsubagent_idtools
If the subagent transcript cannot be read, tools is empty.
Returns:
session_idsubagent_idrows
If the subagent transcript cannot be read, rows is empty.
Returns:
session_idproviderinstructions
For Claude, instructions can include merged claude_md.
Returns the live Codex collaboration preset catalog for the active session runtime.
Returns:
data
Each item can include:
name- optional
mode - optional
model - optional
reasoning_effort clears_reasoning_effort
For non-Codex sessions, this route returns an empty data array.
Query params:
- repeatable
cwd force_reload
Returns:
session_idskillsclaude_skill_nameserrors
Query params:
- repeatable
cwd
Returns plugin marketplace state for the session.
Installs a plugin.
Returns the install result from Codex App Server, including auth requirements when applicable.
Uninstalls a plugin.
Returns the uninstall result from Codex App Server.
Returns:
session_idtoolsresourcesresource_templatesauth_statuses
For Codex sessions this is backed by App Server mcpServerStatus/list with the lightweight toolsAndAuthOnly detail level so the UI can render server status without repeatedly fetching heavy resource payloads.
Refreshes MCP server state.
Returns AcceptedResponse with no detail snapshot.
Toggles a Claude MCP server.
This is currently Claude-specific. Codex MCP support is currently read/refresh-oriented through the shared inventory routes.
Returns AcceptedResponse with no detail snapshot.
Starts MCP auth flow for a server.
For Codex sessions this calls App Server mcpServer/oauth/login and returns:
acceptedauthorization_url
For Claude sessions this starts the provider auth flow and returns accepted with no authorization URL.
Clears MCP auth state for a server.
This is currently Claude-specific.
Returns AcceptedResponse with no detail snapshot.
Sets the Claude MCP server config payload.
This is currently Claude-specific.
Returns AcceptedResponse with no detail snapshot.
Applies Claude flag/settings payload.
Returns AcceptedResponse with no detail snapshot.
Returns the session permission rules view.
For Claude, this is derived from CLI/disk settings. For Codex, this reflects approval and sandbox policy state.
Adds a permission rule.
Removes a permission rule.
Both routes return:
{
"ok": true,
"session_detail_snapshot": { "...optional SessionDetailSnapshot..." }
}Returns the server meta payload used by the app shell.
Returns the active workspace provider:
{"workspace_provider":"local"}Updates the active workspace provider and returns the same shape.
Returns:
keyvalueconfiguredsecretsource
Writes one workspace-provider config value and returns the same config-value shape.
Runs a provider preflight test.
Returns:
okprovidermessage
Sets server primary/secondary role.
Returns:
{"is_primary":true}Stores a client primary-claim preference.
Returns AcceptedResponse with no detail snapshot.
Returns current update status payload.
Triggers an update check.
Starts the upgrade flow.
Returns the current update channel.
Sets the update channel and returns the same shape.
Returns the combined usage summary snapshot for direct OrbitDock sessions. Passive hook sessions are intentionally excluded so dashboard totals track sessions created and controlled by OrbitDock.
Summary buckets include both:
session_countfor backward compatibilitydistinct_session_countas the server-authored unique session count for that scope
Clients should prefer distinct_session_count for new UI.
Returns grouped usage entries for the requested time range.
Each entry includes:
keylabelcost_usdinput_tokensoutput_tokenscached_tokensturn_countsession_countdistinct_session_count
This is the narrow grouped read. Use it when a surface needs one filtered breakdown only.
Returns a composite usage snapshot for a single time scope without requiring the client to stitch several separate reads together.
Returns:
today_start_unixsummarytoday_provider_breakdowntoday_model_breakdownday_breakdown
This is a general REST resource, not a dashboard-specific endpoint. It exists so any client can fetch one authoritative usage overview snapshot for a given scope.
Returns the top session usage collection for the requested range.
Returns:
start_unixend_unixnext_offsettotal_countsessions
Each session item includes stable usage plus display metadata:
session_idproviderdisplay_namecontext_lineproject_nameproject_pathmodelstarted_atlast_activity_atcost_usdinput_tokensoutput_tokenscached_tokensturn_count
This is the preferred session-list surface for usage UIs. Clients should not infer top sessions by re-grouping lower-level summary buckets on their own.
Returns Codex-specific usage snapshot, including primary/secondary windows and the optional
rate_limit_reached_type reason reported by Codex.
Returns Claude-specific usage snapshot.
Returns available Codex models for the current server/runtime context.
Returns available Claude models for the current server/runtime context.
Returns Codex account/auth status.
Returns the inspected effective Codex config for a working directory.
Returns Codex config profiles, providers, effective values, and warnings for a cwd.
Returns raw user/project Codex config documents and warnings.
Writes Codex config values atomically.
Returns a write result that includes:
statusversionfile_path
Starts Codex login.
Cancels Codex login.
Logs out of Codex.
Runs git init in the provided path.
Returns:
{"ok":true}Returns:
pathentries
Returns:
projects
Workspace sync ingestion endpoint.
- Requires a workspace sync bearer token.
- Applies a
SyncBatchRequest. - Returns:
{
"acked_through": 42
}- Can return:
401 missing_bearer_token401 invalid_workspace_token401 workspace_not_found409 sync_sequence_conflict
Returns:
repo_rootworktree_revisionworktrees
Creates a tracked worktree and returns:
repo_rootworktree_revisionworktree
Discovers worktrees for a repo root and returns the same surface shape as GET /api/worktrees.
Removes or archives a worktree.
Query params:
forcedelete_branchdelete_remote_brancharchive_only
Returns:
repo_rootworktree_revisionworktree_iddeletedok
Returns:
missions
Creates a mission.
Returns one MissionSummary.
Returns MissionDetailResponse.
This is the authoritative mission detail bootstrap.
Updates mission metadata and returns MissionDetailResponse.
Deletes the mission and returns:
missions
Returns the mission issue list as an array of MissionIssueItem.
Retries/requeues an issue and returns MissionDetailResponse.
Applies an admin transition and returns MissionDetailResponse.
Marks an issue completed and returns MissionDetailResponse.
Stores a PR URL and returns MissionDetailResponse.
Creates a default MISSION.md and returns MissionDetailResponse.
Writes merged mission settings and returns MissionDetailResponse.
Starts the mission orchestrator.
Returns:
{"ok":true}Manually dispatches a tracker issue and returns MissionDetailResponse.
Triggers an immediate poll tick.
Returns:
{"ok":true}Returns:
{"worktrees":[...]}Returns:
{
"configured": true,
"source": "mission"
}Stores a mission-scoped tracker key and returns the same shape.
Deletes the mission-scoped tracker key and returns the same shape.
Copies the resolved global tracker key into mission scope and returns the same shape.
All three use:
{"configured":true}All three use:
{"configured":true}Returns:
lineargithub
Each provider entry contains:
configuredsource
Returns:
provider_strategyprimary_providersecondary_provider
Updates mission defaults and returns the same shape.
The client should:
- fetch the relevant HTTP surface first
- remember that surface revision
- subscribe over WebSocket with
since_revision - refetch the exact HTTP surface only when the socket reports a gap or invalidation
The server sends hello immediately after connect.
The handshake advertises:
server_version- compatibility info
- capabilities
Common client messages:
subscribe_sessions_summarysubscribe_active_sessionssubscribe_archived_sessionssubscribe_missionssubscribe_session_surfaceunsubscribe_session_surface
All subscription messages support since_revision.
sessions_summary_invalidatedactive_sessions_invalidatedarchived_sessions_invalidatedmissions_invalidatedmission_invalidatedconversation_rows_changedsession_deltaapproval_requestedapproval_decision_resultshell_startedshell_outputreview_comment_createdreview_comment_updatedreview_comment_deletedworktree_createdworktree_removedworktree_status_changed
- Do not treat WebSocket as a bootstrap transport.
- Do not assume invalidations contain enough state to rebuild a surface.
- Use HTTP for authoritative snapshots.
- Use WebSocket for deltas, replay, and explicit refetch signals only.