# API Most API methods are supported over both the Websocket and HTTP transports. File Transfer and "/access" requests are only available over HTTP. The Websocket is required to receive printer generated events such as gcode responses. For information on how to set up the Websocket, please see the Appendix at the end of this document. Note that all HTTP responses are returned as a json encoded object in the form of: `{result: }` Arguments sent via the HTTP APIs may either be included in the query string or as part of the request's body. All of the examples in this document use the query string for arguments. Websocket requests are returned in JSON-RPC format: `{jsonrpc: "2.0", "result": , id: }` HTML requests will recieve a 500 status code on error, accompanied by the specific error message. Websocket requests that result in an error will receive a properly formatted JSON-RPC response: `{jsonrpc: "2.0", "error": {code: , message: }, id: }` Note that under some circumstances it may not be possible for the server to return a request ID, such as an improperly formatted json request. The `test\client` folder includes a basic test interface with example usage for most of the requests below. It also includes a basic JSON-RPC implementation that uses promises to return responses and errors (see json-rcp.js). ## Printer Administration ### Get Klippy host information: - HTTP command:\ `GET /printer/info` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.info", id: }` - Returns:\ An object containing the build version, cpu info, Klippy's current state. ```json { state: "", state_message: "", hostname: "", software_version: "", cpu_info: "", klipper_path: "", python_path: "", log_file: "", config_file: "", } ``` ### Emergency Stop - HTTP command:\ `POST /printer/emergency_stop` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.emergency_stop", id: }` - Returns:\ `ok` ### Restart the host - HTTP command:\ `POST /printer/restart` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.restart", id: }` - Returns:\ `ok` ### Restart the firmware (restarts the host and all connected MCUs) - HTTP command:\ `POST /printer/firmware_restart` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.firmware_restart", id: }` - Returns:\ `ok` ## Printer Status ### List available printer objects: - HTTP command:\ `GET /printer/objects/list` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.objects.list", id: }` - Returns:\ An a list of "printer objects" that are currently available for query or subscription. This list will be passed in an "objects" parameter. ```json { objects: ["gcode", "toolhead", "bed_mesh", "configfile",....]} ``` ### Query printer object status: - HTTP command:\ `GET /printer/objects/query?gcode` The above will fetch a status update for all gcode attributes. The query string can contain multiple items, and specify individual attributes: `?gcode=gcode_position,busy&toolhead&extruder=target` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.objects.query", params: {objects: {gcode: null, toolhead: ["position", "status"]}}, id: }` Note that an empty array will fetch all available attributes for its key. - Returns:\ An object where the top level items are "eventtime" and "status". The "status" item contains data about the requested update. ```json { eventtime: , status: { gcode: { busy: true, gcode_position: [0, 0, 0 ,0], ...}, toolhead: { position: [0, 0, 0, 0], status: "Ready", ...}, ...} } ``` See [printer_objects.md](printer_objects.md) for details on the printer objects available for query. ### Subscribe to printer object status: - HTTP command:\ `POST /printer/objects/subscribe?connection_id=123456789& gcode=gcode_position,bus&extruder=target` Note: The HTTP API requires that a `connection_id` is passed via the query string or as part of the form. This should be the [ID reported](#get-websocket-id) from a currently connected websocket. A request that includes only the `connection_id` argument will cancel the subscription on the specified websocket. - Websocket command:\ `{jsonrpc: "2.0", method: "printer.objects.subscribe", params: {objects: {gcode: null, toolhead: ["position", "status"]}}, id: }` Note that if `objects` is an empty object then the subscription will be cancelled. - Returns:\ Status data for objects in the request, with the format matching that of the `/printer/objects/query`: ```json { eventtime: , status: { gcode: { busy: true, gcode_position: [0, 0, 0 ,0], ...}, toolhead: { position: [0, 0, 0, 0], status: "Ready", ...}, ...} } ``` See [printer_objects.md](printer_objects.md) for details on the printer objects available for subscription. Status updates for subscribed objects are sent asynchronously over the websocket. See the `notify_status_update` notification for details. ### Query Endstops - HTTP command:\ `GET /printer/query_endstops/status` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.query_endstops.status", id: }` - Returns:\ An object containing the current endstop state, with each attribute in the format of `endstop:`, where "state" can be "open" or "TRIGGERED", for example: ```json {x: "TRIGGERED", y: "open", z: "open"} ``` ### Query Server Info - HTTP command:\ `GET /server/info` - Websocket command: `{jsonrpc: "2.0", method: "server.info", id: }` - Returns:\ An object containing the server's state, structured as follows: ```json { klippy_connected: , klippy_state: , plugins: [] } ``` Note that `klippy_state` will match the `state` value received from `/printer/info`. The `klippy_connected` item tracks the state of the connection to Klippy. The `plugins` key will return a list of all enabled plugins. This can be used by clients to check if an optional plugin is available. ### Fetch stored temperature data - HTTP command:\ `GET /server/temperature_store` - Websocket command: `{jsonrpc: "2.0", method: "server.temperature_store", id: }` - Returns:\ An object where the keys are the available temperature sensor names, and with the value being an array of stored temperatures. The array is updated every 1 second by default, containing a total of 1200 values (20 minutes). The array is organized from oldest temperature to most recent (left to right). Note that when the host starts each array is initialized to 0s. ### Fetch stored gcode info - HTTP command:\ `GET /server/gcode_store` Optionally, a `count` argument may be added to specify the number of responses to fetch. If omitted, the entire gcode store will be sent (up to 1000 responses). `GET /server/gcode_store?count=100` - Websocket command: `{jsonrpc: "2.0", method: "server.gcode_store", id: }` OR `{jsonrpc: "2.0", method: "server.gcode_store", params: {count: } id: }` - Returns:\ An object with the field `gcode_store` that contains an array of objects. Each object will contain a `message` field and a `time` field: ```json { gcode_store: [ { message: , time: unix_time_stamp }, ... ] } ``` Each `message` field contains a gcode response received at the time indicated in the `time` field. Note that the time stamp refers to unix time (in seconds). This can be used to create a JavaScript `Date` object: ```javascript for (let resp of result.gcode_store) { let date = new Date(resp.time * 1000); // Do something with date and resp.message ... } ``` ### Restart Server - HTTP command:\ `POST /server/restart` - Websocket command: `{jsonrpc: "2.0", method: "server.restart", id: }` - Returns:\ `"ok"` upon receipt of the restart request. After the request is returns, the server will restart. Any existing connection will be disconnected. A restart will result in the creation of a new server instance where the configuration is reloaded. ## Get Websocket ID - HTTP command:\ Not Available - Websocket command: `{jsonrpc: "2.0", method: "server.websocket.id", id: }` - Returns:\ This connected websocket's unique identifer in the format shown below. Note that this API call is only available over the websocket. ```json { websocket_id: } ``` ## Gcode Controls ### Run a gcode: - HTTP command:\ `POST /printer/gcode/script?script=` For example,\ `POST /printer/gcode/script?script=RESPOND MSG=Hello`\ Will echo "Hello" to the terminal. - Websocket command:\ `{jsonrpc: "2.0", method: "printer.gcode.script", params: {script: }, id: }` - Returns:\ An acknowledgement that the gcode has completed execution: `ok` ### Get GCode Help - HTTP command:\ `GET /printer/gcode/help` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.gcode.help", params: {script: }, id: }` - Returns:\ An object where they keys are gcode handlers and values are the associated help strings. Note that help strings are not available for basic gcode handlers such as G1, G28, etc. ## Print Management ### Print a file - HTTP command:\ `POST /printer/print/start?filename=` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.print.start", params: {filename: , id:}` - Returns:\ `ok` on success ### Pause a print - HTTP command:\ `POST /printer/print/pause` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.print.pause", id: }` - Returns:\ `ok` ### Resume a print - HTTP command:\ `POST /printer/print/resume` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.print.resume", id: }` - Returns:\ `ok` ### Cancel a print - HTTP command:\ `POST /printer/print/cancel` - Websocket command:\ `{jsonrpc: "2.0", method: "printer.print.cancel", id: }` - Returns:\ `ok` ## Machine Commands ### Shutdown the Operating System - HTTP command:\ `POST /machine/shutdown` - Websocket command:\ `{jsonrpc: "2.0", method: "machine.shutdown", id: }` - Returns:\ No return value as the server will shut down upon execution ### Reboot the Operating System - HTTP command:\ `POST /machine/reboot` - Websocket command:\ `{jsonrpc: "2.0", method: "machine.reboot", id: }` - Returns:\ No return value as the server will shut down upon execution ### Restart a system service Restarts a system service via `sudo systemctl restart `. Currently only `moonraker` and `klipper` are allowed. - HTTP command:\ `POST /machine/services/restart?service=` - Websocket command:\ `{jsonrpc: "2.0", method: "machine.services.restart", params: {service: "service name"}, id: }` - Returns:\ `ok` when complete. Note that if `moonraker` is chosen, the return value will be sent prior to the restart. ## File Operations Most file operations are available over both APIs, however file upload, file download, and file delete are currently only available via HTTP APIs. Moonraker organizes different local directories into "roots". For example, gcodes are located at `http:\\host\server\files\gcodes\*`, otherwise known as the "gcodes" root. The following roots are available: - gcodes - config - config_examples (read-only) - docs (read-only) Write operations (upload, delete, make directory, remove directory) are only available on the `gcodes` and config roots. Note that the `config` root is only available if the "config_path" option has been set in Moonraker's configuration. ### List Available Files Walks through a directory and fetches all files. All file names include a path relative to the specified "root". Note that if the query st - HTTP command:\ `GET /server/files/list?root=gcodes` If the query string is omitted then the command will return the "gcodes" file list by default. - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.list", params: {root: "gcodes"} , id: }` If `params` are are omitted then the command will return the "gcodes" file list. - Returns:\ A list of objects containing file data in the following format: ```json [ {filename: "file name", size: , modified: , ...] ``` ### Get GCode Metadata Get file metadata for a specified gcode file. If the file is located in a subdirectory, then the file name should include the path relative to the "gcodes" root. For example, if the file is located at:\ `http://host/server/files/gcodes/my_sub_dir/my_print.gcode` Then the filename should be `my_sub_dir/my_print.gcode`. - HTTP command:\ `GET /server/files/metadata?filename=` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.metadata", params: {filename: "filename"} , id: }` - Returns:\ Metadata for the requested file if it exists. If any fields failed parsing they will be omitted. The metadata will always include the file name, modified time, and size. ```json { filename: "file name", size: , modified: , slicer: "Slicer Name", slicer_version: "", first_layer_height: , first_layer_bed_temp: , first_layer_extr_temp: , layer_height: , object_height: , estimated_time: , filament_total: , gcode_start_byte: , gcode_end_byte: , thumbnails: [ { width: , height: , size: , data: }, ... ] } ``` ### Get directory information Returns a list of files and subdirectories given a supplied path. Unlike `/server/files/list`, this command does not walk through subdirectories. - HTTP command:\ `GET /server/files/directory?path=gcodes/my_subdir&extended=true` If the query string is omitted then the command will return the "gcodes" file list by default. - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.get_directory", params: {path: "gcodes/my_subdir", extended: true} , id: }` If the "params" are omitted then the command will return the "gcodes" file list by default. The `extended` argument is optional, and defaults to false. If specified and set to true, then data returned for gcode files will also include metadata if it is available. - Returns:\ An object containing file and subdirectory information in the following format: ```json { files: [ { filename: "file name", size: , modified: }, ... ], dirs: [ { dirname: "directory name", modified: } ] } ``` ### Make new directory Creates a new directory at the specified path. - HTTP command:\ `POST /server/files/directory?path=gcodes/my_new_dir` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.post_directory", params: {path: "gcodes/my_new_dir"}, id: }` Returns:\ `ok` if successful ### Delete directory Deletes a directory at the specified path. - HTTP command:\ `DELETE /server/files/directory?path=gcodes/my_subdir` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.delete_directory", params: {path: "gcodes/my_subdir"} , id: }` If the specified directory contains files then the delete request will fail, however it is possible to "force" deletion of the directory and all files in it with and additional argument in the query string:\ `DELETE /server/files/directory?path=gcodes/my_subdir&force=true` OR to the JSON-RPC params:\ `{jsonrpc: "2.0", method: "get_directory", params: {path: "gcodes/my_subdir", force: True}, id: }` Note that a forced deletion will still check in with Klippy to be sure that a file in the requested directory is not loaded by the virtual_sdcard. - Returns:\ `ok` if successful ### Move a file or directory Moves a file or directory from one location to another. Note that the following conditions must be met for a move successful move: - The source must exist - The source and destinations must have the same "root" directory - The user (typically "Pi") must have the appropriate file permissions - Neither the source nor destination can be loaded by the virtual_sdcard. If the source or destination is a directory, it cannot contain a file loaded by the virtual_sdcard. When specifying the `source` and `dest`, the "root" directory should be prefixed. Currently the only supported roots are "gcodes/" and "config/". This API may also be used to rename a file or directory. Be aware that an attempt to rename a directory to a directory that already exists will result in *moving* the source directory to the destination directory. - HTTP command:\ `POST /server/files/move?source=gcodes/my_file.gcode &dest=gcodes/subdir/my_file.gcode` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.move", params: {source: "gcodes/my_file.gcode", dest: "gcodes/subdir/my_file.gcode"}, id: }` ### Copy a file or directory Copies a file or directory from one location to another. A successful copy has the pre-requesites as a move with one exception, a copy may complete if the source file/directory is loaded by the virtual_sdcard. As with the move API, the source and destination should have the root prefixed. - HTTP command:\ `POST /server/files/copy?source=gcodes/my_file.gcode &dest=gcodes/subdir/my_file.gcode` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.copy", params: {source: "gcodes/my_file.gcode", dest: "gcodes/subdir/my_file.gcode"}, id: }` ### Gcode File Download - HTTP command:\ `GET /server/files/gcodes/` - Websocket command:\ Not Available - Returns:\ The requested file ### File Upload Upload a file. Currently files may be uploaded to the "gcodes" or "config" root, with "gcodes" being the default location. If one wishes to upload to a subdirectory, the path may be added to the upload's file name (relative to the root). If the directory does not exist an error will be returned. Alternatively, the "path" argument may be set, as explained below. - HTTP command:\ `POST /server/files/upload` The file to be uploaded should be added to the FormData per the XHR spec. The following arguments may be added to the form: - root: The root location in which to upload the file. Currently this may be "gcodes" or "config". If not specified the default is "gcodes". - path: This argument may contain a path (relative to the root) indicating a subdirectory to which the file is written. If a "path" is present, the server will attempt to create any subdirectories that do not exist. Arguments available only for the "gcodes" root: - print: If set to "true", Klippy will attempt to start the print after uploading. Note that this value should be a string type, not boolean. This provides compatibility with Octoprint's legacy upload API. - Websocket command:\ Not Available - Returns:\ The file name along with a successful response. ```json {'result': "file_name"} ``` If the supplied root is "gcodes", a "print_started" attribute is also returned. ```json {'result': "file_name", 'print_started': } ``` ### Gcode File Delete Delete a file in the "gcodes" root. A relative path may be added to the file to delete a file in a subdirectory. - HTTP command:\ `DELETE /server/files/gcodes/` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.delete_file", params: {path: "gcodes/"}, id: }` If the gcode file exists within a subdirectory, the relative path should be included in the file name. - Returns:\ The HTTP request returns the name of the deleted file. ### Download included config file - HTTP command:\ `GET /server/files/config/` - Websocket command:\ Not Available - Returns:\ The requested file ### Delete included config file Delete a file in the "config" root. A relative path may be added to the file to delete a file in a subdirectory. - HTTP command:\ `DELETE /server/files/config/` - Websocket command:\ `{jsonrpc: "2.0", method: "server.files.delete_file", params: {path: "config/}, id: }` - Returns:\ The HTTP request returns the name of the deleted file. ### Download a config example - HTTP command:\ `GET /server/files/config_examples/` - Websocket command:\ Not Available - Returns:\ The requested file ### Download Klipper documentation - HTTP command:\ `GET /server/files/docs/` - Websocket command:\ Not Available - Returns:\ The requested file ### Download klippy.log - HTTP command:\ `GET /server/files/klippy.log` - Websocket command:\ Not Available - Returns:\ klippy.log ### Download moonraker.log - HTTP command:\ `GET /server/files/moonraker.log` - Websocket command:\ Not Available - Returns:\ moonraker.log ## Authorization Untrusted Clients must use a key to access the API by including it in the `X-Api-Key` header for each HTTP Request. The API below allows authorized clients to receive and change the current API Key. ### Get the Current API Key - HTTP command:\ `GET /access/api_key` - Websocket command:\ Not Available - Returns:\ The current API key ### Generate a New API Key - HTTP command:\ `POST /access/api_key` - Websocket command:\ Not available - Returns:\ The newly generated API key. This overwrites the previous key. Note that the API key change is applied immediately, all subsequent HTTP requests from untrusted clients must use the new key. ### Generate a Oneshot Token Some HTTP Requests do not expose the ability the change the headers, which is required to apply the `X-Api-Key`. To accomodiate these requests it a client may ask the server for a Oneshot Token. Tokens expire in 5 seconds and may only be used once, making them relatively for inclusion in the query string. - HTTP command:\ `GET /access/oneshot_token` - Websocket command: Not available - Returns:\ A temporary token that may be added to a requests query string for access to any API endpoint. The query string should be added in the form of: `?token=randomly_generated_token` ## Update Manager APIs The following endpoints are availabe when the `[update_manager]` plugin has been configured: ### Get update status Retreives the current state of each "package" available for update. Typically this will consist of information regarding `moonraker`, `klipper`, and a `client`. If moonraker has not yet received information from Klipper then its status will be omitted. If a client has not been configured then its status will also be omitted. If the parameter "refresh" is passed and set to true then Moonraker will query Github for the most recent release information. - HTTP command:\ `GET /machine/update/status?refresh=false` If the query string is omitted then "refresh" will default to false. - Websocket command:\ `{jsonrpc: "2.0", method: "machine.update.status", params: {refresh: false} , id: }` If the "params" are omitted then "refresh" will default to false. - Returns:\ Status information in the following format: ```json { 'version_info': { 'moonraker': { branch: , remote_alias: , version: , remote_version: , current_hash: , remote_hash: , is_valid: , is_dirty: , detached: , debug_enabled: }, 'klipper': { branch: , remote_alias: , version: , remote_version: , current_hash: , remote_hash: , is_valid: , is_dirty: , detached: , debug_enabled: }, 'client': { name: , version: , remote_version: }, 'system': { package_count: , package_list: } }, busy: false, github_rate_limit: , github_requests_remaining: github_limit_reset_time: , } ``` - The `busy` field is set to true if an update is in progress. Moonraker will not allow concurrent updates. - The `github_rate_limit` is the maximum number of github API requests the user currently has. An unathenticated user typically has 60 requests per hour. - The `github_requests_remaining` is the number of API request the user currently has remaining. - The `github_limit_reset_time` is reported as seconds since the epoch. When this time is reached the user's limit will be reset. - The `moonraker` and `klipper` objects have the following fields: - `branch`: the name of the current git branch. This should typically be "master". - `remote_alias`: the alias for the remote. This should typically be "origin". - `version`: version of the current repo on disk - `remote_version`: version of the latest available update - `current_hash`: hash of the most recent commit on disk - `remote_hash`: hash of the most recent commit pushed to the remote - `is_valid`: True if installation is a valid git repo on the master branch and an "origin" set to the official remote - `is_dirty`: True if the repo has been modified - `detached`: True if the repo is currently in a detached state - `debug_enabled`: True when "enable_repo_debug" has been configured. This will bypass repo validation, allowing detached updates, and updates from a remote/origin other than "origin/master". - The `client` object has the following fields: - `name`: Name of the configured client - `version`: version of the installed client. - `remote_version`: version of the latest release published to GitHub - The `system` object has the following fields: - `package_count`: The number of system packages available for update - `package_list`: An array containing the names of packages available for update ### Update Moonraker Pulls the most recent version of Moonraker from GitHub and restarts the service. If "include_deps" is set to `true` an attempt will be made to install new packages (via apt-get) and python dependencies (via pip). Note that Moonraker uses semantic versioning to check for dependency changes automatically, so it is generally not necessary to set `include_deps` to `true`. - HTTP command:\ `POST /machine/update/moonraker?include_deps=false` If the query string is omitted then "include_deps" will default to false. - Websocket command:\ `{jsonrpc: "2.0", method: "machine.update.moonraker", params: {include_deps: false}, id: }` If the "params" are omitted then "include_deps" will default to false. - Returns:\ `ok` when complete ### Update Klipper Pulls the most recent version of Klipper from GitHub and restarts the service. If "include_deps" is set to `true` an attempt will be made to install new packages (via apt-get) and python dependencies (via pip). At the moment there is no method for automatically checking for updated Klipper dependencies, so clients might wish to make this option available to users via the UI. - HTTP command:\ `POST /machine/update/klipper?include_deps=false` If the query string is omitted then "include_deps" will default to false. - Websocket command:\ `{jsonrpc: "2.0", method: "machine.update.klipper", params: {include_deps: false}, id: }` If the "params" are omitted then "include_deps" will default to false. - Returns:\ `ok` when complete ### Update Client If `client_repo` and `client_path` have been configured in `[update_manager]` this endpoint can be used to install the most recently publish release of the client. - HTTP command:\ `POST /machine/update/client` - Websocket command:\ `{jsonrpc: "2.0", method: "machine.update.client", id: }` - Returns:\ `ok` when complete ### Update System Packages Upgrades the system packages. Currently only `apt-get` is supported. - HTTP command:\ `POST /machine/update/system` - Websocket command:\ `{jsonrpc: "2.0", method: "machine.update.system", id: }` - Returns:\ `ok` when complete ## Power APIs The APIs below are available when the `[power]` plugin has been configured. ### Get Devices - HTTP command:\ `GET /machine/device_power/devices` - Websocket command:\ `{"jsonrpc":"2.0","method":"machine.device_power.devices","id":"1"}` - Returns:\ An array of objects containing info for each configured device. ```json { devices: [ { device: , status: , type: }, ... ] } ``` ### Get Device Status - HTTP command:\ `GET /machine/device_power/status?dev_one&dev_two` - Websocket command:\ `{"jsonrpc":"2.0","method":"machine.device_power.status","id":"1", "params":{"dev_one":null, "dev_two": null}}` - Returns:\ An object containing status for each requested device ```json { dev_one: , dev_two: , ... } ``` ### Power On Device(s) - HTTP command:\ `POST /machine/device_power/on?dev_one&dev_two` - Websocket command:\ `{"jsonrpc":"2.0","method":"machine.device_power.on","id":"1", "params":{"dev_one":null, "dev_two": null}}` - Returns:\ An object containing status for each requested device ```json { dev_one: , dev_two: , ... } ``` ### Power Off Device(s) - HTTP command:\ `POST /machine/device_power/off?dev_one&dev_two` - Websocket command:\ `{"jsonrpc":"2.0","method":"machine.device_power.off","id":"1", "params":{"dev_one":null, "dev_two": null}}` - Returns:\ An object containing status for each requested device ```json { dev_one: , dev_two: , ... } ``` ## Websocket notifications Printer generated events are sent over the websocket as JSON-RPC 2.0 notifications. These notifications are sent to all connected clients in the following format: `{jsonrpc: "2.0", method: }` OR `{jsonrpc: "2.0", method: , params: []}` If a notification has parameters, the `params` value will always be wrapped in an array as directed by the JSON-RPC standard. Currently all notifications available are broadcast with either no parameters or a single parameter. ### Gcode response: All calls to gcode.respond() are forwarded over the websocket. They arrive as a "gcode_response" notification: `{jsonrpc: "2.0", method: "notify_gcode_response", params: ["response"]}` ### Status subscriptions: Status Subscriptions arrive as a "notify_status_update" notification: `{jsonrpc: "2.0", method: "notify_status_update", params: []}` The structure of the status data is identical to the structure that is returned from an object query's "status" attribute. ### Klippy Ready: Notify clients when Klippy has reported a ready state `{jsonrpc: "2.0", method: "notify_klippy_ready"}` ### Klippy Disconnected: Notify clients when Moonraker's connection to Klippy has terminated `{jsonrpc: "2.0", method: "notify_klippy_disconnected"}` ### File List Changed When a client makes a change to the virtual sdcard file list (via upload or delete) a notification is broadcast to alert all connected clients of the change: `{jsonrpc: "2.0", method: "notify_filelist_changed", params: []}` The param is an object in the following format, where the "action" is the operation that prompted the change, and the "item" contains information about the item that has changed: ```json {action: "", item: { path: "", root: "", size: , modified: "" } ``` Note that file move and copy actions also include a "source item" that contains the path and root of the source file or directory. ```json {action: "", item: { path: "", root: "", size: , modified: "" }, source_item: { path: "", root: "" } } ``` The following `actions` are currently available: - `upload_file` - `delete_file` - `create_dir` - `delete_dir` - `move_item` - `copy_item` ### Metadata Update When a new file is uploaded via the API a websocket notification is broadcast to all connected clients after parsing is complete: `{jsonrpc: "2.0", method: "notify_metadata_update", params: [metadata]}` Where `metadata` is an object in the following format: ```json { filename: "file name", size: , modified: "last modified date", slicer: "Slicer Name", first_layer_height: , layer_height: , object_height: , estimated_time: