-
Notifications
You must be signed in to change notification settings - Fork 0
api endpoints
Active contributors: elwina
The full reference for the localhost control plane, one route per section. All requests go to http://127.0.0.1:<port> with the Authorization: Bearer <token> header from the lockfile, and every response is an Envelope. Types come from crates/capto-ipc/src/types.rs, crates/capto-core/src/session.rs, and crates/capto-core/src/settings.rs. The router and handlers are defined in apps/desktop/src-tauri/src/cli_server.rs.
- Method/path:
GET /v1/status - Request: none
- Response data:
SessionSnapshotfromcrates/capto-core/src/session.rs({ state, elapsedMs, outputPath, lastError, encoder, hideApp }) - Errors: no application-level errors; unauthenticated
unauthorized→ 401
{ "ok": true, "data": {
"state": "Idle",
"elapsedMs": 0,
"outputPath": null,
"lastError": null,
"encoder": null,
"hideApp": false
} }state is one of Idle, Starting, Recording, Paused, Stopping.
- Method/path:
GET /v1/doctor - Request: none
- Response data:
DoctorInfo(OS, capture backend, FFmpeg path/presence, control-plane status, pid, port, preferred encoder) fromcrates/capto-ipc/src/types.rs - Errors:
unauthorized→ 401
{ "ok": true, "data": {
"os": "windows",
"captureBackend": "dxgi",
"ffmpegPath": "C:\\Capto\\ffmpeg.exe",
"ffmpegOk": true,
"controlPlane": true,
"pid": 4812,
"port": 51023,
"preferredEncoder": "h264_nvenc"
} }ffmpegOk is a real -version probe, not just file presence, so a wedged process still reports false (session_svc::doctor).
- Request: none
- Response data: full
AppSettingsfromcrates/capto-core/src/settings.rs(camelCase) - Errors:
unauthorized→ 401
- Method/path:
PATCH /v1/config - Request: a JSON object of partial settings; only the supplied keys are merged
- Response data: the merged full
AppSettings - Errors:
configIo→ 404 on filesystem failure;unauthorized→ 401 - Side effect: hotkey re-registration. If the patch changes
hotkeys,patch_settingsinapps/desktop/src-tauri/src/session_svc.rscallsregister_hotkeysand stores any conflict results in app state. It also emits asettings://changedevent to the UI.
{ "ok": true, "data": { "fps": 60, "quality": 80 } }- Method/path:
GET /v1/config/path - Request: none
- Response data:
ConfigPathInfo({ path }) pointing atsettings.json - Errors:
unauthorized→ 401
- Request:
RecordStartRequestfromcrates/capto-ipc/src/types.rs, camelCase, with all fields optional (#[serde(default)]) exceptsource - Response data:
SessionSnapshot - Errors: classified by the
record_starthandler inapps/desktop/src-tauri/src/cli_server.rs:-
stateConflict(409) when the message containsinvalid stateoralready, for example starting while already recording -
encode(500) when the message containsffmpegorencode -
capture(500) for everything else
-
{
"source": "display",
"displayId": 0,
"includeCursor": true,
"format": "mp4",
"fps": 60,
"quality": 80
}- Request: none
- Response data:
SessionSnapshot(returns toIdle, with the finaloutputPath) - Errors:
stateConflict(409) when nothing is recording
- Request: none
- Response data:
SessionSnapshotwithstate: "Paused" - Errors:
stateConflict(409) when not recording or already paused
- Request: none
- Response data:
SessionSnapshotwithstate: "Recording" - Errors:
stateConflict(409) when not paused
- Request:
ShotRequest(sourceplus optionaldisplayId/windowId/region) - Response data:
{ "path": "<absolute png path>" } - Errors:
capture(500) on capture or region failure; window-gone returnscapture
{ "ok": true, "data": { "path": "C:\\Users\\x\\Videos\\Capto\\capto-shot-20260812-104523-a1b2c3d4.png" } }All four listing endpoints are GET, return raw vendor JSON in data, and require no body.
| Endpoint | Returns | Error code |
|---|---|---|
GET /v1/list/displays |
capture displays | capture |
GET /v1/list/windows |
capture windows | capture |
GET /v1/list/audio |
mic + loopback devices | capture |
GET /v1/list/encoders |
FFmpeg probe result | encode |
/v1/list/encoders calls refresh_encoder and probes the bundled FFmpeg, so it reports encode when FFmpeg is missing.
- Query: optional
limit(positive integer; default 20 in the handler, capped at a minimum of 1) - Request body: none
- Response data:
OutputsList({ outputDir, items: [ { path, name, bytes, modifiedMs } ] }), newest first, filtered tocapto-*/capto_*files plus common media extensions - Errors:
configIo(500) on directory read failure
{ "ok": true, "data": {
"outputDir": "C:\\Users\\x\\Videos\\Capto",
"items": [
{ "path": "C:\\Users\\x\\Videos\\Capto\\capto-20260812...mp4",
"name": "capto-20260812....mp4",
"bytes": 2143548,
"modifiedMs": 1755012345678 }
]
} }- Request:
OpenOutputsRequest({ path?, folder?, last? }) fromcrates/capto-ipc/src/types.rs - Response data:
{ opened, kind }wherekindisfolderorfile - Errors:
notFound(404) when a path does not exist or no output is found - Behaviors (
app_services::open_outputsinsession_svc.rs):-
folder: true→ opens (and creates if needed) the output directory -
pathset → opens that file -
last: true→ resolves the most recent output viaoutputs_recent(limit 1) - none of path/folder/last → error
-
{ "request": { "last": true, "folder": false },
"response": { "ok": true, "data": { "opened": "C:\\...\\capto.mp4", "kind": "file" } } }- Request: none
- Response data: a
Metricssnapshot (request counters, duration histogram, per-status counters) - Errors:
notFound(404) when theCONTROL_PLANE_METRICSfeature flag is disabled;unauthorized→ 401
Metrics are recorded by the telemetry_layer middleware on every control-plane call (apps/desktop/src-tauri/src/cli_server.rs).
Every handler returns unauthorized (HTTP 401) with code unauthorized when the bearer token is missing or wrong. Route dispatch failures and unknown paths return HTTP 404. The server converts internal codes to HTTP status in map_err (apps/desktop/src-tauri/src/cli_server.rs).
Every CLI command maps 1:1 to an endpoint (crates/capto-cli/src/main.rs), so the endpoint list and the CLI surface stay in lockstep.
| CLI command | Endpoint |
|---|---|
capto status |
GET /v1/status |
capto doctor |
GET /v1/doctor |
capto config get |
GET /v1/config |
capto config set |
PATCH /v1/config |
capto config path |
GET /v1/config/path |
capto record start |
POST /v1/record/start |
capto record stop |
POST /v1/record/stop |
capto record pause |
POST /v1/record/pause |
capto record resume |
POST /v1/record/resume |
capto shot |
POST /v1/shot |
capto list displays |
GET /v1/list/displays |
capto list windows |
GET /v1/list/windows |
capto list audio |
GET /v1/list/audio |
capto list encoders |
GET /v1/list/encoders |
capto outputs recent |
GET /v1/outputs/recent?limit=N |
capto outputs open |
POST /v1/outputs/open |
capto open |
no HTTP, launches the desktop only |
See capto CLI for the exit-code table and auto-launch behavior.
| File | Role |
|---|---|
apps/desktop/src-tauri/src/cli_server.rs |
Router, handlers, auth, error classification, telemetry |
apps/desktop/src-tauri/src/session_svc.rs |
Shared implementation behind every handler |
crates/capto-ipc/src/types.rs |
Request and info types (RecordStartRequest, ShotRequest, OutputsList, ...) |
crates/capto-ipc/src/envelope.rs |
Envelope and error serialization |
crates/capto-core/src/session.rs |
SessionSnapshot |
crates/capto-core/src/settings.rs |
AppSettings |
crates/capto-cli/src/main.rs |
CLI command surface and exit-code mapping |
- Control-plane API, envelope, auth, versioning, mental model
- capto CLI, client commands, exit codes, discovery
- capto-ipc, envelope, lockfile, shared types
-
capto-core,
SessionSnapshot/AppSettings - Security, token handling and redaction
- Recording, record workflow semantics