API Reference¶
Bambuddy provides a REST API for integration with external tools and automation.
Authentication¶
API Key Authentication¶
Include your API key in the X-API-Key header:
Getting an API Key¶
- Go to Settings > API Keys
- Click Create API Key
- Select permissions
- Copy the key (shown only once)
See API Keys & Webhooks for details.
Interactive API Browser¶
Bambuddy includes a built-in API browser for exploring and testing endpoints without external tools.
Accessing the API Browser¶
- Go to Settings > API Keys
- The API Browser appears in the right column
Features¶
| Feature | Description |
|---|---|
| OpenAPI Integration | Automatically loads all endpoints from the schema |
| Grouped by Category | Endpoints organized by printers, archives, settings, etc. |
| Parameter Inputs | Fill in path, query, and body parameters |
| Auto-examples | Request body pre-filled with schema examples |
| Live Execution | Execute requests and see real responses |
| Response Display | Formatted JSON with status code and timing |
| Search | Filter endpoints across all categories |
Testing with API Keys¶
- Paste your API key in the "API Key for Testing" input
- The key is sent as
X-API-Keyheader with each request - Test authenticated endpoints without external tools
Quick Setup
After creating a new API key, click "Use in API Browser" to automatically add it for testing.
Base URL¶
All endpoints are relative to this base URL.
Printers¶
List Printers¶
Response:
[
{
"id": 1,
"name": "Workshop X1C",
"ip_address": "192.168.1.100",
"serial_number": "01P00A000000001",
"model": "X1 Carbon",
"status": "idle"
}
]
Get Printer¶
Response:
{
"id": 1,
"name": "Workshop X1C",
"ip_address": "192.168.1.100",
"serial_number": "01P00A000000001",
"model": "X1 Carbon",
"status": "printing",
"current_print": {
"filename": "benchy.3mf",
"progress": 45,
"remaining_time": 3600
}
}
Get Printer Status¶
Response:
{
"state": "printing",
"progress": 45,
"remaining_time": 3600,
"current_layer": 120,
"total_layers": 267,
"temperatures": {
"nozzle": 220,
"bed": 60,
"chamber": 35
},
"hms_status": "ok",
"awaiting_plate_clear": false
}
awaiting_plate_clear is a Bambuddy-side gate, not printer telemetry. It goes true when a print reaches a terminal state and stays true until the plate is confirmed clear via Clear Plate; the queue will not dispatch the next job in the meantime. It survives restarts and Auto Off power cycles, so a printer that reports IDLE after a reboot can still be waiting. The same flag is pushed over the WebSocket printer_status message and over MQTT — including a dedicated retained topic, which is the better subscription for automations because it does not depend on the printer still being powered on.
Refresh Printer Status¶
Request a full status update from the printer via MQTT pushall command. Useful for getting fresh AMS data after swapping spools.
Response:
Errors:
404- Printer not found400- Printer not connected
Clear HMS Errors¶
Clear HMS/print errors on the printer. Sends a clean_print_error MQTT command and clears errors locally.
Response:
Errors:
404- Printer not found400- Printer not connected500- Failed to clear HMS errors
Permission: printers:control
Clear Plate¶
Acknowledge that the build plate has been cleared after a finished/failed print. Sets a plate-cleared flag so the scheduler can start the next queued print.
Response:
Acknowledgement is accepted whenever awaiting_plate_clear is true, whatever the printer currently reports — after an Auto Off power cycle it boots into IDLE with no memory of the finished print, and the gate still needs clearing. The reported state only matters as a fallback when the flag is not set.
Errors:
404- Printer not found400- Printer not connected400- Printer is not awaiting acknowledgement and is not inFINISH/FAILEDstate
Permission: printers:clear_plate
Set Print Speed¶
Change the print speed preset during an active print.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
mode | int | Yes | Speed preset: 1 (Silent 50%), 2 (Standard 100%), 3 (Sport 124%), 4 (Ludicrous 166%) |
Response:
Errors:
404- Printer not found400- Printer not connected or no active print422- Invalid mode (must be 1-4)
Permission: printers:control
Add Printer¶
Request:
{
"name": "New Printer",
"ip_address": "192.168.1.101",
"access_code": "12345678",
"serial_number": "01P00A000000002"
}
Update Printer¶
Request:
Delete Printer¶
Archives¶
List Archives¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
printer_id | int | Filter by printer |
status | string | success, failed, stopped |
start_date | date | Filter from date |
end_date | date | Filter to date |
search | string | Full-text search |
project_id | int | Filter by project |
limit | int | Max results (default: 50) |
offset | int | Pagination offset |
Response:
{
"total": 1234,
"archives": [
{
"id": 1,
"name": "Benchy",
"filename": "benchy.3mf",
"printer_id": 1,
"printer_name": "Workshop X1C",
"created_at": "2024-01-15T14:30:00Z",
"duration": 8100,
"status": "success",
"filament_used": 45.2,
"filament_type": "PLA"
}
]
}
Get Archive¶
Update Archive¶
Request:
Delete Archive¶
Download 3MF¶
Returns the 3MF file as download.
Export Archives¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
format | string | csv or xlsx |
| (others) | Same filters as list |
Projects¶
List Projects¶
Get Project¶
Create Project¶
Request:
{
"name": "Voron Build",
"description": "Building a Voron 2.4",
"color": "#4caf50",
"target_count": 100
}
Update Project¶
Delete Project¶
Print Queue¶
Get Queue¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
printer_id | int | Filter by printer |
status | string | pending, printing, completed |
Add to Queue¶
Request:
Remove from Queue¶
Reorder Queue¶
Request:
List Batches¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status | string | active, completed, or cancelled |
Batches with neither queue items nor per-plate targets are omitted — see Batch Orders. Fetching one by id (GET /queue/batches/{batch_id}) returns it regardless.
Create Batch or Order¶
Without plates this creates a plain grouping: pass item_ids to group existing pending items, or omit them and pass the returned id as batch_id on later POST /queue calls. With plates it becomes an order that records how many runs of each plate are wanted, so a failed run still counts as owed.
Request:
{
"name": "Bracket run",
"library_file_id": 42,
"plates": [
{ "plate_id": 1, "quantity_target": 1 },
{ "plate_id": 2, "quantity_target": 2 },
{ "plate_id": 3, "quantity_target": 3 }
],
"due_date": "2026-09-01T12:00:00Z",
"notes": "Rush job"
}
plate_id is null for a single-plate file. A quantity_target of 0 is allowed — a plate that is not required yet keeps its row so the target can be raised later — but an order in which every target is 0 is rejected.
Update an Order¶
Every field is optional. Supplying plates replaces the whole target set, so a plate left out of the list has its target row removed. Lowering a target below what has already been dispatched is allowed and simply leaves nothing owed; queued items are never cancelled implicitly.
Request:
Dispatch Remaining Runs¶
Creates queue items for the runs the order still owes. Each is copied from the most recent item for that plate, inheriting its printer or model target, AMS mapping, filament overrides and print options, and is appended to the end of the relevant printer's queue.
Request:
| Field | Type | Description |
|---|---|---|
plate_id | int | null | Which plate to dispatch. Only read when only_plate is true |
only_plate | bool | Restrict to the single plate named above. Default false — every plate with work outstanding |
limit | int | Cap on items created across all plates. Omit to queue everything owed |
Returns 400 when a plate owes runs but has never been queued, since there is no existing item to copy settings from, and when the batch has been cancelled.
Ungroup a Batch¶
Clears batch_id from every member the caller owns. The batch row is deleted once no members remain.
Cancel a Batch¶
Cancels the batch's pending items and marks the batch cancelled. Items that have already run are untouched.
Scheduled Drying Sessions¶
Get Scheduled Drying Sessions¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
printer_id | int | Filter by printer |
Returns sessions that are pending, running, or failed, earliest start time first, with sessions that have no start time ahead of the rest. Completed and cancelled sessions are not returned.
Permission: printers:read
Create Scheduled Drying Session¶
Request:
{
"printer_id": 1,
"ams_id": 2,
"temp": 45,
"duration_hours": 12,
"filament": "PLA",
"rotate_tray": true,
"start_after": "2026-07-26T18:00:00Z"
}
start_after is the earliest start, and it is optional: omit it (or send null) and the session runs as soon as the printer is idle and the AMS is ready. The drying popover has no equivalent — its Now option starts drying immediately through POST /printers/{id}/drying/start instead — so this is an API-only way to say "next time the printer is free".
Permission: printers:control
Cancel or Dismiss Scheduled Drying Session¶
Cancels a pending or running session and responds with {"status": "cancelled"}. A running session is also sent a stop command. On a failed session the record is deleted instead, and the response is {"status": "dismissed"}.
Permission: printers:control
Spool Inventory¶
List Spools¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
include_archived | bool | Include archived spools (default false) |
Get Spool¶
Find Spool by Tag¶
Look up a single spool by its NFC tag identifiers without listing the whole inventory. This is intended for NFC inventory integrations that scan a Bambu Lab spool tag and need to check whether it already exists before creating or updating it.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
tray_uuid | string | Bambu Lab spool UUID from the tag — the same value the AMS reports over MQTT |
tag_uid | string | RFID tag UID |
include_archived | bool | Include archived spools (default false) |
At least one of tray_uuid or tag_uid must be supplied. Values are normalised (case-insensitive, non-hex separators ignored). tray_uuid is matched first and tag_uid is used as a fallback. Returns the single matching spool.
Response:
{
"id": 42,
"material": "PLA",
"brand": "Bambu",
"color_name": "Red",
"tray_uuid": "AABBCCDDEEFF0011AABBCCDDEEFF0011",
"tag_uid": "04A1B2C3"
}
Errors:
400- Neithertray_uuidnortag_uidwas provided404- No matching spool found
Required scope
This endpoint accepts inventory read or inventory update access — for API keys, either the Read Status scope or the Manage Inventory scope. This lets a key that can already create, update, and delete spools look one up to dedupe an NFC scan. (Listing spools and fetching a spool by id still require Read Status.)
Statistics¶
Get Statistics¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
printer_id | int | Filter by printer |
start_date | date | Period start |
end_date | date | Period end |
Response:
{
"total_prints": 1234,
"successful_prints": 1100,
"failed_prints": 100,
"stopped_prints": 34,
"success_rate": 89.14,
"total_print_time": 360000,
"total_filament_used": 15000.5,
"total_cost": 350.00
}
Export Statistics¶
Camera¶
An <img> or <video> tag cannot send an Authorization header, so the stream and snapshot endpoints also accept a token in the query string. Pass either a 60-minute browser token (POST /printers/camera/stream-token) or a long-lived camera token — see Long-Lived Camera Tokens.
Stream (MJPEG)¶
Returns MJPEG stream. Query params:
| Parameter | Type | Description |
|---|---|---|
fps | int | Frames per second (1-30) |
token | string | Camera token, when auth is enabled |
Snapshot¶
Returns single JPEG image. Accepts the same token query param.
Stop Stream¶
Terminates active streams for printer.
Cam Wall¶
Wall Feed¶
Every printer plus the handful of status fields a Cam Wall tile draws. One call for the whole wall — a kiosk display polls this on a fixed interval with no WebSocket to invalidate it.
| Parameter | Type | Description |
|---|---|---|
token | string | A Cam Wall-scoped camera token, when auth is enabled |
Authenticated only by a camwall-scoped token. A camera_stream token is refused here — it was minted to hand out video, not to enumerate a fleet by name.
[
{
"id": 1,
"name": "X1C-Lab",
"camera_rotation": 0,
"connected": true,
"state": "RUNNING",
"progress": 42.0,
"remaining_time": 33,
"layer_num": 120,
"total_layers": 300,
"hms_errors": []
}
]
That list is the entire payload. It deliberately carries no serial_number, no ip_address, no access_code, and no print filename: the token travels in a URL displayed on a screen, so the feed behind it must not disclose more than the camera picture already does.
Streaming Overlay¶
Overlay Status¶
Everything the streaming overlay draws for one printer — name, camera rotation, live print state, and the one display setting it reads. A token-authenticated sibling of the printer status endpoint, so an OBS browser source with no login session can back the overlay.
| Parameter | Type | Description |
|---|---|---|
token | string | A Streaming Overlay-scoped camera token, when auth is enabled |
Authenticated only by an overlay-scoped token. A camwall or camera_stream token is refused here — unlike the Cam Wall feed this names the file being printed, so it sits behind its own scope.
{
"id": 1,
"name": "X1C-Lab",
"camera_rotation": 0,
"connected": true,
"state": "RUNNING",
"current_print": "Benchy.gcode.3mf",
"gcode_file": "Metadata/plate_1.gcode",
"progress": 42.0,
"remaining_time": 33,
"layer_num": 120,
"total_layers": 300,
"stg_cur_name": null,
"time_format": "system"
}
That object is the entire payload. Like the Cam Wall feed it carries no serial_number, ip_address, or access_code — but it does carry the print filename, which is why the overlay scope is distinct from camwall.
System¶
System Info¶
Response:
Health Check¶
Response:
Error Responses¶
Error Format¶
HTTP Status Codes¶
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized (no/invalid API key) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found |
| 429 | Rate Limited |
| 500 | Server Error |
Rate Limits¶
| Endpoint Type | Limit |
|---|---|
| Read | 100/minute |
| Write | 30/minute |
| Control | 10/minute |
Rate Limit Headers¶
Content Types¶
Request¶
Response¶
Except for file downloads (application/octet-stream) and images (image/jpeg).
Webhooks¶
Bambuddy can send webhooks for events. Configure in Settings > Notifications.
Webhook Payload¶
{
"event": "print_complete",
"timestamp": "2024-01-15T14:30:00Z",
"data": {
"printer_id": 1,
"printer_name": "Workshop X1C",
"archive_id": 123,
"filename": "benchy.3mf",
"duration": 8100,
"status": "success"
}
}
Event Types¶
| Event | Trigger |
|---|---|
print_started | Print begins |
print_progress | Progress milestone |
print_complete | Print finishes |
print_failed | Print fails |
printer_offline | Connection lost |
printer_error | HMS error |