Bambu Printer App - API Reference
Overview
This REST API provides complete control over Bambu Lab printers via HTTP requests. Built with Flask and Socket.IO, powered by bambu-printer-manager, it exposes printer status, control commands, file management, and real-time telemetry data.
Base URL: http://localhost:5000/api
Response Format: All endpoints return JSON unless noted otherwise.
Standard Success Response: {"status": "success"}
Standard Error Response: {"status": "error", "reason": "description"}
Table of Contents
- OpenAPI & Swagger
- Printer Status & Information
- Temperature Control
- Fan Control
- Print Job Control
- Filament Management
- File Management
- Tool Control (Dual Extruder)
- AMS Control
- Detection & Safety
- Advanced Settings
- Telemetry & Data
- System & Diagnostics
- Socket.IO Events
- build_all_data() Response Schema
- Error Handling
- Library-Only Methods (no HTTP route)
- Environment Variables
- Examples
- Related Resources
- Version History
OpenAPI & Swagger
The API server publishes a generated OpenAPI document and an interactive Swagger UI.
GET /api/openapi.json
Swagger UI: GET /api/openapi.json
Returns the generated OpenAPI 3.0 document for the currently running API
routes.
Success Response (200 OK): JSON OpenAPI schema document.
GET /api/docs
Swagger UI: GET /api/docs
Serves Swagger UI configured to load /api/openapi.json.
Success Response (200 OK): HTML page with interactive API explorer.
Printer Status & Information
GET /api/ping
Swagger UI: GET /api/ping
Liveness probe: 200 whenever the gunicorn worker is alive and serving, independent of printer connection state. This is what the container's HEALTHCHECK polls — unlike /api/health_check below, it never reports unhealthy just because the printer is powered off.
Response: {"status": "alive"}
GET /api/printer
Swagger UI: GET /api/printer
Returns the complete serialised BambuPrinter object via BambuPrinter.toJson().
Condition: printer.recent_update must be truthy (i.e. a healthy MQTT data stream has been established). /api/health_check below is more permissive: it also succeeds when printer.printer_state.spools is non-empty, even without recent_update.
Success Response (200 OK): Full JSON document produced by BambuPrinter.toJson(), which recursively serialises all public attributes — _config, _service_state, _printer_state, _active_job_info, _sdcard_contents, _sdcard_3mf_files, etc.
Error Response (304 Not Modified):
GET /api/health_check
Swagger UI: GET /api/health_check
Health check that always attempts to return printer JSON regardless of connection state.
Logic: If not printer.recent_update and not printer.printer_state.spools (both false at once), the response is assembled as a 500 error tuple; otherwise 200 success.
Success Response (200 OK):
printer contains the full BambuPrinter.toJson() result.
Error Response (500 Internal Server Error) when no live data is available:
printer is an empty dict here — only the success response calls toJson().
Temperature Control
GET /api/set_tool_target_temp
Swagger UI: GET /api/set_tool_target_temp
Set the nozzle temperature target for the currently active extruder.
Library method: BambuPrinter.set_nozzle_temp_target(value, tool_num)
The active tool index is read from printer.printer_state.active_tool.value:
- Single-extruder printers (
active_tool = -1): sendsM104 S{temp}(noTargument). - H2D dual-extruder (
active_tool = 0or1): sendsM104 S{temp} T{active_tool}.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
temp |
int | yes | 0 |
Target nozzle temperature in °C. Values below 0 are clamped to 0. |
Example: /api/set_tool_target_temp?temp=220
Response: {"status": "success"}
GET /api/set_bed_target_temp
Swagger UI: GET /api/set_bed_target_temp
Set the heated bed temperature target.
Library method: BambuPrinter.set_bed_temp_target(value)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
temp |
int | yes | 0 |
Target bed temperature in °C. |
Example: /api/set_bed_target_temp?temp=60
Response: {"status": "success"}
GET /api/set_chamber_target_temp
Swagger UI: GET /api/set_chamber_target_temp
Set the chamber temperature target.
Library method: BambuPrinter.set_chamber_temp_target(value)
If the printer has capabilities.has_chamber_temp, sends SET_CHAMBER_TEMP_TARGET followed by SET_CHAMBER_AC_MODE (mode 0 for targets below 40 °C, mode 1 for 40 °C and above). Otherwise only stores the value locally — used by the external ChamberMonitor integration.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
temp |
int | yes | 0 |
Target chamber temperature in °C. |
Example: /api/set_chamber_target_temp?temp=45
Response: {"status": "success"}
Fan Control
GET /api/set_fan_speed_target
Swagger UI: GET /api/set_fan_speed_target
Set part-cooling fan speed.
Library method: BambuPrinter.set_part_cooling_fan_speed_target_percent(value)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
percent |
int | yes | 0 |
Target speed as a percentage (0–100). |
Example: /api/set_fan_speed_target?percent=75
Response: {"status": "success"}
GET /api/set_aux_fan_speed_target
Swagger UI: GET /api/set_aux_fan_speed_target
Set auxiliary fan speed.
Library method: BambuPrinter.set_aux_fan_speed_target_percent(value)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
percent |
int | yes | 0 |
Target speed as a percentage (0–100). |
Example: /api/set_aux_fan_speed_target?percent=50
Response: {"status": "success"}
GET /api/set_exhaust_fan_speed_target
Swagger UI: GET /api/set_exhaust_fan_speed_target
Set exhaust/chamber fan speed.
Library method: BambuPrinter.set_exhaust_fan_speed_target_percent(value)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
percent |
int | yes | 0 |
Target speed as a percentage (0–100). |
Example: /api/set_exhaust_fan_speed_target?percent=100
Response: {"status": "success"}
GET /api/set_enhanced_cooling_fan_speed_target
Swagger UI: GET /api/set_enhanced_cooling_fan_speed_target
Set the toolhead's Enhanced Cooling Fan (extension-tool accessory) speed. Sends M106 P9.
Library method: BambuPrinter.set_enhanced_cooling_fan_speed_target_percent(value)
The printer publishes no telemetry for this fan, so the commanded value is recorded as sticky state (BambuClimate.enhanced_cooling_fan_target_percent) and resets only when the extension tool leaves the MOUNTED state. Observed firmware behavior is effectively on/off (stock slicer G-code only issues S255 or S0); commands sent while the fan is unplugged are acknowledged and are harmless no-ops.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
percent |
int | yes | 0 |
Target speed as a percentage (0–100). |
Example: /api/set_enhanced_cooling_fan_speed_target?percent=100
Response: {"status": "success"}
Print Job Control
GET /api/print_3mf
Swagger UI: GET /api/print_3mf
Start a 3MF print job.
Library method: BambuPrinter.print_3mf_file(name, plate, bed, use_ams, ams_mapping, bedlevel, flow, timelapse)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
filename |
string | yes | "" |
Full path to the .3mf file on the printer SD card (e.g. /test.3mf). |
platenum |
int | no | 0 |
Plate index within the .3mf to print (0-based). |
plate |
string | yes | — | Plate/surface type. Must be a valid PlateType enum name: AUTO, COOL_PLATE, ENG_PLATE, HOT_PLATE, TEXTURED_PLATE, NONE. Omitting or supplying an invalid value causes a 500 error. |
use_ams |
bool | no | false |
Pass true to enable AMS filament feeding. Exact string "true" required. |
ams_mapping |
string | no | null |
JSON-encoded array of absolute tray IDs, one per filament slot. Values: 0–103 (4-slot AMS, ams_id * 4 + slot_id), 128–135 (single-slot AMS HT), -1 (unmapped). Example: "[0,4,-1]". For an external-spool print pass use_ams=false and leave this empty: the library derives the holder of each filament from the plate. |
bl |
bool | no | false |
Pass true to enable bed levelling before print. |
flow |
bool | no | false |
Pass true to enable flow-rate calibration before print. |
tl |
bool | no | false |
Pass true to enable timelapse recording. |
Example:
/api/print_3mf?filename=/test.3mf&platenum=1&plate=COOL_PLATE&use_ams=true&ams_mapping=[0,4]&bl=true&flow=true&tl=false
Response: {"status": "success"}
Error Response (400 Bad Request), when the library refuses the print, for example a dual-nozzle plate that carries no extruder map:
GET /api/pause_printing
Swagger UI: GET /api/pause_printing
Pause the current print job.
Library method: BambuPrinter.pause_printing()
Response: {"status": "success"}
GET /api/resume_printing
Swagger UI: GET /api/resume_printing
Resume a paused print job.
Library method: BambuPrinter.resume_printing()
Response: {"status": "success"}
GET /api/stop_printing
Swagger UI: GET /api/stop_printing
Cancel/stop the current print job.
Library method: BambuPrinter.stop_printing()
Response: {"status": "success"}
GET /api/skip_objects
Swagger UI: GET /api/skip_objects
Skip one or more objects during an active print (uses the printer's exclude-object feature).
Library method: BambuPrinter.skip_objects(objects)
The objects list is split on commas and passed directly to the library. The integer identify_id values for each object are obtained from get_3mf_props_for_file → metadata.map.bbox_objects[n].id.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
objects |
string | yes | "" |
Comma-separated list of integer object identify_id values to skip. |
Example: /api/skip_objects?objects=1,3,7
Response: {"status": "success"}
Filament Management
GET /api/load_filament
Swagger UI: GET /api/load_filament
Load filament from the specified AMS slot or external spool.
Library method: BambuPrinter.load_filament(slot_id, ams_id=0)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
slot |
int | yes | 0 |
AMS slot index (0–3 within a unit) or 254/255 for an external spool holder. Passed as slot_id to the library. |
ams_id |
int | no | 0 |
AMS unit (0–3, 128+ for AMS HT). Passed as ams_id to the library. |
Example: /api/load_filament?slot=2&ams_id=0
Response: {"status": "success"}
GET /api/unload_filament
Swagger UI: GET /api/unload_filament
Unload the currently loaded filament.
Library method: BambuPrinter.unload_filament(ams_id=0)
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
ams_id |
int | no | 0 |
The AMS unit, or external holder (254/255), to unload from. |
Example: /api/unload_filament?ams_id=0
Response: {"status": "success"}
GET /api/refresh_spool_rfid
Swagger UI: GET /api/refresh_spool_rfid
Request the printer to re-read the RFID tag for a specific AMS slot.
Library method: BambuPrinter.refresh_spool_rfid(slot_id, ams_id=ams_id)
Only RFID-equipped Bambu Lab spools carry tag data. The printer pushes updated telemetry after scanning, which triggers on_printer_update and a printer_update Socket.IO event.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
slot_id |
int | yes | 0 |
Slot position within the AMS unit (0–3). |
ams_id |
int | yes | 0 |
AMS unit ID (typically 0–3). |
Example: /api/refresh_spool_rfid?slot_id=1&ams_id=0
Response: {"status": "success"}
GET /api/set_spool_details
Swagger UI: GET /api/set_spool_details
Set custom filament details for an AMS tray.
Library method: BambuPrinter.set_spool_details(tray_id, tray_info_idx, tray_id_name, tray_type, tray_color, nozzle_temp_min, nozzle_temp_max, ams_id=0) — the route never passes ams_id; the library derives it from tray_id regardless (the parameter is unused).
The endpoint sleeps 2 seconds after issuing the command to allow the printer to process the update before responding.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
tray_id |
int | yes | 0 |
Global tray ID. 0–15 for 4-slot AMS units; 254 or 255 for external spools. |
tray_info_idx |
string | yes | "" |
Bambu filament preset index (e.g. GFL99). |
tray_id_name |
string | no | "" |
Display name for the spool. Omit to leave unchanged. |
tray_type |
string | no | "" |
Filament material type string (e.g. PLA, PETG-CF). |
tray_color |
string | no | "" |
Spool colour as a hex string (e.g. #FF5733). |
nozzle_temp_min |
int | no | -1 |
Minimum recommended nozzle temperature in °C. Pass -1 to leave unchanged. |
nozzle_temp_max |
int | no | -1 |
Maximum recommended nozzle temperature in °C. Pass -1 to leave unchanged. |
Example:
/api/set_spool_details?tray_id=0&tray_info_idx=GFL99&tray_id_name=My%20PLA&tray_type=PLA&tray_color=%23FF5733&nozzle_temp_min=200&nozzle_temp_max=230
Response (after 2-second delay): {"status": "success"}
GET /api/set_spool_k_factor
Swagger UI: GET /api/set_spool_k_factor
Stub endpoint — no operation is currently performed.
The implementation body is commented out in source. The endpoint accepts tray_id but ignores it and immediately returns success. The underlying library method, BambuPrinter.set_spool_k_factor(), is itself deprecated (broken in recent Bambu firmware) and is not called by this route — see Library-Only Methods.
Response: {"status": "success"}
GET /api/filament_catalog
Swagger UI: GET /api/filament_catalog
Return bpm's built-in filament catalog: one entry per Bambu-recognised tray_info_idx (e.g. GFL99), carrying the printer-database defaults for that filament (nozzle temperature range, drying softening/cooling temperature, bed type, etc). Used by the frontend to populate filament pickers and by /api/start_ams_dryer to derive a safe default cooling_temp.
Response (200 OK): JSON array of catalog entry objects (bpm.bambucommands.FILAMENT_CATALOG).
GET /api/start_ams_dryer
Swagger UI: GET /api/start_ams_dryer
Start the dryer on an AMS unit that has one (AMS 2 Pro, AMS HT).
Library method: BambuPrinter.turn_on_ams_dryer(target_temp, duration, cooling_temp, rotate_tray, ams_id, filament_type)
The route validates before publishing anything: ams_id must name a connected AMS unit that reports a dryer (an AMS Lite has none); temp must fall within the model's drying range (AMS_2_PRO: 45–65 °C, AMS_HT: 45–85 °C — limits mirrored from Bambu Studio's AMSDryControl.cpp, enforced only here, not by bpm or the firmware); hours must be 1–999 (the longest dry an H2D was measured to accept; Studio's 24 h cap is UI-only). cooling_temp is derived automatically, mirroring Bambu Studio: the lowest drying_softening_temp among the unit's loaded spools' catalog entries (from /api/filament_catalog), or 50 °C when none is known. filament_type is taken from the first loaded spool that reports one.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ams_id |
int | yes | The AMS unit to dry. |
temp |
int | yes | Target drying temperature in °C (see per-model range above). |
hours |
int | yes | Drying duration, 1–999 hours. |
rotate |
bool | no | Exact string "true" rotates the tray during drying; anything else (default) does not. |
Example: /api/start_ams_dryer?ams_id=0&temp=55&hours=4&rotate=true
Response: {"status": "success"}
Error Response (400 Bad Request) — {"status": "error", "reason": "<reason>"} — for a missing/non-integer ams_id, temp, or hours; an ams_id with no matching AMS unit, or one that has not reported yet, or one with no dryer; a temp outside the model's range; or hours outside 1–999.
GET /api/stop_ams_dryer
Swagger UI: GET /api/stop_ams_dryer
Stop the dryer on an AMS unit.
Library method: BambuPrinter.turn_off_ams_dryer(ams_id)
Same ams_id validation as /api/start_ams_dryer (must name a connected, dryer-capable AMS unit).
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
ams_id |
int | yes | The AMS unit whose dryer should stop. |
Example: /api/stop_ams_dryer?ams_id=0
Response: {"status": "success"}
Error Response (400 Bad Request): {"status": "error", "reason": "<reason>"} for a missing/non-integer ams_id, or one naming no connected dryer-capable unit.
File Management
All file operations use FTPS to communicate with the printer SD card.
GET /api/get_sdcard_contents
Swagger UI: GET /api/get_sdcard_contents
Return the cached SD card file tree (populated by the last get_sdcard_contents() call).
Library method: BambuPrinter.get_sdcard_contents() — performs a live FTPS listing and updates the internal cache. It returns None when the listing failed (a timeout, a dropped connection, or a folder that could not be listed) and clears the cache; an empty card is a tree whose children is empty. The route answers 502 {"status": "error", "reason": "SD card listing failed"} for a failed listing.
Response: Alphabetically sorted tree structure:
{
"name": "/",
"id": "/",
"children": [
{
"name": "Projects",
"id": "/Projects/",
"children": [
{
"name": "model.3mf",
"id": "/Projects/model.3mf",
"size": 1048576
}
]
},
{
"name": "test.3mf",
"id": "/test.3mf",
"size": 204800
}
]
}
Folder nodes have a children array; file nodes have a size field (bytes). Folders sort before files at every level.
GET /api/refresh_sdcard_contents
Swagger UI: GET /api/refresh_sdcard_contents
Refresh the SD card file listing from the printer via FTPS and return success.
Library method: BambuPrinter.get_sdcard_contents() — also rebuilds the 3MF-only cache.
Response: {"status": "success"}
GET /api/get_sdcard_3mf_files
Swagger UI: GET /api/get_sdcard_3mf_files
Return the SD card tree filtered to .3mf files only (all other file types stripped, empty folders retained).
Library method: BambuPrinter.get_sdcard_3mf_files() — also triggers a full get_sdcard_contents() refresh internally.
Response: Same tree structure as get_sdcard_contents but with non-.3mf files removed.
GET /api/refresh_sdcard_3mf_files
Swagger UI: GET /api/refresh_sdcard_3mf_files
Refresh the SD card listing (both full and 3MF-only caches) via FTPS and return success.
Library method: BambuPrinter.get_sdcard_3mf_files() which internally calls get_sdcard_contents().
Response: {"status": "success"}
GET /api/delete_sdcard_file
Swagger UI: GET /api/delete_sdcard_file
Delete a file or folder from the SD card via FTPS.
Library method: BambuPrinter.delete_sdcard_file(file) for files; BambuPrinter.delete_sdcard_folder(path) for folders (when file ends with /). The folder variant recursively deletes all contents before removing the directory.
After deletion, both the full file cache and the 3MF cache are updated in-memory. The response is the updated _sdcard_contents tree.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
file |
string | yes | SD card path. Files: /path/file.3mf. Folders: /path/folder/ (trailing slash selects folder deletion). |
Example: /api/delete_sdcard_file?file=/old_print.3mf
Response: Updated SD card file tree (same structure as get_sdcard_contents).
GET /api/make_sdcard_directory
Swagger UI: GET /api/make_sdcard_directory
Create a new directory on the SD card via FTPS.
Library method: BambuPrinter.make_sdcard_directory(dir) — creates the directory then calls get_sdcard_contents().
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
dir |
string | yes | Full path for the new directory (trailing slash recommended). |
Example: /api/make_sdcard_directory?dir=/Projects/new_folder/
Response: Updated SD card file tree (same structure as get_sdcard_contents).
GET /api/rename_sdcard_file
Swagger UI: GET /api/rename_sdcard_file
Rename or move a file/folder on the SD card via FTPS.
Library method: BambuPrinter.rename_sdcard_file(src, dest) — renames then calls get_sdcard_contents().
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
src |
string | yes | Source path on SD card. |
dest |
string | yes | Destination path on SD card. |
Example: /api/rename_sdcard_file?src=/old.3mf&dest=/archive/old.3mf
Response: Updated SD card file tree (same structure as get_sdcard_contents).
POST /api/upload_file_to_host
Swagger UI: POST /api/upload_file_to_host
Upload a file to the API server's local staging directory, ./uploads/{BAMBU_SERIAL_NUMBER}/. Each container serves exactly one printer, and staging under the printer's own serial keeps two containers sharing the same host uploads/ mount from colliding on identically-named files.
Method: POST only.
Form Data:
| Field | Type | Required | Description |
|---|---|---|---|
myFile |
file | yes | File to upload. |
The uploaded filename is sanitised by staged_filename() (Werkzeug's secure_filename()); when sanitisation changes the name (e.g. it contains +, &, or other characters outside [A-Za-z0-9_.-]), an 8-character digest of the original filename is appended before the extension so two different original names can never collide on the same staged name. The response reports the staged name — pass it, not the original filename, to /api/upload_file_to_printer's src parameter.
Success Response (200 OK):
Error Response (400 Bad Request):
{"status": "error", "reason": "invalid filename"} when sanitisation yields no usable name, or {"status": "error", "reason": "invalid path"} on the (normally unreachable) traversal-containment check.
GET /api/upload_file_to_printer
Swagger UI: GET /api/upload_file_to_printer
Transfer a file from the server's per-printer staging directory (./uploads/{BAMBU_SERIAL_NUMBER}/) to the printer SD card via FTPS.
Library method: BambuPrinter.upload_sdcard_file(src, dest) — uploads the file, then if it is a .3mf file runs get_project_info to cache its metadata, then calls get_sdcard_contents() to refresh the file tree. src is resolved by the route against this container's own staging directory before being passed to the library, and is rejected before any FTPS call if it would resolve outside that directory.
Accepts both GET and POST methods.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
src |
string | yes | Filename in this container's ./uploads/{BAMBU_SERIAL_NUMBER}/ directory (the staged name returned by /api/upload_file_to_host) — never a path that escapes it. |
dest |
string | yes | Full destination path on SD card (e.g. /prints/model.3mf). |
Example: /api/upload_file_to_printer?src=model-3f2a9c1b.3mf&dest=/prints/model.3mf
Response: Updated SD card file tree (same structure as get_sdcard_contents).
Error Response (400 Bad Request): {"status": "error", "reason": "invalid src path"} when src would resolve outside the staging directory (e.g. a ../ traversal).
GET /api/download_file_from_printer
Swagger UI: GET /api/download_file_from_printer
Download a file from the printer SD card. The file is saved to this container's per-printer staging directory, ./uploads/{BAMBU_SERIAL_NUMBER}/, and then streamed to the client.
Library method: BambuPrinter.download_sdcard_file(src, dest) — dest is built by the route from the filename portion of src, resolved against the staging directory.
Accepts both GET and POST methods.
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
src |
string | yes | Full path on the SD card (e.g. /test.3mf). The filename is extracted after the last /. |
Example: /api/download_file_from_printer?src=/test.3mf
Response: Binary file download (content-type determined by Flask's send_from_directory).
Error Response (400 Bad Request): {"status": "error", "reason": "invalid filename"} when src ends in /, /., or /.. (an empty, ., or .. filename), or when the resolved destination would escape the staging directory.
GET /api/get_3mf_props_for_file
Swagger UI: GET /api/get_3mf_props_for_file
Parse and return metadata for a specific .3mf file.
Library method: get_project_info(file, printer, plate_num=plate, use_cached_list=True)
Returns a dataclasses.asdict(ProjectInfo) result.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
file |
string | yes | "" |
Full SD card path to the .3mf file. |
plate |
int | no | 0 |
Plate number to retrieve metadata for (1-based). 0 (the route's own default when omitted, distinct from the library's own default of 1) is not a valid plate number in any .3mf. When a cached <file>-N.json metadata file already exists for the file, get_project_info first substitutes whichever cached plate sorts first lexicographically (not necessarily the lowest or first-in-file plate number) as the requested plate number; if that cache entry is still valid (matching timestamp/size, or matching md5) it is served straight from cache without opening the .3mf, otherwise the .3mf is re-parsed and the first plate number found in the file is used. |
Example: /api/get_3mf_props_for_file?file=/test.3mf&plate=1
Success Response (200 OK):
{
"id": "/test.3mf",
"name": "test.3mf",
"size": 204800,
"timestamp": 1700000000,
"md5": "A1B2C3D4...",
"plate_num": 1,
"plates": [1, 2],
"metadata": {
"thumbnail": "data:image/png;base64,...",
"topimg": "data:image/png;base64,...",
"filament": [
{"id": 1, "type": "PLA", "color": "#FF0000"},
{"id": 2, "type": "PETG", "color": "#0000FF"}
],
"ams_mapping": ["1", "2"],
"filament_extruders": [1, 2],
"physical_extruder_map": [1, 0],
"external_spool_trays": [254, 255],
"map": {
"filament_ids": ["..."],
"filament_colors": ["#FF0000", "#0000FF"],
"bbox_objects": [
{"id": 1, "name": "Part_1", "val": [0.0, 0.0, 50.0, 50.0]},
{"id": 2, "name": "Support_1", "val": [0.0, 0.0, 50.0, 50.0]}
]
},
"slicer_settings": {
"enable_support": "1",
"support_type": "normal",
"brim_type": "no_brim",
"brim_width": "5",
"raft_layers": "0",
"sparse_infill_density": "15%",
"wall_loops": "2",
"layer_height": "0.2",
"initial_layer_height": "0.2"
}
}
}
metadata.slicer_settings keys are always present. Each falls back to a hard-coded default (enable_support/raft_layers/brim_width: "0", support_type: "normal", brim_type: "no_brim", sparse_infill_density: "15%", wall_loops: "2", layer_height/initial_layer_height: "0.2") when Metadata/project_settings.config is absent from the .3mf (older BambuStudio exports may lack it) or lacks that key.
metadata.ams_mapping is a placeholder in the shape of print_3mf's ams_mapping parameter, not a tray assignment: index id - 1 holds str(id) for each filament and "-1" fills the gaps. The .3mf carries no tray ids, so build the real mapping from the spools loaded on the printer.
metadata.filament_extruders is the slicer's 1-based logical extruder per filament and metadata.physical_extruder_map maps each logical extruder to a physical one (0 main, 1 deputy; [1, 0] on H2D, where logical extruder 1 is the left one). metadata.external_spool_trays is the external spool holder that feeds each filament, at index id - 1: 255 right/main, 254 left/deputy, -1 unused. Single-nozzle printers report 255, the wire id, although their telemetry names the one holder tray 254. It is an empty list when a dual-nozzle plate has no extruder map, which is also when print_3mf refuses the print.
The metadata.map.bbox_objects[n].id integer is the identify_id required by skip_objects.
Error Response (404 Not Found):
GET /api/get_current_3mf_props
Swagger UI: GET /api/get_current_3mf_props
Return metadata for the currently active print job.
Checks printer.active_job_info.project_info and returns it if project_info.id is non-empty.
Success Response (200 OK): dataclasses.asdict(ProjectInfo) with "status": "success" merged in. Same schema as get_3mf_props_for_file.
Error Response (404 Not Found):
GET /api/retry_project_info
Swagger UI: GET /api/retry_project_info
Reset the project-info fetch flag so bpm's fallback re-runs on the next MQTT update. Useful when /api/get_current_3mf_props keeps returning 404 for a job that was already running when the API server started (bpm's normal fetch-on-job-start path was missed).
Implementation: directly clears printer._active_job_info.project_info_fetch_attempted and printer._active_job_info.project_info — not a BambuPrinter public method.
Response: {"status": "success"}
Tool Control (Dual Extruder)
These endpoints are only meaningful on H2D / H2D Pro printers with dual extruders.
GET /api/toggle_active_tool
Swagger UI: GET /api/toggle_active_tool
Switch between right (0) and left (1) extruders on H2D / H2D Pro printers.
Library method: BambuPrinter.set_active_tool(tool)
Computes the target tool as abs(active_tool.value - 1):
- If
active_toolisRIGHT_EXTRUDER (0)→ switches to1(left). - If
active_toolisLEFT_EXTRUDER (1)→ switches to0(right).
Response: {"status": "success"}
GET /api/set_nozzle_details
Swagger UI: GET /api/set_nozzle_details
Set the nozzle diameter and material type for the active extruder.
Library method: BambuPrinter.set_nozzle_details(nozzle_diameter, nozzle_type, nozzle_flow, extruder_id)
The endpoint sleeps 1 second after issuing the command before responding.
nozzle_diameter is parsed via NozzleDiameter(float(...)), nozzle_type via NozzleType[...], and nozzle_flow via NozzleFlowType[...]. Supplying an invalid value for any of the three raises a ValueError / KeyError which is caught by the 500 error handler — including omitting nozzle_flow entirely, since the route does not default it (NozzleFlowType[""] raises KeyError).
For a single-extruder printer (not capabilities.has_dual_extruder) the library sends SET_ACCESSORIES and nozzle_flow/extruder_id are accepted but unused. For a dual-extruder printer (H2D / H2D Pro) it sends SET_NOZZLE instead, which encodes nozzle_flow + nozzle_type + nozzle_diameter into a single identifier string (e.g. HH01) and targets extruder_id (or the currently active tool when extruder_id is -1).
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
nozzle_diameter |
float | yes | 0.2, 0.4, 0.6, 0.8 |
Nozzle diameter in mm (NozzleDiameter enum values). |
nozzle_type |
string | yes | STAINLESS_STEEL, HARDENED_STEEL, TUNGSTEN_CARBIDE, BRASS, E3D |
Nozzle material (NozzleType enum name). |
nozzle_flow |
string | yes | STANDARD, HIGH_FLOW, TPU_HIGH_FLOW |
Nozzle flow family (NozzleFlowType enum name). Only meaningful on dual-extruder printers, but the route requires a valid value regardless. |
extruder_id |
int | no | -1 |
Dual-extruder printers only: which extruder the nozzle is installed in. -1 (default) targets the currently active tool. |
Example: /api/set_nozzle_details?nozzle_diameter=0.4&nozzle_type=HARDENED_STEEL&nozzle_flow=STANDARD&extruder_id=-1
Response (after 1-second delay): {"status": "success"}
GET /api/refresh_nozzles
Swagger UI: GET /api/refresh_nozzles
Request the printer to push current nozzle info in its next push_status message.
Library method: BambuPrinter.refresh_nozzles()
Relevant only on models with support_refresh_nozzle capability (H2D, H2D Pro).
Response: {"status": "success"}
Detection & Safety
GET /api/set_buildplate_marker_detector
Swagger UI: GET /api/set_buildplate_marker_detector
Enable or disable the build-plate ArUco marker detector. The camera reads ArUco fiducial markers printed on the build surface before the print starts to verify the plate type (e.g. textured PEI vs. smooth PEI). If the plate is incompatible with the sliced settings, the printer pauses before the first layer. Runs pre-print only — not during the print. No sensitivity parameter. Disable if your plate's markers are worn or you are using a third-party plate.
Library method: BambuPrinter.set_buildplate_marker_detector(enabled)
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
enabled |
bool | yes | Exact string "true" enables; anything else disables. |
Example: /api/set_buildplate_marker_detector?enabled=true
Response: {"status": "success"}
GET /api/set_spaghetti_detector
Swagger UI: GET /api/set_spaghetti_detector
Enable or disable the spaghetti / failed-print detector. Detects loose filament strands extruded in mid-air rather than adhering to the print — the classic sign of a delaminated or detached print. When triggered, the printer halts.
Library method: BambuPrinter.set_spaghetti_detector(enabled, sensitivity)
Parameters:
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
enabled |
bool | yes | — | "true" / other |
Enable or disable. |
sensitivity |
string | no | "medium" |
"low", "medium", "high" |
Detection sensitivity (DetectorSensitivity string value). |
Example: /api/set_spaghetti_detector?enabled=true&sensitivity=high
Currently broken: the route passes sensitivity straight through as the raw query string (request.args.get("sensitivity", "medium")), but BambuPrinter.set_spaghetti_detector reads sensitivity.value — a str has no .value. Every call raises AttributeError: 'str' object has no attribute 'value', which the 500 error handler reports instead of the success response below.
Response: {"status": "success"} (never actually returned — see above)
GET /api/set_purgechutepileup_detector
Swagger UI: GET /api/set_purgechutepileup_detector
Enable or disable the purge-chute pile-up detector.
Library method: BambuPrinter.set_purgechutepileup_detector(enabled, sensitivity)
Parameters:
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
enabled |
bool | yes | — | "true" / other |
Enable or disable. |
sensitivity |
string | no | "medium" |
"low", "medium", "high" |
Detection sensitivity. |
Example: /api/set_purgechutepileup_detector?enabled=true&sensitivity=medium
Currently broken: same defect as /api/set_spaghetti_detector above — the route passes sensitivity as a raw string, but BambuPrinter.set_purgechutepileup_detector calls sensitivity.value on it, raising AttributeError: 'str' object has no attribute 'value' on every call.
Response: {"status": "success"} (never actually returned — see above)
GET /api/set_nozzleclumping_detector
Swagger UI: GET /api/set_nozzleclumping_detector
Enable or disable the nozzle-clumping detector (X-Cam AI vision). Detects filament accumulating as a blob around the nozzle tip. This is the newer, preferred path for nozzle blob detection — it supersedes the NOZZLE_BLOB_DETECT PrintOption (home_flag) on supported printers and adds sensitivity control.
Library method: BambuPrinter.set_nozzleclumping_detector(enabled, sensitivity)
Parameters:
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
enabled |
bool | yes | — | "true" / other |
Enable or disable. |
sensitivity |
string | no | "medium" |
"low", "medium", "high" |
Detection sensitivity. |
Example: /api/set_nozzleclumping_detector?enabled=true&sensitivity=low
Currently broken: same defect as /api/set_spaghetti_detector above — the route passes sensitivity as a raw string, but BambuPrinter.set_nozzleclumping_detector calls sensitivity.value on it, raising AttributeError: 'str' object has no attribute 'value' on every call.
Response: {"status": "success"} (never actually returned — see above)
GET /api/set_airprinting_detector
Swagger UI: GET /api/set_airprinting_detector
Enable or disable the air-printing / no-extrusion detector (X-Cam AI vision). Detects the nozzle extruding into open air, indicating a clog or filament grinding. This is the newer, preferred path — it supersedes the AIR_PRINT_DETECT PrintOption (home_flag) on supported printers and adds sensitivity control.
Library method: BambuPrinter.set_airprinting_detector(enabled, sensitivity)
Parameters:
| Name | Type | Required | Default | Allowed values | Description |
|---|---|---|---|---|---|
enabled |
bool | yes | — | "true" / other |
Enable or disable. |
sensitivity |
string | no | "medium" |
"low", "medium", "high" |
Detection sensitivity. |
Example: /api/set_airprinting_detector?enabled=true&sensitivity=medium
Currently broken: same defect as /api/set_spaghetti_detector above — the route passes sensitivity as a raw string, but BambuPrinter.set_airprinting_detector calls sensitivity.value on it, raising AttributeError: 'str' object has no attribute 'value' on every call.
Response: {"status": "success"} (never actually returned — see above)
AMS Control
GET /api/send_ams_control_command
Swagger UI: GET /api/send_ams_control_command
Send a control command to the AMS system.
Library method: BambuPrinter.send_ams_control_command(ams_cmd)
The cmd value is resolved via AMSControlCommand[cmd.upper()]. Invalid names raise a KeyError → 500.
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
cmd |
string | yes | PAUSE, RESUME, RESET, DONE, ABORT |
AMS control command (AMSControlCommand enum name). RESUME also resumes the print. |
Example: /api/send_ams_control_command?cmd=RESET
Response: {"status": "success"}
GET /api/hms_action
Press a printer prompt button. The buttons for the current print_error are the actions of its device_error entry in hms_errors.
Library method: BambuPrinter.send_hms_action(id) — sends what Bambu Studio sends for that button (resume, done or abort as ams_control alone, or clean_print_error).
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
id |
int | yes | an HMSAction id, e.g. 9 CONTINUE, 7 FILAMENT_EXTRUDED, 51 ABORT |
The button pressed. |
Example: /api/hms_action?id=9
Response: {"status": "success", "sent": true}. sent is false for a button that sends nothing (Check Assistant, Cancel). A button bpm cannot send answers 400 with {"status": "error", "error": "..."}.
GET /api/clear_command_errors
Swagger UI: GET /api/clear_command_errors
Drop every refused-command entry (type command_error) from printer_state.hms_errors — e.g. when the user dismisses one in the UI. Nothing is sent to the printer.
Library method: BambuPrinter.clear_command_errors()
Response: {"status": "success"}
GET /api/set_ams_user_setting
Swagger UI: GET /api/set_ams_user_setting
Configure an AMS user setting.
Library method: BambuPrinter.set_ams_user_setting(setting, enabled)
The setting value is resolved via AMSUserSetting[setting.upper()]. Invalid names raise a KeyError → 500.
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
setting |
string | yes | CALIBRATE_REMAIN_FLAG, STARTUP_READ_OPTION, TRAY_READ_OPTION |
Setting to modify (AMSUserSetting enum name). CALIBRATE_REMAIN_FLAG enables weight-sensor-based remaining estimation — AMS 2 Pro only (AMS Lite and AMS HT lack weight sensors). |
enabled |
bool | yes | "true" / other |
Enable or disable the setting. |
Example: /api/set_ams_user_setting?setting=STARTUP_READ_OPTION&enabled=true
Response: {"status": "success"}
Advanced Settings
GET /api/send_gcode
Swagger UI: GET /api/send_gcode
Send one or more raw G-code commands to the printer.
Library method: BambuPrinter.send_gcode(gcode) — wraps the command in SEND_GCODE_TEMPLATE and publishes via MQTT.
Pipe characters (|) in the gcode parameter are converted to newlines (\n) before being sent, allowing multiple commands in a single URL.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
gcode |
string | yes | "" |
G-code string. Use \| in the URL to separate multiple commands. |
Example: /api/send_gcode?gcode=G28|G1 Z10 F600|M104 S200
Response: {"status": "success"}
Warning
Direct G-code bypasses all safety interlocks. Incorrect commands can damage the printer.
GET /api/set_print_option
Swagger UI: GET /api/set_print_option
Enable or disable a printer option.
Library method: BambuPrinter.set_print_option(option, enabled)
The option value is resolved via PrintOption[option.upper()]. Invalid names raise a KeyError → 500.
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
option |
string | yes | AUTO_RECOVERY, FILAMENT_TANGLE_DETECT, SOUND_ENABLE, AUTO_SWITCH_FILAMENT, NOZZLE_BLOB_DETECT, AIR_PRINT_DETECT |
Option to modify (PrintOption enum name). See descriptions below. |
enabled |
bool | yes | "true" / other |
Enable or disable the option. |
Option descriptions:
| Option | Description |
|---|---|
AUTO_RECOVERY |
Resume print automatically after power loss or fault. |
FILAMENT_TANGLE_DETECT |
Pause if AMS sensors detect a tangle. AMS-only — no effect on external spool prints. |
SOUND_ENABLE |
Enable audible beep notifications. |
AUTO_SWITCH_FILAMENT |
Auto-switch to another AMS slot when the active spool runs out. Target slot must have the same filament type AND color. AMS-hosted spools only. |
NOZZLE_BLOB_DETECT |
Legacy firmware-level nozzle blob detection (home_flag). On supported printers, prefer set_nozzleclumping_detector (xcam AI, adds sensitivity). |
AIR_PRINT_DETECT |
Legacy firmware-level air-printing detection (home_flag). On supported printers, prefer set_airprinting_detector (xcam AI, adds sensitivity). |
Example: /api/set_print_option?option=AUTO_RECOVERY&enabled=true
Response: {"status": "success"}
GET /api/set_light_state
Swagger UI: GET /api/set_light_state
Control the chamber and column LED lights.
Library method: BambuPrinter.light_state = bool
Setting the property publishes CHAMBER_LIGHT_TOGGLE commands for three light nodes: chamber_light, chamber_light2, and column_light.
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
state |
string | yes | "on", any other string |
"on" turns all lights on; any other value turns them off. |
Example: /api/set_light_state?state=on
Response: {"status": "success"}
Note: The application also automatically controls lights based on print state transitions and chamber door sensor events (when capabilities.has_chamber_door_sensor is true).
GET /api/set_speed_level
Swagger UI: GET /api/set_speed_level
Set the print speed profile.
Library method: BambuPrinter.speed_level = str
The route always passes a plain string (str(request.args.get("level"))), so the setter's isinstance(value, SpeedLevel) and isinstance(value, int) branches never match from this endpoint — it always falls to SpeedLevel[str(value).upper()].value, a lookup by enum name, not by digit. Publishes SPEED_PROFILE_TEMPLATE with the resolved numeric code ("1"–"4") as the param field.
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
level |
string | yes | "quiet" (→1), "standard" (→2), "sport" (→3), "ludicrous" (→4) — case-insensitive SpeedLevel member name |
Speed profile to select. |
Example: /api/set_speed_level?level=sport
Error Response (500 Internal Server Error) for any value that is not one of the four names above, including a bare digit like "2" (KeyError: '2' — SpeedLevel is looked up by name here, not by value).
Response: {"status": "success"}
Telemetry & Data
GET /api/get_all_data
Swagger UI: GET /api/get_all_data
Return the full telemetry history used for charting, combined with the current printer state.
Calls build_all_data() internally. See build_all_data() Response Schema for the complete schema.
Response (200 OK): build_all_data() result. See schema section below.
GET /api/zoom_in
Swagger UI: GET /api/zoom_in
Zoom in on a telemetry chart (reduce the visible history window by 500 seconds per call).
Finds the named collection in ds.collections and decrements its zoom by 500 seconds. Minimum zoom window is 500 seconds. If the collection has fewer than 500 seconds of data, the call is a no-op.
If zoom is currently 0 (show all data), it is first set to min(3600, max_age) before decrementing.
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
name |
string | yes | tool, bed, chamber, fan, aux_fan, exhaust_fan, heatbreak_fan, tool_0, tool_1 |
Collection name to zoom. Typically tool, bed, chamber, or fan. |
Example: /api/zoom_in?name=tool
Response: {"status": "success", "printer": {}}
GET /api/zoom_out
Swagger UI: GET /api/zoom_out
Zoom out on a telemetry chart (increase the visible history window by 500 seconds per call).
If zoom + 500 >= max_age, zoom resets to 0 (show all data).
Parameters:
| Name | Type | Required | Allowed values | Description |
|---|---|---|---|---|
name |
string | yes | tool, bed, chamber, fan, aux_fan, exhaust_fan, heatbreak_fan, tool_0, tool_1 |
Collection name to zoom. |
Example: /api/zoom_out?name=bed
Response: {"status": "success", "printer": {}}
GET /api/dump_data_ds.collections
Swagger UI: GET /api/dump_data_ds.collections
Dump all internal DataCollection objects as newline-delimited JSON (JSONL), one collection per line.
Response: Plain text, MIME type application/jsonl+json. Each line is one JSON-serialised DataCollection object.
Currently broken: the route calls json.dumps(..., default=ds.printer.jsonSerializer, ...), but jsonSerializer is a module-level function in bpm.bambutools — it is imported into bpm.bambuprinter's module namespace, not bound as a BambuPrinter attribute. ds.printer.jsonSerializer raises AttributeError, which the 500 error handler reports as {"status": "error", "message": "AttributeError: 'BambuPrinter' object has no attribute 'jsonSerializer'", ...} instead of the JSONL success response described above.
System & Diagnostics
GET /api/toggle_session
Swagger UI: GET /api/toggle_session
Pause or resume the MQTT connection to the printer.
Library methods: BambuPrinter.pause_session() / BambuPrinter.resume_session()
- If
service_stateisCONNECTED→ callspause_session(). - If
service_stateisPAUSED→ callsresume_session().
Response:
state is the ServiceState enum name after the toggle: "PAUSED" or "CONNECTED".
GET /api/trigger_printer_refresh
Swagger UI: GET /api/trigger_printer_refresh
Force a printer reconnection or refresh.
Library methods: BambuPrinter.quit() + start_session() (reconnect, run on a background thread) when disconnected; BambuPrinter.refresh() (synchronous) when connected.
- If
service_stateis notCONNECTEDand notPAUSED: a single-flight lock guards against overlapping reconnects. - If a reconnect is already running, the request returns immediately without starting another.
- Otherwise a background thread calls
quit(), waits 1 second, callsstart_session(), and loops (retryingstart_session()oninternalException) untilCONNECTED— this can take an unbounded amount of time when the printer is unreachable. The thread also respawns the telemetryDataCollectorthread if it is not alive, since aquit()/start_session()cycle terminates the old one. - Otherwise (already
CONNECTEDorPAUSED): callsrefresh()synchronously to request apush_statusfrom the printer.
Response — one of three shapes depending on which branch ran:
status |
Meaning |
|---|---|
"accepted" |
Not connected; a background reconnect was just started. |
"reconnecting" |
Not connected; a reconnect was already in progress, so this call was a no-op. |
"success" |
Already connected or paused; refresh() ran synchronously. |
All three shapes are {"status": "<one of the above>", "printer": {}}. printer is always an empty dict in this response. Call /api/printer or /api/get_all_data for current state, and poll /api/printer (or /api/health_check) to detect when an "accepted" reconnect has actually finished.
GET /api/toggle_verbosity
Swagger UI: GET /api/toggle_verbosity
Toggle the root logger between DEBUG and INFO level, and optionally set config.verbose.
The level always toggles based on the current level (not the verbose parameter): INFO → DEBUG, DEBUG → INFO. The verbose parameter independently sets printer.config.verbose.
Parameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
verbose |
bool | no | "false" |
Exact string "true" sets printer.config.verbose = True; anything else sets it False. Does not control which log level is selected. |
Example: /api/toggle_verbosity?verbose=true
Response:
level is the new log level name ("DEBUG" or "INFO"). verbose mirrors the value passed in.
GET /api/dump_log
Swagger UI: GET /api/dump_log
Retrieve the contents of ./output.log.
Response: Plain text, MIME type application/jsonl+json. Empty string if the file does not exist.
GET /api/truncate_log
Swagger UI: GET /api/truncate_log
Clear (truncate to zero bytes) ./output.log.
Response: {"status": "success"}
GET /api/fake_error
Swagger UI: GET /api/fake_error
Intentionally raise a ZeroDivisionError to test the 500 error handler.
Response (500 Internal Server Error):
{
"status": "error",
"message": "ZeroDivisionError: division by zero",
"stacktrace": "Traceback (most recent call last):\n ..."
}
Socket.IO Events
The server uses Flask-SocketIO with async_mode="threading" and cors_allowed_origins="*". Connect to the server root at http://localhost:5000 using any Socket.IO v4 client.
Event: printer_update
Direction: Server → Client
Trigger: Emitted inside on_printer_update(printer) every time BambuPrinter calls its on_update callback. This happens on every incoming MQTT push_status message from the printer. It is also emitted by the ChamberMonitor thread when an external MQTT chamber temperature update is received.
Before emitting, on_printer_update performs several automatic side-effects:
- If
gcode_statetransitions to"FINISH"andintegrated_external_heaterisTrueandchamber_temp_target != 0→ callsset_chamber_temp_target(0). - If
gcode_statetransitions to"FINISH"and the light is on → turns off the light. - If
gcode_statetransitions to"PREPARE"or"RUNNING"from a non-"PAUSE"state → resetsgcode_state_durations. - If
gcode_statetransitions to"RUNNING"and the light is off → turns on the light. - If the printer has a chamber door sensor and the door state changes → turns the light on when the door opens, and off when it closes (unless a job is running).
Payload: The full build_all_data() result. See build_all_data() Response Schema.
Frontend usage:
import { io } from 'socket.io-client';
const socket = io('http://localhost:5000');
socket.on('printer_update', (data) => {
// data is identical to the /api/get_all_data response
const printer = data.printer;
const toolSeries = data.tool.series; // multi-series array
const bedSeries = data.bed.series; // single-series object {data: [...]}
});
build_all_data() Response Schema
build_all_data() is called by both GET /api/get_all_data and the printer_update Socket.IO event. It assembles historical sensor time-series data sampled every ~2.5 seconds with a 60-minute rolling retention window.
Top-level keys
| Key | Type | Description |
|---|---|---|
tool |
object | Extruder temperature history. Multi-series. |
bed |
object | Heated-bed temperature history. Single series. |
chamber |
object | Chamber temperature history. Single series. |
fan |
object | All fan speed histories. Multi-series. |
gcode_state_durations |
object | Cumulative seconds spent in each gcode_state since the last job start. |
printer |
object | Full BambuPrinter.toJson() result, or error object when no live data. |
Chart object structure (bed, chamber)
bed and chamber use a single-series structure:
{
"minVal": 19.0,
"maxVal": 65.0,
"zoom": 0,
"maxAge": -3595,
"xAxis": {
"data": [-3595, -3590, -3585, ..., 0]
},
"series": {
"data": [22.3, 22.3, 59.1, ..., 60.0]
}
}
| Field | Type | Description |
|---|---|---|
minVal |
float | Y-axis minimum (data minimum minus a padding margin). |
maxVal |
float | Y-axis maximum (data maximum plus a padding margin). |
zoom |
int | Active zoom window in seconds. 0 = show all available data. |
maxAge |
int | X-axis value of the oldest visible data point (negative seconds). Absent when no data points exist. |
xAxis.data |
int[] | Time offsets in seconds relative to now. 0 = current time; negative values are in the past. |
series.data |
float[] | Temperature values in °C, aligned 1-to-1 with xAxis.data. |
Chart object structure (tool)
tool uses a multi-series structure. Series data is sourced from per-extruder temperature tracking (extruders[0].temp, extruders[1].temp).
- Single-extruder printers (X1, P1, A1, P2, H2S): one series labelled
"Tool". - Dual-extruder H2D / H2D Pro: two series labelled
"Right"and"Left".
Only series that have collected data points are included (no phantom series on single-extruder printers).
{
"minVal": 19.0,
"maxVal": 230.0,
"zoom": 1500,
"maxAge": -1503,
"xAxis": {
"data": [-1503, -1500, -1495, ..., 0]
},
"series": [
{
"data": [22.1, 22.1, 220.0, ..., 220.5],
"label": "Right",
"color": "#e15759"
},
{
"data": [22.0, 22.0, 215.0, ..., 215.2],
"label": "Left",
"color": "#76b7b2"
}
]
}
Gaps between sparse samples are filled by step-interpolation (_step_fill): the last known value is held until a new sample is available.
| Series label | Color | Source |
|---|---|---|
"Tool" (single extruder) |
#e15759 |
extruders[0].temp |
"Right" (H2D) |
#e15759 |
extruders[0].temp |
"Left" (H2D) |
#76b7b2 |
extruders[1].temp |
Chart object structure (fan)
fan uses a multi-series structure combining all four fan speed collections. The merged x-axis is the sorted union of all individual fan x-axes. Gaps are step-filled.
The zoom and maxAge fields on the fan object come from the fan (part-cooling) collection only.
{
"minVal": -0.1,
"maxVal": 101.0,
"zoom": 0,
"maxAge": -3595,
"xAxis": {
"data": [-3595, -3590, ..., 0]
},
"series": [
{
"data": [0.0, 0.0, 80.0, ..., 80.0],
"label": "Part Cooling",
"color": "#af7aa1"
},
{
"data": [60.0, 60.0, 60.0, ..., 60.0],
"label": "Auxiliary",
"color": "#4e79a7"
},
{
"data": [100.0, 100.0, 100.0, ..., 100.0],
"label": "Exhaust",
"color": "#f28e2c"
},
{
"data": [40.0, 40.0, 40.0, ..., 40.0],
"label": "Heatbreak",
"color": "#59a14f"
}
]
}
| Series label | Color | Source (BambuClimate field) |
|---|---|---|
"Part Cooling" |
#af7aa1 |
climate.part_cooling_fan_speed_percent |
"Auxiliary" |
#4e79a7 |
climate.aux_fan_speed_percent |
"Exhaust" |
#f28e2c |
climate.exhaust_fan_speed_percent |
"Heatbreak" |
#59a14f |
climate.heatbreak_fan_speed_percent |
All fan values are in percent (0–100). Raw printer values on 0–15 scale are converted via scaleFanSpeed() before storage.
gcode_state_durations
Cumulative elapsed seconds per gcode_state since the last job start (or application startup). Reset to an empty dict when gcode_state transitions to PREPARE or RUNNING from a non-PAUSE state.
{
"gcode_state_durations": {
"IDLE": 42.5,
"PREPARE": 30.0,
"RUNNING": 3600.0,
"PAUSE": 120.0,
"FINISH": 0.0
}
}
printer key
When printer.recent_update is truthy and printer.printer_state.spools is non-empty:
BambuPrinter.toJson() result.
When no live data is available:
Error Handling
All endpoints are protected by Flask's @app.errorhandler(500) which returns:
{
"status": "error",
"message": "ExceptionType: message text",
"stacktrace": "Traceback (most recent call last):\n ..."
}
304 Not Modified
Returned only by GET /api/printer when no live data is available:
404 Not Found
Returned by GET /api/get_3mf_props_for_file and GET /api/get_current_3mf_props:
500 Internal Server Error
Returned on any unhandled exception (including invalid enum names, missing required parameters, FTPS failures):
Library-Only Methods (no HTTP route)
BambuPrinter exposes several public methods and properties that bambu-printer-app's REST API does not currently wrap in a route. They are reachable only by importing bpm directly (see the bambu-printer-manager documentation).
| Method | Signature | Description |
|---|---|---|
clean_print_error |
(subtask_id: str = "", print_error: int = 0) |
Clears an active print_error on the printer via clean_print_error. |
clean_print_error_uiop |
(print_error: int = 0) |
Sends the UI dialog-close acknowledgment Bambu Studio sends alongside clean_print_error; without it the printer stays in a "waiting for UI acknowledgment" state. |
ftp_connection |
() — context manager |
Yields an IoTFTPSClient connected to the printer's SD card; used internally by every FTPS-backed method above. |
get_current_bind_list |
(state: BambuState) -> list[dict] |
Builds the manual_ams_bind list the H2D dual-extruder firmware requires when binding AMS units to extruders. |
rename_printer |
(new_name: str) |
Renames the printer (update/RENAME_PRINTER). |
sdcard_file_exists |
(path: str) -> bool |
Checks whether a file exists on the SD card via FTPS. |
select_extrusion_calibration_profile |
(tray_id: int, cali_idx: int = -1) |
Selects a saved extrusion (k-factor) calibration profile for a tray. |
send_anything |
(anything: str) |
Publishes an arbitrary JSON string directly to the printer's MQTT request topic — bypasses all validation; anything must already be valid JSON. |
set_spool_k_factor |
(tray_id, k_value, n_coef=1.4, nozzle_temp=-1, bed_temp=-1, max_volumetric_speed=-1) |
Deprecated (broken on recent Bambu firmware) — use select_extrusion_calibration_profile instead. |
Read-only or setter-only properties not surfaced by any route: internalException, cached_sd_card_contents, cached_sd_card_3mf_files, bed_temp_target_time, tool_temp_target_time, chamber_temp_target_time, fan_speed_target_time, printer_state, active_job_info, config, client, on_update, recent_update, and the deprecated skipped_objects, nozzle_diameter, nozzle_type (superseded by printer_state.active_nozzle).
Environment Variables
Required at startup:
BAMBU_HOSTNAME=192.168.1.100 # Printer IP address
BAMBU_ACCESS_CODE=12345678 # 8-character printer access code
BAMBU_SERIAL_NUMBER=00M12345678901 # Full printer serial number
INTEGRATED_EXTERNAL_HEATER=FALSE # Set TRUE to enable ChamberMonitor integration
BAMBU_SERIAL_NUMBER is validated at startup against ^[A-Za-z0-9]+$ — any other character (including ., /, or a leading / that Path.__truediv__ would treat as absolute) exits the process before the server starts, since the value becomes a directory name under ./uploads/.
Optional — only used when INTEGRATED_EXTERNAL_HEATER=TRUE:
CHAMBER_MQTT_HOST=192.168.1.50
CHAMBER_MQTT_PORT=1883
CHAMBER_MQTT_USER=user
CHAMBER_MQTT_PASS=password
CHAMBER_TARGET_TOPIC=chamber/target
CHAMBER_TEMPERATURE_TOPIC=chamber/temperature
CHAMBER_REQUESTED_STATE_TOPIC=chamber/set
CHAMBER_CURRENT_STATE_TOPIC=chamber/state
CHAMBER_STATE_ON_VALUE=ON
CHAMBER_STATE_OFF_VALUE=OFF
Examples
Python
import requests
# Get printer status
response = requests.get("http://localhost:5000/api/printer")
printer = response.json()
# Set bed temperature
requests.get("http://localhost:5000/api/set_bed_target_temp?temp=60")
# Start print job (plate is required)
params = {
"filename": "/test.3mf",
"platenum": 1,
"plate": "COOL_PLATE",
"use_ams": "true",
"ams_mapping": "[0,4]",
"bl": "true",
}
requests.get("http://localhost:5000/api/print_3mf", params=params)
JavaScript (Socket.IO + axios)
import { io } from 'socket.io-client';
import axios from 'axios';
const BASE = 'http://localhost:5000';
// Real-time updates via Socket.IO
const socket = io(BASE);
socket.on('printer_update', (data) => {
const printer = data.printer;
// data.tool.series is an array of {data, label, color}
const toolSeries = data.tool.series;
// data.bed.series is a plain object {data: [...]}
const bedTemps = data.bed.series.data;
console.log('gcode_state:', printer._printer_state?.gcode_state);
});
// Control endpoints
await axios.get(`${BASE}/api/set_light_state`, { params: { state: 'on' } });
await axios.get(`${BASE}/api/set_speed_level`, { params: { level: '2' } });
// Upload and print
const formData = new FormData();
formData.append('myFile', fileInput.files[0]);
await axios.post(`${BASE}/api/upload_file_to_host`, formData);
await axios.get(`${BASE}/api/upload_file_to_printer`, {
params: { src: 'model.3mf', dest: '/prints/model.3mf' },
});
await axios.get(`${BASE}/api/print_3mf`, {
params: { filename: '/prints/model.3mf', plate: 'AUTO', platenum: 1 },
});
cURL
# Printer info
curl http://localhost:5000/api/printer
# Set chamber temperature
curl "http://localhost:5000/api/set_chamber_target_temp?temp=45"
# Send G-code (multiple commands with |)
curl "http://localhost:5000/api/send_gcode?gcode=G28|G1 Z10 F600"
# Upload file
curl -F "myFile=@model.3mf" http://localhost:5000/api/upload_file_to_host
# Download SD card file
curl -o downloaded.3mf "http://localhost:5000/api/download_file_from_printer?src=/test.3mf"
Data Models
For comprehensive documentation of all data structures, attributes, and telemetry fields returned by this API, see the Data Dictionary.
Related Resources
Project Documentation
- bambu-printer-manager GitHub
- bambu-printer-manager Documentation
- Data Dictionary - Complete attribute reference
- MQTT Protocol Reference - MQTT command reference
Reference Implementations
- BambuStudio - Official Bambu Lab client
- OrcaSlicer - Community fork with enhanced features
- ha-bambulab - Home Assistant integration
- ha-bambulab pybambu - Python MQTT client
- Bambu-HomeAssistant-Flows - Workflow patterns
- OpenBambuAPI - Alternative API implementation
- X1Plus - Community firmware
- bambu-node - Node.js implementation
Version History
| Version | Date | Changes |
|---|---|---|
| 1.4 | 2026-09-27 | Verification pass against current source: added filament_catalog, set_enhanced_cooling_fan_speed_target, clear_command_errors, ping, retry_project_info, start_ams_dryer, stop_ams_dryer, and a Library-Only Methods section; corrected /api/printer's single-condition check, set_speed_level's actual accepted values, trigger_printer_refresh's async reconnect behaviour, set_nozzle_details's nozzle_flow/extruder_id parameters, load_filament/unload_filament's ams_id parameter, the per-serial upload/download staging directory, get_3mf_props_for_file's plate default and slicer_settings metadata key, and the dump_data_ds.collections/jsonSerializer defect; added BAMBU_SERIAL_NUMBER validation note |
| 1.3 | 2026-06-10 | Full rewrite from source: corrected build_all_data() multi-series schema for tool and fan, fixed file-operation response bodies (all return updated SD card tree, not custom dicts), documented Socket.IO printer_update event, added gcode_state_durations, corrected set_spool_k_factor stub status, corrected print_3mf plate required/default behaviour, corrected toggle_verbosity level-toggle logic, added NOZZLE_BLOB_DETECT/AIR_PRINT_DETECT to set_print_option, expanded environment variables section |
| 1.2 | 2026-03-02 | Added Detection & Safety section (buildplate, spaghetti, purgechute, nozzleclumping, airprinting detectors, refresh_nozzles); fixed dump_data_ds.collections route name |
| 1.1 | 2026-02-25 | Updated reference implementations; added comprehensive external sources |
| 1.0 | 2026-02-23 | Initial REST API reference documentation |
Support
For issues, questions, or contributions: - Open an issue: bambu-printer-app Issues - Library issues: bambu-printer-manager Issues