mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-14 11:19:42 +02:00
I corrected the toolbar location and documented the existing cron request and response fields, with checks for route, schema, and status coverage.
202 lines
10 KiB
Markdown
202 lines
10 KiB
Markdown
# HTTP API
|
|
|
|
Codeman's HTTP and SSE API is a **stable contract**. Everything the dashboard does goes
|
|
through it, so anything the dashboard can do, a script can do.
|
|
|
|
This page is the orientation. The complete specification, including every wait semantic and
|
|
the SSE catalogue, is
|
|
[`docs/api-reference.md`](https://github.com/Ark0N/Codeman/blob/master/docs/api-reference.md).
|
|
|
|
## What is stable
|
|
|
|
Covered by semantic versioning: endpoint paths under `/api/v1`, the response envelope,
|
|
`errorCode` values, and SSE event names.
|
|
|
|
Not covered, and free to change in a patch release: on-disk state files, internal modules,
|
|
and anything marked experimental. The full statement is in
|
|
[Versioning](Versioning).
|
|
|
|
`/api/v1/*` is a versioned alias of `/api/*`. Prefer the versioned form in anything you
|
|
intend to keep.
|
|
|
|
## The envelope
|
|
|
|
```json
|
|
{ "success": true, "data": { } }
|
|
```
|
|
|
|
```json
|
|
{ "success": false, "error": "human readable", "errorCode": "NOT_FOUND" }
|
|
```
|
|
|
|
A few legacy GET handlers return bare bodies rather than the envelope, so a robust client
|
|
reads `body.data ?? body`.
|
|
|
|
Branch on `errorCode`, which is stable. The HTTP status is reliable too:
|
|
|
|
| `errorCode` | HTTP | Meaning |
|
|
| ------------------ | ---- | ------------------------------------------------ |
|
|
| `INVALID_INPUT` | 400 | Malformed request or failed validation. |
|
|
| `UNAUTHORIZED` | 401 | Authentication required or failed. |
|
|
| `NOT_FOUND` | 404 | No such resource. |
|
|
| `SESSION_BUSY` | 409 | The session is busy. |
|
|
| `CONFLICT` | 409 | Conflicts with current state. |
|
|
| `ALREADY_EXISTS` | 409 | Resource already exists. |
|
|
| `OPERATION_FAILED` | 422 | Well formed, could not be completed. |
|
|
| `RATE_LIMITED` | 429 | Too many requests. |
|
|
| `INTERNAL_ERROR` | 500 | Unexpected server error. |
|
|
|
|
New error codes are non-breaking. Removing or renaming one is a major change.
|
|
|
|
**A `401` is the bare string `Unauthorized`, not the envelope.** Piping it into `jq` throws
|
|
a parse error rather than showing the failure, so check the status first.
|
|
|
|
## Authentication
|
|
|
|
With no password set, and the default loopback bind, there is none. With `CODEMAN_PASSWORD`
|
|
set, use HTTP Basic or the session cookie:
|
|
|
|
```bash
|
|
curl -s -u admin:"$CODEMAN_PASSWORD" "$API/api/sessions"
|
|
```
|
|
|
|
A **missing** `Origin` header is allowed, so curl and CLI tools work unchanged. A
|
|
present-but-foreign origin is rejected by the CSRF guard. On an HTTPS install with the
|
|
self-signed certificate, add `-k`.
|
|
|
|
## Endpoint map
|
|
|
|
Roughly 235 handlers across 26 route modules. By domain:
|
|
|
|
| Domain | Handlers | Covers |
|
|
| ------------------- | -------- | --------------------------------------------------- |
|
|
| System | 56 | Status, settings, digest, updates, tunnel. |
|
|
| Sessions | 34 | Create, input, terminal, wait, last response, kill. |
|
|
| Cases | 34 | Create, link, clone, remote and docker cases. |
|
|
| Files | 17 | Preview, edit, raw, attachments, path picker. |
|
|
| Orchestrator | 10 | Plans and phases. |
|
|
| Ralph | 9 | Loop control and configuration. |
|
|
| Cron | 9 | Jobs and run history. |
|
|
| Admin | 8 | Multi-user administration. |
|
|
| Plan | 8 | Plan orchestration. |
|
|
| Respawn | 7 | Respawn configuration and presets. |
|
|
| Webviews | 6 | Saved dashboards, plus the proxy. |
|
|
| Mux | 5 | tmux operations. |
|
|
| Custom model endpoints | 5 | Saved OpenAI-compatible endpoints, and applying one to a session. |
|
|
| Push | 4 | Web push subscriptions. |
|
|
| Read My Mind | 4 | Intent profiles and prediction. |
|
|
| Scheduled | 4 | The legacy scheduled-run concept. |
|
|
| Approvals | 4 | The inbox, answering, acknowledging. |
|
|
| Tab layout | 2 | Named tab groups per owner. |
|
|
| Teams, me, search, hooks, clipboard, telemetry, voice, ws | 1-2 each | |
|
|
|
|
Each route module documents its own endpoints in its file header.
|
|
|
|
## Cron jobs
|
|
|
|
Saved scheduled jobs are distinct from the legacy `/api/scheduled` loops. Their
|
|
versioned endpoints are:
|
|
|
|
| Method | Path | Purpose |
|
|
| --- | --- | --- |
|
|
| GET | `/api/v1/cron/jobs` | List jobs |
|
|
| POST | `/api/v1/cron/jobs` | Create a job |
|
|
| GET | `/api/v1/cron/jobs/:id` | Read a job |
|
|
| PUT | `/api/v1/cron/jobs/:id` | Update a job (partial body) |
|
|
| DELETE | `/api/v1/cron/jobs/:id` | Delete a job |
|
|
| PUT | `/api/v1/cron/jobs/:id/enabled` | Enable/disable with `{ enabled: boolean }` |
|
|
| POST | `/api/v1/cron/jobs/:id/run` | Run now, without changing the schedule |
|
|
| GET | `/api/v1/cron/jobs/:id/runs` | Read a job's run history |
|
|
| GET | `/api/v1/cron/runs` | Read all accessible run history |
|
|
|
|
Responses use the envelope above: job lists/history have arrays in `data`, a
|
|
single-job GET has the job itself, create/update/enable have `{ job }`, delete has
|
|
`{}`, and Run Now has `{ run, activeAgents }`. Prompt delivery is asynchronous;
|
|
`session_started` and `prompt_sent` describe launch/delivery, not task success.
|
|
|
|
The [cron API reference](https://github.com/Ark0N/Codeman/blob/master/docs/api-reference.md#cron-jobs)
|
|
lists all request and response fields, validation, and ownership restrictions.
|
|
[Creating a job](Cron-Jobs) covers the UI and schedule semantics.
|
|
|
|
## Long-polling instead of polling
|
|
|
|
Three calls block until something happens, so an agent driving Codeman from a shell can wait
|
|
rather than spin:
|
|
|
|
| Call | Blocks until |
|
|
| ----------------------------------------- | -------------------------------------------------------- |
|
|
| `GET /api/v1/sessions/:id/wait` | One of a set of lifecycle signals fires. |
|
|
| `GET /api/v1/sessions/:id/wait-output` | A literal string appears in the session's output. |
|
|
| `POST /api/v1/sessions/:id/input` + `wait`| The input is delivered **and then** a signal fires. |
|
|
|
|
Three semantics that break callers who assume otherwise:
|
|
|
|
1. **A timeout is `200`, not an error.** It answers with `wait.timedOut: true`. Loop over
|
|
short waits; a single long call gets cut by tunnels and proxies.
|
|
2. **Send-and-wait is not a POST followed by a wait.** It registers the waiter *before*
|
|
writing, which closes the window where a separate wait sees the session still idle from
|
|
the previous turn and answers instantly about the wrong turn.
|
|
3. **Signals are edge triggered with no history.** One that fires with no waiter registered
|
|
is unobservable afterwards. Fan-outs must register their waits as they dispatch.
|
|
|
|
`wait-output` matches a **literal substring, never a regex.** That is deliberate: no regex
|
|
means no catastrophic backtracking on attacker-influenced output.
|
|
|
|
Only `claude` and `deepseek` sessions emit `stop` and `blocked`: Claude's come from Claude
|
|
Code hooks, DeepSeek's from the harness reporting its state to Codeman. Shell and the other
|
|
external CLI sessions accept `idle`, `working`, and `exit`.
|
|
|
|
## SSE
|
|
|
|
`GET /api/events` is the live event stream. 158 event names, kept in sync between server and
|
|
client with a test that fails on drift.
|
|
|
|
The heartbeat is a **named** `sse:heartbeat` event rather than an SSE comment, because
|
|
comments are invisible to `EventSource` by specification and a client could not observe
|
|
them. That is what lets the browser detect a stream that has silently stopped delivering.
|
|
|
|
```js
|
|
const es = new EventSource('/api/events');
|
|
es.addEventListener('session:created', (e) => console.log(JSON.parse(e.data)));
|
|
```
|
|
|
|
## Quick examples
|
|
|
|
```bash
|
|
API="${CODEMAN_API_URL:-http://localhost:3000}"
|
|
|
|
curl -s "$API/api/status" | jq # whole-system snapshot
|
|
curl -s "$API/api/sessions" | jq '.data[].name' # live sessions
|
|
curl -s "$API/api/sessions/unified" | jq # live + historical, deduped
|
|
curl -s "$API/api/subagents" | jq # background agents
|
|
curl -s "$API/api/search?q=deploy" | jq # cross-session search
|
|
curl -s "$API/api/mcp-sync" | jq # preview MCP server sync (opt-in: 403 until mcpSyncEnabled is on)
|
|
curl -s -X POST "$API/api/mcp-sync" | jq # apply it: add missing servers to each CLI config, never edit/remove
|
|
|
|
# with ID set to a session id:
|
|
curl -s "$API/api/sessions/$ID/last-response" | jq -r '.data.text' # last answer, from the transcript (claude, codex, deepseek)
|
|
curl -s "$API/api/model-endpoints" | jq # saved custom OpenAI-compatible endpoints
|
|
curl -s -X POST "$API/api/sessions/$ID/custom-model" -H 'Content-Type: application/json' \
|
|
-d '{"endpointId":"local-llama","modelId":"qwen3-27b"}' | jq # restart the CLI on that endpoint; {"clear":true} undoes it
|
|
```
|
|
|
|
## Limits
|
|
|
|
| Limit | Default |
|
|
| --------------------- | ------------------------------------------ |
|
|
| Max sessions | 50 |
|
|
| Max agent windows | 500 |
|
|
| Max SSE clients | 100 |
|
|
| Terminal buffer | 32 MB per session |
|
|
| Text payload | 1 MB |
|
|
| Wait timeout ceiling | 600 s, and the response tells you what was applied |
|
|
|
|
Most are environment-overridable. See `src/config/`.
|
|
|
|
## Read next
|
|
|
|
- [Driving Codeman From An Agent](Driving-Codeman-From-An-Agent) - the practical version, with recipes.
|
|
- [Hooks And Integrations](Hooks-And-Integrations) - events flowing back into Codeman.
|
|
- [Versioning](Versioning) - what the version number promises.
|
|
- [`docs/api-reference.md`](https://github.com/Ark0N/Codeman/blob/master/docs/api-reference.md) - the full specification.
|