KX-Bridge HTTP API Reference
This document lists the HTTP and WebSocket surface exposed by
kobrax_moonraker_bridge.py. It is a reference for integrators and
plugin authors, not a tutorial — for day-to-day usage of the bridge see
MANUAL.md, and for setup see README.md.
The API has two distinct parts:
- Moonraker-compatible surface — a subset of the real
Moonraker HTTP + WebSocket API,
implemented just far enough to make Mainsail, Fluidd, OrcaSlicer, and
moonraker-obico work against the Kobra X. This is not a full
Moonraker implementation — many real Moonraker endpoints/methods do
not exist here, and some responses are static stubs that exist only
to stop a client from erroring/looping (noted below).
- Bridge-specific surface —
/api/... and /kx/... endpoints for
things Moonraker has no concept of: multi-printer management, AMS/ACE
filament control, the GCode store, custom filament profile import,
Spoolman, and the smart-plug power switch.
Security
There is no authentication on any endpoint. The bridge is designed
to be run on a trusted local network only. Do not expose port 7125
(or any additional per-printer port) to the internet — anyone who can
reach the port can control the printer, read/delete files, and read
/kx/printers credentials indirectly through bridge behavior. /access/api_key
returns a hardcoded dummy value purely so moonraker-obico doesn't warn;
it is not a real credential.
CORS is enabled (_json_cors / handle_kx_options add
Access-Control-Allow-* headers and answer OPTIONS with 204) so the
Web UI can call sibling bridge instances directly in multi-printer setups.
Moonraker-compatible endpoints (HTTP)
All responses follow Moonraker's {"result": {...}} envelope unless noted.
| Method |
Path |
Purpose |
Notes |
| GET |
/server/info |
Server/klippy status |
Always reports klippy_connected: true, klippy_state: "ready" |
| GET |
/printer/info |
Printer identity |
Static hostname/paths; software_version from KLIPPER_VERSION |
| GET |
/machine/system_info |
System info stub |
Mostly static/placeholder fields |
| GET |
/printer/objects/list |
List available printer objects |
Keys of _build_printer_objects() |
| GET |
/printer/objects/query?objects=... |
Query object status |
Comma-separated objects query param, or bare query keys |
GET/POST |
/printer/objects/subscribe |
Subscribe (HTTP polling variant) |
Returns full status snapshot immediately |
| GET |
/server/files/list |
List gcode files |
Only returns the single currently-tracked file (if any) |
| GET |
/server/files/metadata?filename=... |
File metadata (layers, est. time, etc.) |
Shared logic with WS server.files.metadata; falls back to GCode store / buried-report cache |
| POST |
/server/files/upload |
Upload a gcode file (multipart) |
Same handler as /api/files/local |
| POST |
/printer/print/start?filename=... |
Start a print |
Body may include filament_assignments, excluded_objects, auto_leveling |
| POST |
/printer/print/pause |
Pause current print |
|
| POST |
/printer/print/resume |
Resume current print |
|
| POST |
/printer/print/cancel |
Cancel current print |
|
| GET |
/access/api_key |
Dummy API key |
No real auth exists |
| GET |
/machine/update/status |
Update-manager stub |
Always busy: false, empty version_info |
| GET |
/server/history/list?limit= |
Print job history |
Backed by the bridge's own GCodeStore/job DB |
| GET |
/server/webcams/list |
Webcam descriptor |
Rewrites localhost/127.0.0.1 Host header to the bridge's LAN IP so remote Obico/Mainsail instances get a reachable URL |
| POST |
/printer/gcode/script |
Execute a (very limited) gcode command |
See _exec_gcode_script; not a general gcode interpreter |
| GET |
/server/database/item?namespace=&key= |
Moonraker "database" KV read |
Real payload only for lane_data (AMS/filament sync for OrcaSlicer); stub/empty responses for AFC, afc-install, happy_hare, mainsail; in-memory KV for obico |
| POST |
/server/database/item |
Moonraker "database" KV write |
In-memory only (not persisted across restarts); used by moonraker-obico for its own settings |
| GET |
/server/database/list |
List KV namespaces |
Static: ["lane_data", "mainsail", "obico"] |
OctoPrint-compatibility shim
| Method |
Path |
Purpose |
| GET |
/api/version |
OctoPrint-style version probe (some tools check this instead of Moonraker) |
| POST |
/api/files/local, /api/files/{path} |
Alias for the same multipart upload handler as /server/files/upload |
WebSocket JSON-RPC (/websocket)
Moonraker's JSON-RPC 2.0 protocol over a single /websocket endpoint. On
connect the bridge immediately pushes notify_klippy_ready and then
periodic notify_status_update notifications. Supported method values:
| Method |
Purpose |
printer.info / printer_info |
Same payload as /printer/info |
server.info / server_info |
Same payload as /server/info |
printer.objects.list |
Same as HTTP equivalent |
printer.objects.query / printer.objects.get |
Object status by requested keys |
printer.objects.subscribe |
Returns a status snapshot (no real push subscription semantics — status pushes happen automatically via notify_status_update) |
printer.print.start |
params.filename |
printer.print.pause / .resume / .cancel |
|
machine.system_info |
Minimal stub |
server.files.list |
Always returns [] over WS (unlike the HTTP version) |
printer.gcode.script |
params.script, same limited executor as the HTTP endpoint |
server.connection.identify |
Returns a dummy connection_id for Obico's handshake |
connection.register_remote_method |
Accepted and ignored (Obico registers a remote-event callback) |
server.webcams.list |
Same shape as HTTP, using the bridge's own LAN IP |
server.history.list |
Job history, same source as /server/history/list |
machine.update.status |
Stub |
server.files.metadata |
Same logic as /server/files/metadata |
Any other method is logged and answered with an empty result: {} — it
does not error, to avoid breaking clients that probe for optional
methods.
Bridge-specific endpoints
All /kx/... (and most /api/...) responses use {"result": ...} on
success and {"error": "..."} with a 4xx/5xx status on failure, except
where noted.
Printer control (/api/...)
| Method |
Path |
Purpose |
Body / Query |
| POST |
/api/light |
Toggle chamber light |
{on, brightness} |
| POST |
/api/fan |
Set part-cooling fan speed |
{speed} (0–100) |
| POST |
/api/connect |
Manually (re)connect the MQTT client |
— |
| POST |
/api/disconnect |
Manually disconnect |
— |
| POST |
/api/restart |
Restart the bridge process |
— |
| POST |
/api/speed |
Set print speed mode |
{mode} (int) |
| POST |
/api/axis |
Jog an axis, or {"action":"turnoff"} to disable steppers |
{axis, move_type, distance} |
| POST |
/api/temperature |
Set nozzle/bed target temps |
{nozzle?, bed?}; uses a different MQTT path mid-print vs. idle |
| GET |
/api/state |
Full dashboard status snapshot |
Primary polling endpoint used by the Web UI |
| GET |
/api/camera |
Current camera stream URL |
|
| GET |
/api/camera/stream |
MJPEG live view |
multipart/x-mixed-replace, fed from a shared ffmpeg fanout |
| GET |
/api/camera/h264 |
Raw H.264 stream (for Obico) |
|
| GET |
/api/camera/snapshot |
Last cached JPEG frame |
Instant, served from RAM |
| POST |
/api/camera/start / /api/camera/stop / /api/camera/reset |
Camera lifecycle control |
reset clears the 429 backoff and restarts ffmpeg |
| GET |
/api/settings |
Read current config.ini-backed settings |
|
| POST |
/api/settings |
Write settings, then restart the bridge |
See config fields below |
| GET |
/api/update/check |
Check Gitea releases for a newer version |
Branches on nightly/dev/stable channel |
| POST |
/api/update/apply |
Self-update (non-Docker builds only) |
{tag} |
| POST |
/api/file_ready/clear |
Dismiss the "file ready to print" banner/dialog state |
|
| GET |
/api/log/stream |
Server-Sent Events log tail |
|
| GET |
/api/log/download |
Download buffered log as plaintext |
|
| GET |
/serve/{filename} |
Internal file server used to hand the printer a URL to fetch gcode from |
Not meant for direct browser use |
/api/settings fields (POST body, all optional — merges into
existing config.ini): printer_ip, mqtt_port, username, password,
mode_id, device_id, power_on_url, power_off_url,
power_status_url, default_ams_slot, auto_leveling,
vibration_compensation, camera_on_print, web_upload_warning,
print_start_dialog, poll_interval, verbose_http_log,
printer_name, spoolman_server, spoolman_sync_rate,
ace_dry_presets.
AMS / ACE filament control (/api/...)
| Method |
Path |
Purpose |
Body |
| POST |
/api/ams/set_slot |
Set material type + color for a slot |
{index, type, color:[r,g,b]} |
| POST |
/api/ams/feed |
Feed filament in/out |
{slot_index, type} (1=feed in, 2=feed out) |
| POST |
/api/ace/auto_feed |
Toggle auto-feed for an ACE unit |
{ace_id, on} |
| POST |
/api/ace/dry |
Start/stop the ACE dryer |
`{action: "start" |
GCode store (bridge-managed uploads) (/kx/files...)
| Method |
Path |
Purpose |
| GET |
/kx/files |
List files the bridge has stored, with last-print status/duration |
| DELETE |
/kx/files/{file_id} |
Delete a stored file |
| GET |
/kx/files/{file_id}/download |
Download a stored file |
| POST |
/kx/files/{file_id}/verify |
Clear the "web upload, unverified" flag |
| GET |
/kx/files/{id}/objects |
Print-object list + SVG preview (for the pre-print skip feature) |
| GET |
/kx/history?limit=&offset= |
Paginated print job history |
Files on the printer's own storage (/kx/printer-files...)
Distinct from the GCode store above — these list/manage files that live
on the printer's internal storage (e.g. printed directly from Anycubic
Slicer Next, bypassing the bridge).
| Method |
Path |
Purpose |
| GET |
/kx/printer-files |
List files via the printer's file/listLocal MQTT action |
| POST |
/kx/printer-files/delete |
Delete one or more files: {"filenames": [...]} (single endpoint for single + bulk delete) |
| GET |
/kx/printer-files/{filename}/thumbnail |
Fetch (and cache) a file's embedded gcode thumbnail via file/fileDetails |
Printing (/kx/print)
| Method |
Path |
Purpose |
Body |
| POST |
/kx/print |
Start a print from a stored GCode-store file |
{file_id, filament_assignments?, excluded_objects?, auto_leveling?} |
filament_assignments is [{slot_index, material, color_hex}, ...]; if
omitted, all currently-occupied AMS slots are auto-mapped.
Pre-print / mid-print object skip (/kx/skip...)
| Method |
Path |
Purpose |
| POST |
/kx/skip |
Skip named objects mid-print: {"names": [...]} |
| POST |
/kx/skip/query |
Re-request the object list from the printer and return merged skip state |
| GET |
/kx/skip/state |
Current skip state (object list, already-skipped names, SVG, filename) |
Filament profiles (/kx/filament/...)
| Method |
Path |
Purpose |
Body / Query |
| GET |
/kx/filament/slots |
Current AMS slot contents + any user profile override |
|
| GET |
/kx/filament/profiles?type=&vendor= |
Curated OrcaSlicer filament profile catalog (system + user-imported) |
Optional filters |
| GET |
/kx/filament/profiles/user |
User-imported profiles only (for the settings management list) |
|
| POST |
/kx/filament/profiles/user |
Import profiles from a ZIP or .json file(s) (multipart) |
Multipart field file/files/upload; ZIP entries or bare .json, parsed via orca_filaments.parse_profile_bytes |
| DELETE |
/kx/filament/profiles/user?vendor=&name= |
Delete one user profile (both params) or all (no params) |
|
| POST |
/kx/filament/slots/{idx}/profile |
Assign (or clear) a fixed profile override for one AMS slot |
{vendor, name}; empty strings clear the mapping. Selector is (vendor, name), not id — IDs are not unique across the Orca profile catalog |
GET/POST |
/kx/filament/visible_vendors |
Get/set the vendor visibility filter for the slot profile dropdown |
POST body {"vendors": [...]}; empty list = show all |
Spoolman integration (/kx/spoolman/...)
| Method |
Path |
Purpose |
| GET |
/kx/spoolman/status |
Whether Spoolman is configured/reachable, server URL, sync rate, current slot→spool map |
| GET |
/kx/spoolman/spools |
Proxied list of spools from the configured Spoolman server |
| POST |
/kx/spoolman/active-spool |
Assign spool IDs to AMS slots: {"slot_map": {"0": 42, "2": 17}} (AMS slot index → Spoolman spool ID) |
Multi-printer management (/kx/printers...)
| Method |
Path |
Purpose |
Body |
| GET |
/kx/printers |
List all configured printers with online-ish metadata |
|
| POST |
/kx/printers/add |
Add a printer by IP (credentials auto-fetched from the printer) |
{printer_ip, name?} — triggers a bridge restart |
| DELETE |
/kx/printers/{pid} |
Remove a printer from config; renumbers remaining [printer_N] sections |
— triggers a bridge restart |
| POST |
/kx/printers/{pid}/power |
Toggle an external smart plug (Tasmota-style) for a printer |
`{"action": "on" |
| GET |
/kx/printers/{pid}/power-status |
Query the smart plug's current on/off state |
|
Power switch is not the printer's own power state — it's a plain
GET fired at a user-configured power_on_url / power_off_url /
power_status_url (e.g. a Tasmota cmnd=Power%20on URL). See
MANUAL.md for details.
It only exists for printers where power_on_url or power_off_url is
set in config; /kx/printers exposes this as has_power_control.
Misc
| Method |
Path |
Purpose |
| GET |
/kx/ui/{name} |
Serves theme assets (JS/CSS/vendored libs) and translation JSON files under the active UI theme |
| GET |
/ , /printer{N} |
Serves the Web UI (index.html with CSS/JS inlined for embedded-webview compatibility, e.g. OrcaSlicer's device tab) |
| GET |
/favicon.ico |
Favicon |
Response conventions
- Moonraker-compatible endpoints wrap results as
{"result": {...}} (or
{"error": {"code": ..., "message": ...}} for the /server/database/*
404 case) to match the real Moonraker schema.
- Bridge-specific
/api/... and /kx/... endpoints generally return
{"result": ...} on success and {"error": "message"} with a
non-2xx HTTP status on failure — but this is not universal; check the
handler in kobrax_moonraker_bridge.py if exact shape matters (route
registrations are near the end of the file, search for
r.add_get(/r.add_post(/r.add_delete().
- Endpoints that trigger a config write (
/api/settings,
/kx/printers/add, /kx/printers/{pid} DELETE) restart the whole
bridge process shortly after responding — clients should expect a
brief connection drop.