This reference describes the HTTP controls implemented by Bambu firmware 3.10.4. Use the WebSocket API to set the chamber target. Set normal printer nozzle and bed targets through the printer; this HTTP API does not provide a general nozzle-target or bed-target setter.
Read Developer reference before connecting. Examples use 192.0.2.42 as a placeholder; replace it with the HAT's current address. These examples change settings when sent to a real device.
Send every request below as POST with URL-encoded form fields, not a JSON body:
POST /api/scaler HTTP/1.1
Host: 192.0.2.42
Accept: application/json
Content-Type: application/x-www-form-urlencoded
X-Tyson-Request: 1
action=settings&maximum=400&hotend=left
Ordinary forms are limited to 2,048 bytes. X-Tyson-Request: 1 is a required request marker, not an API key. The HAT also validates Host and any supplied Origin. When optional LAN access protection is enabled, supply its code header or a valid browser session as well. A browser on a separately hosted wiki or application cannot directly use these routes as a cross-origin API.
Successful control requests return a complete state snapshot. A response confirms that the handler accepted the request; output confirmation, printer acknowledgment, calibration, and flash saving may continue afterward. Read the relevant state fields before reporting completion. A lost HTTP response is an unknown outcome: read current state before deciding whether to retry.
| Status | Meaning for these routes |
|---|---|
200 OK |
Accepted bed, fan, or print request; inspect the returned state for ongoing work. |
202 Accepted |
Accepted scaler or manual DAC request; inspect subsequent state for confirmation. |
400 Bad Request |
Invalid form or a route-specific syntax error, such as unsupported hotend selection or malformed print revision. |
403 Forbidden |
Address, origin, request marker, or firmware-update/startup guard rejected the request. The body is JSON with error. |
409 Conflict |
The requested action is unavailable in the current controller state. Some routes also use this for invalid action values. |
500 Internal Server Error |
A synchronous save failed. Changes may already be in memory; read the response and state. |
503 Service Unavailable |
Factory reset is in progress or a state snapshot could not be allocated. |
Errors other than the request guard may be plain text or an HTTP-server error page. Do not assume every response is JSON. Display the returned error message and refresh state instead of retrying a rejected action continuously.
POST /api/scalerThe maximum field selects the actual-temperature endpoint corresponding to a 300°C printer reading. Supported values are exactly 300, 350, 400, 425, and 450.
Optional hotend=left selects the original/left hotend and is the default when omitted. hotend=right is available only when the HAT recognizes an X2D (dual_hotend: true). A malformed channel returns 400; an otherwise valid right-channel action on a single-hotend printer returns 409.
action |
Additional fields | Behavior |
|---|---|---|
settings |
maximum |
Save a supported preset. Does not enable mapping. |
enable |
None | Enable mapping with the selected calibrated preset and remember that enable choice. |
disable |
None | Disable mapping and clear the remembered enable choice. Refused while calibration or its save is in progress. |
stop |
None | Cancel an active preset calibration, or stop active mapping and request printer nozzle-off. Returns 409 if nothing is active. |
cancel |
None | Cancel the active calibration; returns 409 when no calibration is running. |
calibrate |
None | Start electrical mapping calibration. |
auto_calibrate |
None | Start or continue the automatic preset-calibration sequence. |
calibrate_preset |
maximum |
Calibrate the selected preset; maximum must still equal the saved selection. |
restart_calibration |
None | Restart the automatic calibration sequence. |
resume_calibration |
None | Resume a paused calibration when its resume checks pass. |
clear_calibration |
None | Request removal of saved mapping and preset calibration. |
Normal accepted actions above return 202 with the state snapshot, including settings. Calibration can operate the printer heater; follow the calibration workflow and monitor its state before implementing those actions. The obsolete test_profile action is rejected with 409. Legacy recovery, described below, is a separate response path.
Choose a preset:
curl -i -X POST http://192.0.2.42/api/scaler \
-H 'Accept: application/json' \
-H 'X-Tyson-Request: 1' \
--data 'action=settings&maximum=400&hotend=left'
Then read scaler_maximum, scaler_saving, and scaler_settings_save_failed. Changing the saved preset while mapping is running does not change the active mapping immediately. scaler_active_maximum reports the active endpoint; scaler_preset_pending reports a saved selection waiting to be used the next time mapping is enabled.
Enabling requires the installed channel, usable electrical mapping and preset calibration, a fresh valid local PT100 reading within the controller limits, confirmed mapping output, and no conflicting calibration or save. Normal calibrated mapping uses local measurements and does not require idle printer reports or a zero nozzle target; calibration has separate printer-state checks. Check scaler_calibrated, profile_passed, scaler_status, scaler_enabled, scaler_error, enable_save_pending, and enable_save_failed. For the right hotend, read those fields inside right_hotend; the original/left fields are at the top level of the state object.
disable and stop have different effects. Disabling ends live mapping. Stopping an active mapping also requests nozzle-off, which still needs the printer to respond. A successful HTTP response is not a measurement that the physical nozzle heater is off.
Starting calibration requires fresh idle printer reports with nozzle target zero, a valid local PT100 reading at or below 50°C, and confirmed mapping output. Automatic preset calibration also checks fresh printer error/temperature status; another hotend or bed calibration can block it. Follow scaler_calibrating, scaler_calibration_progress, profile_active, profile_status, profile_progress, profile_completed, and profile_error. Wait for scaler_saving and profile_saving to clear before interpreting the final result. A paused preset uses profile_paused, profile_resume_ready, and profile_resume_blocked; send resume_calibration only after the reported reason is resolved. Clearing calibration is asynchronous: use scaler_clear_pending, scaler_clear_status, and scaler_clear_error.
The additional action restore_legacy recovers older saved calibration associated with a previous printer address. It accepts required previous_host (a hostname or address without a scheme or port) and optional previous_port (integer 1–65535, default 8883). It applies only to the original/left hotend; hotend=right returns 400.
Recovery requires stopped control, no competing calibration/save/restore operation, and no currently configured original-hotend or bed calibration. The stored record must match the configured printer serial and previous address. It returns 200 state on success, 400 for invalid fields, 409 for unavailable or mismatched recovery/state changes, and 500 if the recovered identity could not be saved. This reads already stored legacy data; it is not a network download from previous_host. For normal backup files, use Calibration transfer API.
POST /api/bedThe bed's maximum selects the actual-temperature endpoint corresponding to a 110°C Bambu target. Supported values are exactly 110, 165, and 220.
action |
Additional fields | Behavior |
|---|---|---|
settings |
maximum |
Save a supported bed preset while bed control is stopped. |
enable |
None | Enable calibrated bed control and remember the enable choice. |
stop |
None | Stop bed control, cancel an active PID tune, and clear the remembered enable choice. An already-started calibration save may finish. |
control_settings |
mode, delta, kp, ki, kd |
Save regulation settings while control is stopped and prior saves are complete. |
pid_tune |
target |
Start PID auto-tuning at an actual bed temperature, as an integer from 40 to 200°C. |
calibrate |
None | Start bed mapping calibration. |
clear |
None | Clear the saved mapping while control is stopped. |
Accepted bed requests return 200 with the state snapshot. Invalid actions, unsupported presets, malformed action-specific values, and controller-policy rejections use 409. A missing or malformed overall form can return 400.
For example, after stopping bed control and waiting for any save to finish:
curl -i -X POST http://192.0.2.42/api/bed \
-H 'Accept: application/json' \
-H 'X-Tyson-Request: 1' \
--data 'action=settings&maximum=165'
Wait for bed_saving to become false and inspect bed_error/bed_fault. Enabling requires a connected printer with a fresh bed target of zero, valid calibration, a fresh local bed temperature, confirmed mapping output, and valid regulation settings. Once enabled, set the operational bed target on Bambu. Under the 165 preset, a Bambu target of 100°C corresponds to an actual target of 150°C. The API reports this as bed_actual_target; it is separate from printer_bed_target and measured bed_temperature.
Stopping Tyson bed control does not itself send a new normal bed target to Bambu. Read both controller state and printer target when presenting an off action in another application.
Send all five fields with action=control_settings, even in bang-bang mode:
| Field | Accepted value |
|---|---|
mode |
bang_bang or pid |
delta |
Finite number from 0.1 to 2°C; the bang-bang restart difference below target. |
kp |
Finite number from 0 to 10000; must be greater than zero in PID mode. |
ki |
Finite number from 0 to 1000. |
kd |
Finite number from 0 to 1000000. |
The save runs asynchronously. Read bed_control_saving, bed_control_save_error, bed_control_mode, bed_max_delta, and bed_pid_kp/bed_pid_ki/bed_pid_kd. Preserve the current gains when changing only the mode or delta; example gains are not a tuning recommendation.
PID tuning needs stopped control, completed saves, an idle connected printer with bed target zero, and an actual bed temperature at least 10°C below the requested tuning target. It actively heats the bed. Follow bed_pid_tuning, bed_pid_tune_progress, bed_pid_tune_note, bed_pid_tune_complete, and bed_error. Completion selects PID, turns heating off, and starts saving the measured settings; wait for bed_control_saving to clear and check bed_control_save_error. Use action=stop to cancel. The calibration guide explains the operator workflow.
Bed mapping calibration uses bed_calibrating, bed_calibration_progress, bed_calibration_points, bed_saving, bed_calibrated, and bed_error. A 200 response to calibrate or clear is only the start of that operation, not confirmation that its persistent result has been saved.
POST /api/chamber/fanSend action=on or action=off. Any other action returns 400. The request changes the manual fan preference; automatic chamber-heating and cooling rules continue to apply.
An off request can return 409 while cooling, temperature validity, or other fan conditions require airflow. Read chamber_fan_off_allowed and chamber_fan_off_reason before offering the action. An accepted off request can leave chamber_fan_stopping: true during the ramp; wait for chamber_fan_on: false to report the fan as stopped. Reported outputs are commands, not a fan-rotation measurement.
If chamber_fan_remember is true, the manual preference is saved. Send Accept: application/json: the save path otherwise returns 303 to /settings. If no save is needed, the route directly returns 200 state. A save failure returns 500 after the in-memory preference may already have changed.
Fan mode and remembered-state settings belong to Configuration API. The API uses 40, 55, 70, and 85 for Quiet, Normal, Fast, and Turbo respectively.
POST /api/print/controlSend action and the current print_job.revision as revision. This is the job revision from the latest state snapshot, not state_seq or a client-generated number. The revision must be an integer from 0 through 2147483647.
action |
Required printer state |
|---|---|
pause |
print_job.state is RUNNING. |
resume |
print_job.state is PAUSE. |
stop |
print_job.state is RUNNING, PAUSE, or PREPARE. |
The printer must be connected with Developer Mode enabled, the job status must be fresh, and calibration must be inactive. A changed job revision, pending earlier command, or unavailable action returns 409; a malformed revision returns 400.
Accepted requests return 200 state with the command queued. Monitor print_job.control_pending, print_job.control_error, and print_job.state. The controller waits up to 15 seconds for printer confirmation, then reports a confirmation error. It does not mean the command was never received: read current status before retrying. A job change cancels tracking of the previous command. A stop request also tells bed-error recovery that the user requested a stop.
POST /api/dacThis low-level route accepts mode=manual and integer code from 0 to 3200 for the original/left hotend mapping output. It is not a temperature or heater-power command, and has no right-channel selector. Normal integrations should use calibrated scaling.
The hotend must be installed, mapping must not own the output, and another write must not be pending. Syntax errors return 400; current-state conflicts return 409. Acceptance returns 202; the I²C worker writes and reads back the output afterward. Inspect dac_pending, dac_valid, dac_requested, and dac_code before reporting success. It also clears the remembered hotend-mapping enable choice.
Source basis: main/main.cpp request handlers and state serialization; main/nozzle_scaler.h, main/nozzle_profiles.h, main/bed_control.h, main/bed_pid.h, main/chamber_fan.h, main/print_controls.h, main/print_monitor.cpp, and main/web_request_policy.h. This documents the current implementation, not a separately versioned public API contract.