# Bambu Lab Api > This document covers AMS (Automatic Material System) unit data, filament information, colors, and real-time monitoring. --- # Bambu Lab Cloud API - AMS & Filament **Last Updated:** 2025-10-25 This document covers AMS (Automatic Material System) unit data, filament information, colors, and real-time monitoring. --- ## Base URLs **Global:** https://api.bambulab.com **China:** https://api.bambulab.cn **MQTT US:** us.mqtt.bambulab.com:8883 **MQTT CN:** cn.mqtt.bambulab.com:8883 **Authentication:** Bearer Token (see [API_AUTHENTICATION.md](API_AUTHENTICATION.md)) --- ### AMS & Filament Information #### Overview AMS (Automatic Material System) provides automatic multi-material printing with up to 16 filament spools (4 AMS units × 4 trays each). Get detailed information about your AMS units, loaded filaments, temperatures, humidity levels, and remaining material. #### Get AMS Filaments AMS data is embedded in the device bind response. Use `get_ams_filaments(device_id)` from the Python client. ```python from bambulab import BambuClient client = BambuClient("YOUR_TOKEN") # Get AMS and filament information ams_info = client.get_ams_filaments("01234567890ABCD") print(f"Has AMS: {ams_info['has_ams']}") print(f"Total Trays: {ams_info['total_trays']}") # List all units and filaments for unit in ams_info['ams_units']: print(f"\nAMS Unit {unit['unit_id']}:") print(f" Software: {unit['sw_version']}") print(f" Hardware: {unit['hw_version']}") print(f" Temperature: {unit['temperature']}C") print(f" Humidity: {unit['humidity']}") for tray in unit['trays']: print(f"\n Tray {tray['tray_id']}:") print(f" Type: {tray['filament_type']}") print(f" Color: {tray['filament_color']}") print(f" Temp Range: {tray.get('nozzle_temp_min')}-{tray.get('nozzle_temp_max')}C") print(f" Remaining: {tray.get('remaining')}mm") ``` #### Response Structure ```json { "device_id": "01234567890ABCD", "has_ams": true, "total_trays": 4, "ams_units": [ { "unit_id": 0, "software_version": "01.01.01.01", "hardware_version": "AMS08", "tray_count": 4, "temperature": "25.0", "humidity": "3", "humidity_raw": "28", "dry_time": 0, "info": "1001", "trays": [ { "tray_id": 0, "tray_type": "Empty", "state": 0 }, { "tray_id": 1, "state": 3, "filament_type": "PETG-CF", "filament_color": "000000FF", "tray_info_idx": "GFG50", "nozzle_temp_min": 240, "nozzle_temp_max": 270, "bed_temp": "0", "bed_temp_type": "0", "tray_weight": "0", "tray_diameter": "0.00", "tray_temp": "0", "tray_time": "0", "total_len": 012345, "remain": -1, "k": 0.04, "n": 1, "cali_idx": -1, "tag_uid": "0000000000000000", "tray_id_name": "", "tray_sub_brands": "", "tray_uuid": "01234567890ABCDEF01234567890ABCD", "xcam_info": "01234567890ABCDEF0123456", "ctype": 0, "cols": ["000000FF"] }, { "tray_id": 2, "tray_type": "Empty", "state": 0 }, { "tray_id": 3, "tray_type": "Empty", "state": 0 } ] } ], "external_spool": { "tray_id": 254, "filament_type": "PETG", "filament_color": "FFFF00FF", "tray_info_idx": "GFG60", "nozzle_temp_min": 220, "nozzle_temp_max": 270, "remain": 0, "k": 0.02, "n": 1, "cali_idx": -1 } } ``` #### Field Descriptions **AMS Unit Fields:** - `unit_id`: AMS unit number (0-3) - `software_version`: AMS firmware version - `hardware_version`: AMS hardware model (e.g., "AMS08") - `tray_count`: Number of trays in this unit (typically 4) - `temperature`: Current AMS temperature (C) - `humidity`: Humidity level index (0-5, lower is drier) - `humidity_raw`: Raw humidity percentage - `dry_time`: Time spent in drying mode (seconds) - `info`: Status bits (binary flags) **Tray Fields:** - `tray_id`: Tray slot (0-3 per unit, or 254 for external spool) - `state`: Tray state (0=empty, 1=loading, 2=loaded, 3=ready) - `filament_type`: Material type (PLA, PETG, ABS, TPU, PA, PC, etc.) - `filament_color`: RGBA hex color code - `tray_info_idx`: Bambu Lab filament profile ID - `nozzle_temp_min`: Minimum nozzle temperature (C) - `nozzle_temp_max`: Maximum nozzle temperature (C) - `bed_temp`: Bed temperature setting (C) - `tray_weight`: Filament weight (grams) - `tray_diameter`: Filament diameter (mm, typically 1.75) - `total_len`: Total filament length (mm) - `remain`: Remaining filament length (mm, -1 if unknown) - `k`, `n`: Flow rate calibration values - `cali_idx`: Calibration index - `tag_uid`: RFID tag UID (if present) - `tray_id_name`: Custom tray name - `tray_sub_brands`: Sub-brand identifier - `tray_uuid`: Unique tray identifier - `xcam_info`: X-Cam color detection data - `ctype`: Color type - `cols`: Array of color values **External Spool (Virtual Tray):** - `tray_id`: Always 254 - Same fields as regular trays - Represents filament loaded directly on printer (not in AMS) #### Filament Types Common filament types returned: - **PLA** - Standard PLA - **PLA-CF** - Carbon Fiber PLA - **PETG** - PETG - **PETG-CF** - Carbon Fiber PETG - **ABS** - ABS - **ASA** - ASA - **TPU** - TPU (flexible) - **PA** - Nylon (Polyamide) - **PA-CF** - Carbon Fiber Nylon - **PC** - Polycarbonate - **PVA** - Support material (water-soluble) - **GENERIC** - Unknown/generic #### Color Codes Colors are returned as RGBA hex strings (8 characters): - `FF0000FF` = Red - `00FF00FF` = Green - `0000FFFF` = Blue - `FFFFFFFF` = White - `000000FF` = Black - Last 2 digits = Alpha (FF = opaque) Convert to display format: ```python color_hex = "FF0000FF" rgb = color_hex[:6] # "FF0000" alpha = color_hex[6:] # "FF" print(f"Color: #{rgb} (Alpha: {alpha})") ``` #### Python Examples ##### Example 1: Check Filament Levels ```python def check_filament_levels(device_id): """Check which trays need refilling""" ams_info = client.get_ams_filaments(device_id) if not ams_info['has_ams']: print("No AMS installed") return low_filament = [] for unit in ams_info['ams_units']: for tray in unit['trays']: remaining = tray.get('remain', 0) total = tray.get('total_len', 012345) if remaining > 0 and total > 0: percent = (remaining / total) * 100 if percent < 20: low_filament.append({ 'unit': unit['unit_id'], 'tray': tray['tray_id'], 'type': tray.get('filament_type', 'Unknown'), 'remaining': f"{percent:.1f}%" }) if low_filament: print("Low filament levels:") for item in low_filament: print(f" Unit {item['unit']} Tray {item['tray']}: " f"{item['type']} - {item['remaining']} remaining") else: print("All filaments OK") check_filament_levels("01234567890ABCD") ``` ##### Example 2: List All Filaments ```python def list_all_filaments(device_id): """List all loaded filaments with details""" ams_info = client.get_ams_filaments(device_id) if not ams_info['has_ams']: print("No AMS installed") return print(f"Total Trays: {ams_info['total_trays']}\n") for unit in ams_info['ams_units']: print(f"AMS Unit {unit['unit_id']} (v{unit['software_version']})") print(f" Temperature: {unit['temperature']}C") print(f" Humidity: Level {unit['humidity']}") print("-" * 50) for tray in unit['trays']: if tray.get('state', 0) == 0: print(f" Tray {tray['tray_id']}: Empty") continue # Convert hex color to readable format color = tray.get('filament_color', 'N/A') if color != 'N/A' and len(color) >= 6: color = f"#{color[:6]}" print(f" Tray {tray['tray_id']}:") print(f" Material: {tray.get('filament_type', 'Unknown')}") print(f" Color: {color}") temp_min = tray.get('nozzle_temp_min', 'N/A') temp_max = tray.get('nozzle_temp_max', 'N/A') print(f" Nozzle Temp: {temp_min}-{temp_max}C") remaining = tray.get('remain', -1) total = tray.get('total_len', 0) if remaining > 0 and total > 0: percent = (remaining / total) * 100 print(f" Remaining: {remaining}mm ({percent:.1f}%)") print() list_all_filaments("01234567890ABCD") ``` ##### Example 3: Monitor AMS Temperature/Humidity ```python def monitor_ams_environment(device_id): """Monitor AMS environmental conditions""" ams_info = client.get_ams_filaments(device_id) if not ams_info['has_ams']: print("No AMS installed") return for unit in ams_info['ams_units']: temp = float(unit['temperature']) humidity_idx = int(unit['humidity']) humidity_raw = int(unit['humidity_raw']) print(f"AMS Unit {unit['unit_id']}:") print(f" Temperature: {temp}C") print(f" Humidity: Level {humidity_idx} ({humidity_raw}%)") # Check conditions if temp > 35: print(" WARNING: High temperature") if humidity_idx > 3: print(" WARNING: High humidity - consider drying") print() monitor_ams_environment("01234567890ABCD") ``` #### Real-Time Updates via MQTT **Note:** The `get_ams_filaments()` method returns static data from the device bind endpoint. For **real-time AMS updates** (during printing, filament changes), use MQTT: ```python from bambulab import MQTTClient mqtt = MQTTClient( username="bblp", token="your_token", device_id="01234567890ABCD" ) def on_message(data): if 'ams' in data.get('print', {}): ams_data = data['print']['ams'] # Real-time AMS data for unit in ams_data.get('ams', []): unit_id = unit.get('id', 0) temp = unit.get('temp', 'N/A') humidity = unit.get('humidity', 'N/A') print(f"AMS Unit {unit_id}: {temp}C, Humidity {humidity}%") for tray in unit.get('tray', []): tray_id = tray.get('id', 0) remain = tray.get('remain', -1) if remain > 0: print(f" Tray {tray_id}: {remain}mm remaining") mqtt.connect() mqtt.subscribe_to_updates(on_message) # Keep running for real-time updates try: while True: time.sleep(1) finally: mqtt.disconnect() ``` #### Without AMS If printer doesn't have AMS, the response will be: ```json { "device_id": "01234567890ABCD", "has_ams": false, "total_trays": 0, "ams_units": [], "external_spool": { "tray_id": 254, "filament_type": "PLA", "filament_color": "FFFFFFFF", "remain": 0 } } ``` #### Limitations - **Static snapshot** - Not updated in real-time (use MQTT for that) - **AMS required** - Only works if printer has AMS installed - **May be empty** - Some printers may not report detailed tray data - **Field names vary** - Different firmware versions may use different field names - **Remaining inaccurate** - `remain` field may be -1 or 0 if not tracked --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management - [API_MQTT.md](API_MQTT.md) - MQTT protocol for real-time AMS updates - [API_REFERENCE.md](API_REFERENCE.md) - Error codes - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication --- # Bambu Lab Cloud API - Authentication **Last Updated:** 2025-10-28 This document covers all authentication methods for the Bambu Lab Cloud API, including the new login flow with two-factor authentication. --- ## Quick Start: Login with 2FA ### Using the CLI Tool ```bash # Interactive login (recommended) python cli_tools/login.py # Non-interactive login python cli_tools/login.py --username user@email.com --password yourpass # China region python cli_tools/login.py --region china --username user@email.com # Verify existing token python cli_tools/login.py --verify-only # Test token by fetching profile python cli_tools/login.py --test ``` ### Using the Python API ```python from bambulab import BambuAuthenticator, BambuClient # Authenticate and get token auth = BambuAuthenticator(region="global") token = auth.login( username="your-email@example.com", password="your-password" ) # Token is automatically saved to ~/.bambu_token # Use with API client client = BambuClient(token=token) devices = client.get_devices() ``` --- ## Login Flow with Two-Factor Authentication Bambu Lab enforces two-factor authentication via email verification for all users. ### Authentication Process 1. **Initial Login**: Submit email and password 2. **Verification Code**: Bambu Lab sends 6-digit code to your email 3. **Code Verification**: Enter code to complete authentication 4. **Token Received**: Get access token for API calls ### Python Implementation ```python from bambulab import BambuAuthenticator, BambuAuthError auth = BambuAuthenticator() try: # Method 1: Interactive (prompts for code) token = auth.login("user@email.com", "password") # Method 2: Custom callback def get_code(): return input("Enter code from email: ") token = auth.login("user@email.com", "password", get_code) # Method 3: Use saved token if valid, login if needed token = auth.get_or_create_token( username="user@email.com", password="password" ) print(f"Logged in! Token: {token[:20]}...") except BambuAuthError as e: print(f"Authentication failed: {e}") ``` ### Token Storage Tokens are automatically saved to `~/.bambu_token` with secure permissions (0600): ```python { "region": "global", "token": "eyJhbGc..." } ``` Custom token file location: ```python auth = BambuAuthenticator(token_file="/path/to/token.json") ``` --- ## Login API Endpoints ### 1. Initial Login **Endpoint:** `POST /v1/user-service/user/login` **Request:** ```json { "account": "user@email.com", "password": "your_password", "apiError": "" } ``` **Response (Success):** ```json { "success": true, "accessToken": "eyJhbGc..." } ``` **Response (2FA Required):** ```json { "success": false, "loginType": "verifyCode" } ``` **Response (MFA Required):** ```json { "success": false, "loginType": "tfa", "tfaKey": "..." } ``` ### 2. Send Verification Code **Endpoint:** `POST /v1/user-service/user/sendemail/code` **Request:** ```json { "email": "user@email.com", "type": "codeLogin" } ``` **Response:** ```json { "success": true, "message": "Verification code sent" } ``` ### 3. Verify Code and Login **Endpoint:** `POST /v1/user-service/user/login` **Request:** ```json { "account": "user@email.com", "code": "123456" } ``` **Response:** ```json { "success": true, "accessToken": "eyJhbGc..." } ``` ### 4. MFA Verification (if enabled) **Endpoint:** `POST /api/sign-in/tfa` **Request:** ```json { "tfaKey": "...", "tfaCode": "123456" } ``` --- ## BambuAuthenticator API Reference ### Class: `BambuAuthenticator` ```python class BambuAuthenticator: def __init__( self, region: str = "global", token_file: Optional[str] = None ) ``` **Parameters:** - `region`: API region - "global" (default) or "china" - `token_file`: Path to save tokens (default: `~/.bambu_token`) ### Methods #### `login()` Perform login with 2FA support. ```python def login( self, username: str, password: str, code_callback: Optional[Callable[[], str]] = None ) -> str ``` **Parameters:** - `username`: Bambu Lab account email - `password`: Account password - `code_callback`: Optional function to get verification code **Returns:** Access token string **Raises:** `BambuAuthError` on failure #### `get_or_create_token()` Get existing token or login if needed. ```python def get_or_create_token( self, username: Optional[str] = None, password: Optional[str] = None, code_callback: Optional[Callable[[], str]] = None, force_new: bool = False ) -> str ``` **Parameters:** - `username`: Account email (required if no saved token) - `password`: Account password (required if no saved token) - `code_callback`: Optional code input function - `force_new`: Force new login even if token exists **Returns:** Valid access token #### `save_token()` Save token to file. ```python def save_token(self, token: str) -> None ``` #### `load_token()` Load saved token from file. ```python def load_token(self) -> Optional[str] ``` **Returns:** Token string or None #### `verify_token()` Check if token is valid. ```python def verify_token(self, token: str) -> bool ``` **Returns:** True if valid, False otherwise --- ## Advanced Examples ### Automated Code Retrieval ```python def fetch_code_from_email(): """Fetch code from email automatically""" # Example: Use IMAP to read email import imaplib import re # Connect to email mail = imaplib.IMAP4_SSL('imap.gmail.com') mail.login('user@email.com', 'app_password') mail.select('INBOX') # Search for Bambu Lab email _, messages = mail.search(None, 'FROM "noreply@bambulab.com"') latest = messages[0].split()[-1] # Fetch and parse _, msg = mail.fetch(latest, '(RFC822)') email_body = msg[0][1].decode() # Extract 6-digit code match = re.search(r'\b\d{6}\b', email_body) return match.group(0) if match else None # Use with authenticator auth = BambuAuthenticator() token = auth.login("user@email.com", "password", fetch_code_from_email) ``` ### GUI Integration ```python import tkinter as tk from tkinter import messagebox def get_code_via_gui(): """Show GUI dialog for code input""" root = tk.Tk() root.withdraw() code = tk.simpledialog.askstring( "Verification Code", "Enter the 6-digit code from your email:" ) return code auth = BambuAuthenticator() token = auth.login("user@email.com", "password", get_code_via_gui) ``` ### Retry Logic ```python from bambulab import BambuAuthenticator, BambuAuthError import time def login_with_retry(username, password, max_retries=3): """Login with retry logic""" auth = BambuAuthenticator() for attempt in range(max_retries): try: token = auth.login(username, password) return token except BambuAuthError as e: if attempt < max_retries - 1: print(f"Attempt {attempt + 1} failed: {e}") print("Retrying in 5 seconds...") time.sleep(5) else: raise return None token = login_with_retry("user@email.com", "password") ``` --- ## Base URLs ### Production APIs **Global (International):** ```text Main API: https://api.bambulab.com Portal: https://e.bambulab.com ``` **China Region:** ```text Main API: https://api.bambulab.cn Portal: https://e.bambulab.cn ``` ### Development/Testing APIs (Internal) ```text Dev API: https://api-dev.bambulab.net QA API: https://api-qa.bambulab.net Pre-prod: https://api-pre.bambulab.net ``` --- ## Authentication Headers All authenticated API requests require these headers: ```http Authorization: Bearer Content-Type: application/json x-bbl-app-certification-id: x-bbl-device-security-sign: ``` ### Header Descriptions | Header | Required | Description | |--------|----------|-------------| | `Authorization` | Yes | Bearer token obtained from login | | `Content-Type` | Yes | Always `application/json` for API requests | | `x-bbl-app-certification-id` | Optional | Device certificate ID for enhanced security | | `x-bbl-device-security-sign` | Optional | RSA signature of current timestamp | --- ## Certificate-Based Authentication The Bambu Connect app uses RSA certificate-based signing for enhanced security: ### Process 1. App has a device certificate with RSA key pair 2. Signs current timestamp with private key 3. Sends signature in `x-bbl-device-security-sign` header 4. Sends certificate ID in `x-bbl-app-certification-id` header 5. Server verifies signature with public key from certificate ### Certificate Format - **Algorithm:** RSA 2048-bit or higher - **Signature Algorithm:** SHA-256 - **Certificate Storage:** Secure local storage in app ### Python Example (Simplified) ```python import time from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import serialization def sign_timestamp(private_key_pem): timestamp = str(int(time.time() * 1000)) # Load private key private_key = serialization.load_pem_private_key( private_key_pem.encode(), password=None ) # Sign timestamp signature = private_key.sign( timestamp.encode(), padding.PKCS1v15(), hashes.SHA256() ) # Return base64 encoded signature import base64 return base64.b64encode(signature).decode() # Usage headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", "x-bbl-app-certification-id": cert_id, "x-bbl-device-security-sign": sign_timestamp(private_key) } ``` --- ## JWT Token Format Bambu Lab uses JWT (JSON Web Tokens) for authentication. ### Token Structure ```json { "header": { "alg": "RS256", "typ": "JWT" }, "payload": { "user_id": "012345678", "email": "0123@01234567890", "permissions": ["device:read", "device:write", "files:upload"], "exp": 1761435401, "iat": 1761349001 }, "signature": "..." } ``` ### Token Properties - **Algorithm:** RS256 (RSA with SHA-256) - **Expiration:** Typically 24 hours - **Refresh:** Must obtain new token after expiration - **Scope:** Contains user_id and permissions ### Obtaining a Token **Note:** The login endpoint is not publicly documented. You must obtain a token through: 1. Official Bambu Connect app 2. Bambu Handy mobile app 3. Web portal login flow ### Token Usage ```python import requests headers = { "Authorization": f"Bearer {your_token}", "Content-Type": "application/json" } response = requests.get( "https://api.bambulab.com/v1/iot-service/api/user/bind", headers=headers ) ``` --- ## Security Best Practices ### Secure Token Storage - Store tokens securely (encrypted storage, keychain, etc.) - Never commit tokens to version control - Use environment variables for development - Implement token refresh before expiration ### Certificate Management - Keep private keys secure and never expose them - Rotate certificates periodically - Use hardware security modules (HSM) for production - Implement certificate revocation checking ### Network Security - Always use HTTPS - Validate SSL certificates - Implement certificate pinning for production apps - Use secure network connections (avoid public WiFi) ### Error Handling ```python def make_authenticated_request(url, token): headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } try: response = requests.get(url, headers=headers, timeout=30) if response.status_code == 401: print("Authentication failed - token expired or invalid") # Implement token refresh logic here return None elif response.status_code == 403: print("Access forbidden - insufficient permissions") return None response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Request failed: {e}") return None ``` --- ## Common Authentication Errors ### 401 Unauthorized **Causes:** - Expired token - Invalid token - Missing Authorization header - Malformed Bearer token **Solution:** - Obtain a new token - Verify token format: `Bearer ` - Check token expiration time ### 403 Forbidden **Causes:** - Insufficient permissions - Token valid but user lacks access - Device not bound to user account **Solution:** - Verify user permissions - Ensure device is bound to your account - Check if feature requires premium subscription ### 400 Bad Request **Causes:** - Missing required headers - Invalid certificate signature - Malformed request **Solution:** - Verify all required headers are present - Check certificate signing implementation - Validate request body format --- ## Python Authentication Example Complete example showing authentication workflow: ```python import requests import os class BambuAuth: def __init__(self, token, region="global"): self.token = token self.base_url = ( "https://api.bambulab.com" if region == "global" else "https://api.bambulab.cn" ) def get_headers(self): return { "Authorization": f"Bearer {self.token}", "Content-Type": "application/json" } def test_auth(self): """Test if authentication is working""" url = f"{self.base_url}/v1/user-service/my/profile" response = requests.get(url, headers=self.get_headers()) if response.status_code == 200: print("Authentication successful") return True else: print(f"Authentication failed: {response.status_code}") return False def get_devices(self): """Get list of bound devices""" url = f"{self.base_url}/v1/iot-service/api/user/bind" response = requests.get(url, headers=self.get_headers()) response.raise_for_status() return response.json() # Usage token = os.getenv("BAMBU_TOKEN") auth = BambuAuth(token) if auth.test_auth(): devices = auth.get_devices() print(f"Found {len(devices.get('devices', []))} devices") ``` --- ## Rate Limiting Authentication endpoints have specific rate limits: - **Login attempts:** 5 per minute - **Token refresh:** 10 per hour - **Profile access:** 60 per minute - **Device queries:** 120 per minute Exceeding rate limits returns `429 Too Many Requests`. --- ## Support and Troubleshooting ### Debug Authentication Issues ```python def debug_auth(token, base_url): import jwt import datetime # Decode token (without verification for debugging) try: decoded = jwt.decode(token, options={"verify_signature": False}) print("Token Payload:") print(f" User ID: {decoded.get('user_id')}") print(f" Issued: {datetime.datetime.fromtimestamp(decoded.get('iat', 0))}") print(f" Expires: {datetime.datetime.fromtimestamp(decoded.get('exp', 0))}") # Check if expired if decoded.get('exp', 0) < time.time(): print(" Status: EXPIRED") else: print(" Status: VALID") except Exception as e: print(f"Token decode error: {e}") # Test connection response = requests.get( f"{base_url}/v1/user-service/my/profile", headers={"Authorization": f"Bearer {token}"} ) print(f"\nAPI Response: {response.status_code}") if response.status_code != 200: print(f"Error: {response.text}") ``` ### Common Issues 1. **Token won't work across regions** - Global and China tokens are separate - Must use matching API endpoint 2. **Certificate signature fails** - Check timestamp is current (within 5 minutes) - Verify private key matches certificate - Ensure correct signature algorithm (SHA-256) 3. **Intermittent auth failures** - Check network connectivity - Verify system time is accurate - Implement retry logic with exponential backoff --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management endpoints - [API_USERS.md](API_USERS.md) - User profile endpoints - [API_REFERENCE.md](API_REFERENCE.md) - Error codes and responses --- # Bambu Lab Cloud API - Camera & Video Streaming **Last Updated:** 2025-10-25 This document covers camera credentials, TUTK P2P protocol, video streaming, and local JPEG access. --- ## Base URLs **Global:** https://api.bambulab.com **China:** https://api.bambulab.cn **Authentication:** Bearer Token (see [API_AUTHENTICATION.md](API_AUTHENTICATION.md)) --- ### Camera & Video Streaming #### Overview Bambu Lab printers support camera streaming using two methods: 1. **TUTK P2P Protocol** - Remote access via proprietary P2P (used by Bambu Studio/Handy) 2. **Local JPEG Stream** - Direct TCP connection on same network (higher quality, lower latency) #### Get Camera Credentials (TTCode) ```http POST /v1/iot-service/api/user/ttcode Content-Type: application/json Request Body: { "dev_id": "01234567890ABCD" } Response: { "message": "success", "code": null, "error": null, "ttcode": "01234567890ABCDEF012", "authkey": "01234567", "passwd": "012345", "region": "us", "type": "tutk", "streams": null, "peers": null, "stream_key": "", "stream_salt": "", "channel_name": "", "app_id": "", "rtm": null } ``` **Response Fields:** | Field | Description | |-------|-------------| | `ttcode` | TUTK P2P UID for camera connection | | `authkey` | Authentication key for TUTK protocol | | `passwd` | Camera access password (6-character hex) | | `type` | Protocol type (`tutk` for P2P) | | `region` | Server region (`us` or `cn`) | | `stream_key` | Reserved for future cloud streaming | | `stream_salt` | Reserved for future cloud streaming | | `channel_name` | Reserved for future cloud streaming | | `app_id` | Reserved for future cloud streaming | | `rtm` | Real-time messaging config (unused) | | `streams` | Reserved (null) | | `peers` | Reserved (null) | #### What is TUTK? **TUTK (Throughtek UDP Tunnel Kit)** is a peer-to-peer video streaming protocol: - Proprietary P2P protocol (not HTTP/RTSP) - Works through firewalls/NAT without port forwarding - Used by Bambu Studio and Bambu Handy for remote camera access - Requires TUTK SDK (not open source) - Lower latency than cloud-based streaming - Reduced server costs for Bambu Lab TUTK is a P2P protocol, not HTTP/RTSP, so: - Can't use VLC/ffmpeg with a simple URL - No direct HTTPS streaming endpoint - Not compatible with standard video players - Lower latency (peer-to-peer) - Works through NAT/firewalls - Built into Bambu Studio/Handy #### Camera Streaming Methods **1. Remote TUTK P2P Streaming** (Works Anywhere) Uses the TTCode credentials from the API: ```python # Get TUTK credentials ttcode_data = client.get_ttcode("01234567890ABCD") # TUTK connection parameters: # - UID: ttcode_data['ttcode'] # Example: 01234567890ABCDEF012 # - Auth Key: ttcode_data['authkey'] # Example: 01234567 # - Password: ttcode_data['passwd'] # Example: 012345 # Requires TUTK SDK (proprietary, not included in this library) # Best used through Bambu Studio or Bambu Handy apps ``` **Viewing via TUTK:** 1. Open Bambu Studio or Bambu Handy 2. Select your printer 3. View live camera feed 4. Works from anywhere (not limited to local network) **2. Local JPEG Stream** (Same Network Only) Direct TCP connection for higher quality and lower latency: ```python from bambulab import JPEGFrameStream # Connect to printer on local network stream = JPEGFrameStream( ip="012.012.0.012", access_code="01234567", # 8-digit access code from printer model="P1S" # or "X1C", "A1", etc. ) # Connect stream.connect() # Get frames while True: frame = stream.get_frame() # Returns PIL Image if frame: # Display or save frame frame.show() # or frame.save('snapshot.jpg') time.sleep(0.1) stream.disconnect() ``` **Local Stream Details:** - Protocol: TLS over TCP - Port: 6000 (P1/A1 models) - Format: JPEG frames - Resolution: 1920x1080 or 1280x720 - Frame Rate: ~10-30 FPS (varies by model) - Requires: 8-digit access code from printer screen **Camera Viewer CLI Tool:** ```bash cd cli_tools python camera_viewer.py --ip 012.012.0.012 --code 01234567 --model P1S ``` Displays live camera feed in a window. #### Cloud Streaming Status **Current Status:** Not Available The API response includes empty fields for cloud streaming: - `streams` = null - `stream_key` = "" - `channel_name` = "" - `app_id` = "" These fields are reserved for future cloud streaming features (likely WebRTC-based) but are not currently implemented. #### Local vs Remote Comparison | Feature | Local JPEG | TUTK P2P | Cloud (N/A) | |---------|-----------|----------|-------------| | **Network** | Same LAN only | Anywhere | Anywhere | | **Quality** | High (1080p) | Medium | Unknown | | **Latency** | Very Low | Low | High | | **Setup** | Access code | TTCode API | N/A | | **Tools** | JPEGFrameStream | Bambu Studio | N/A | | **SDK Required** | No | Yes | N/A | #### Python Examples ##### Example 1: Get TTCode Credentials ```python from bambulab import BambuClient client = BambuClient("YOUR_TOKEN") # Get camera credentials for remote access ttcode = client.get_ttcode("01234567890ABCD") print(f"TUTK UID: {ttcode['ttcode']}") print(f"Auth Key: {ttcode['authkey']}") print(f"Password: {ttcode['passwd']}") print(f"Region: {ttcode['region']}") # These credentials work with: # - Bambu Studio (built-in TUTK support) # - Bambu Handy (mobile app) # - Custom apps using TUTK SDK ``` ##### Example 2: Local Camera Streaming ```python from bambulab import JPEGFrameStream import cv2 import numpy as np # Connect to local camera stream = JPEGFrameStream("012.012.0.012", "01234567", model="P1S") stream.connect() try: while True: # Get frame as PIL Image pil_frame = stream.get_frame() if pil_frame: # Convert to OpenCV format for processing frame = cv2.cvtColor(np.array(pil_frame), cv2.COLOR_RGB2BGR) # Display cv2.imshow('Bambu Camera', frame) # Press 'q' to quit if cv2.waitKey(1) & 0xFF == ord('q'): break finally: stream.disconnect() cv2.destroyAllWindows() ``` ##### Example 3: Save Snapshots ```python from bambulab import JPEGFrameStream from datetime import datetime stream = JPEGFrameStream("012.012.0.012", "01234567", model="P1S") stream.connect() # Take a snapshot frame = stream.get_frame() if frame: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") frame.save(f"snapshot_{timestamp}.jpg") print(f"Snapshot saved: snapshot_{timestamp}.jpg") stream.disconnect() ``` ##### Example 4: Monitor Print via Camera ```python from bambulab import JPEGFrameStream, MQTTClient import time # Setup MQTT for print status mqtt = MQTTClient( username="bblp", token="your_token", device_id="01234567890ABCD" ) # Setup camera camera = JPEGFrameStream("012.012.0.012", "01234567", model="P1S") # Connect both mqtt.connect() camera.connect() # Monitor printing def on_status(data): if 'print' in data: progress = data['print'].get('mc_percent', 0) if progress > 0: # Take snapshot at progress milestones if progress % 10 == 0: frame = camera.get_frame() if frame: frame.save(f"print_progress_{progress}pct.jpg") print(f"Snapshot at {progress}%") mqtt.subscribe_to_updates(on_status) try: while True: time.sleep(1) finally: mqtt.disconnect() camera.disconnect() ``` #### Camera Access Requirements **For Local JPEG Stream:** - Printer IP address (same network) - 8-digit access code (from printer screen settings) - Printer model (P1S, X1C, A1, etc.) **For TUTK P2P Stream:** - Bambu Lab Cloud account token - Device serial number - Bambu Studio or Bambu Handy app (easiest) - OR TUTK SDK for custom apps (proprietary) #### Troubleshooting **Local Stream Issues:** - **Connection refused:** Check IP address and network - **Authentication failed:** Verify 8-digit access code - **Timeout:** Ensure firewall allows port 6000 - **No frames:** Camera might be disabled in printer settings **TUTK Issues:** - **TTCode not working:** Token may be expired, get new one - **Cannot connect from remote:** Firewall blocking UDP P2P - **No video in app:** Camera may be disabled on printer **General:** - **Black screen:** Check printer camera settings - **Low FPS:** Network congestion or weak signal - **Choppy video:** Use local stream instead of TUTK for better quality --- --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management - [API_MQTT.md](API_MQTT.md) - MQTT protocol - [API_REFERENCE.md](API_REFERENCE.md) - Error codes - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication --- # Bambu Lab Cloud API - Device Management **Last Updated:** 2025-10-25 This document covers device binding, management, print jobs, projects, tasks, and notifications. --- ## Base URLs **Global:** https://api.bambulab.com **China:** https://api.bambulab.cn **Authentication:** Bearer Token (see [API_AUTHENTICATION.md](API_AUTHENTICATION.md)) --- ### IOT Service (`/v1/iot-service/api/`) Handles device management, printing, and IoT operations. #### User Device Management ##### Get Bound Devices ```http GET /v1/iot-service/api/user/bind Response: { "message": "success", "code": null, "error": null, "devices": [ { "dev_id": "01234567890ABCD", "name": "P1S 1", "online": true, "print_status": "ACTIVE", "dev_model_name": "C11", "dev_product_name": "P1P", "dev_access_code": "012345679" } ] } ``` ##### Bind Device to User ```http POST /v1/iot-service/api/user/bind Content-Type: application/json Authorization: Bearer Request Body: { "device_id": "GLOF01234567901", "device_name": "My Printer", "bind_code": "01234567" } Response: { "code": 0, "message": "Success", "data": { "bind_id": "...", "device_info": {...} } } ``` ##### Get Device Information ```http GET /v1/iot-service/api/user/device/info GET /v1/iot-service/api/user/device/info?device_id Response: { "code": 0, "data": { "device_id": "GLOF01234567901", "device_name": "X1 Carbon", "model": "X1C", "status": "online", "firmware_version": "01.01.01.01", "nozzle_temp": 220, "bed_temp": 60, ... } } ``` ##### Get Device Version ```http GET /v1/iot-service/api/user/device/version GET /v1/iot-service/api/user/device/version?device_id Response: { "code": 0, "data": { "current_version": "01.01.01.01", "latest_version": "01.01.01.01", "update_available": true, "release_notes": "..." } } ``` ##### Unbind Device from User ```http DELETE /v1/iot-service/api/user/bind?dev_id= Authorization: Bearer Response: { "code": 0, "message": "Device unbound successfully" } ``` #### Printing Operations ##### Get Print Jobs ```http GET /v1/iot-service/api/user/print GET /v1/iot-service/api/user/print?device_id GET /v1/iot-service/api/user/print?statusprinting|completed|failed Response: { "code": 0, "data": { "jobs": [ { "job_id": "12345", "file_name": "model.3mf", "status": "printing", "progress": 45, "time_remaining": 3600, "started_at": "2024-10-18T10:00:00Z" } ] } } ``` ##### Start Print Job ```http POST /v1/iot-service/api/user/print Content-Type: application/json Request Body: { "device_id": "GLOF01234567901", "file_id": "012345", "file_name": "model.3mf", "file_url": "https://...", "settings": { "layer_height": 0.2, "infill": 20, "speed": 100 } } Response: { "code": 0, "data": { "job_id": "12345", "status": "queued" } } ``` #### Project Management ##### Get Projects ```http GET /v1/iot-service/api/user/project GET /v1/iot-service/api/user/project?page1&limit20 Response: { "code": 0, "data": { "projects": [ { "project_id": "proj_123", "name": "My Design", "created_at": "2024-10-18T10:00:00Z", "file_count": 3 } ], "total": 45, "page": 1 } } ``` ##### Get Project Details ```http GET /v1/iot-service/api/user/project/{project_id} Response: { "code": 0, "data": { "project_id": "proj_123", "name": "My Design", "created_at": "2024-10-18T10:00:00Z", "updated_at": "2024-10-18T12:00:00Z", "file_count": 3, "files": [...] } } ``` #### Tasks Management Tasks represent print jobs and file operations associated with devices. ##### Get User Tasks ```http GET /v1/user-service/my/tasks GET /v1/user-service/my/tasks?deviceId=&after=&limit=20 Parameters: - deviceId: Filter by device (optional) - after: Pagination cursor (task ID) - limit: Results per page (default: 20) Response: { "tasks": [ { "id": "012345678", "designId": "012345678", "designTitle": "Cube", "deviceId": "01234567890ABCD", "deviceName": "P1S 3", "modelId": "012345678", "profileId": "012345678", "status": "failed", "weight": 12.5, "length": 1850.2, "costTime": 3600, "startTime": "2024-10-24T10:00:00Z", "endTime": "2024-10-24T11:00:00Z", "cover": "https://...", "thumbnail": "https://..." } ], "hits": { "total": { "value": 156, "relation": "eq" } } } ``` ##### Get Single Task ```http GET /v1/iot-service/api/user/task/{task_id} Response: { "code": 0, "data": { "task_id": "012345678", "device_id": "01234567890ABCD", "status": "completed", "progress": 100, "file_name": "model.3mf", "started_at": "2024-10-24T10:00:00Z", "completed_at": "2024-10-24T11:00:00Z" } } ``` ##### Create Task ```http POST /v1/user-service/my/task Content-Type: application/json Request Body: { "modelId": "012345678", "title": "My Print Job", "deviceId": "01234567890ABCD", "profileId": "012345678" } Response: { "id": "012345678", "status": "created" } ``` #### File Upload ##### Get Upload URL ```http GET /v1/iot-service/api/user/upload GET /v1/iot-service/api/user/upload?filename=model.3mf&size=012345 Parameters: - filename: Name of file to upload - size: File size in bytes Response: { "message": "success", "code": null, "error": null, "host": "user", "urls": [ { "type": "filename", "file": "model.3mf", "url": "https://s3.us-west-2.amazonaws.com/or-cloud-upload-prod/users/012345678/filename/01234567890ABCDEF0/model.3mf?AWSAccessKeyId=01234567890ABCDEF012&Expires=0123456789&Signature=01234567890ABCDEF01234567890ABCDEF" }, { "type": "size", "file": "012345", "url": "https://s3.us-west-2.amazonaws.com/or-cloud-upload-prod/users/012345678/size/01234567890ABCDEF0/012345?AWSAccessKeyId=01234567890ABCDEF012&Expires=0123456789&Signature=01234567890ABCDEF01234567890ABCD" } ] } ``` ##### Upload to S3 (Step 1: Filename) ```http PUT Content-Type: application/octet-stream Content-Length: 012345 Response: 200 OK ``` ##### Upload to S3 (Step 2: Size) ```http PUT Content-Type: text/plain Content-Length: 6 012345 Response: 200 OK ``` **Important Notes:** - Must upload to BOTH URLs (filename AND size) for successful upload - Use exact Content-Type headers as specified - URLs are pre-signed by AWS and expire after the time indicated - Size URL expects the file size as plain text - Signature mismatch errors typically indicate wrong Content-Type or HTTP method #### Notifications ##### Get Notifications ```http GET /v1/iot-service/api/user/notification GET /v1/iot-service/api/user/notification?unreadtrue Response: { "code": 0, "data": { "notifications": [ { "id": "notif_123", "type": "print_complete", "message": "Print job completed successfully", "timestamp": "2024-10-18T10:00:00Z", "read": false } ] } } ``` ##### Mark Notification as Read ```http PUT /v1/iot-service/api/user/notification Content-Type: application/json Request Body: { "notification_id": "notif_123", "read": true } ``` --- ## See Also - [API_USERS.md](API_USERS.md) - User profiles and accounts - [API_FILES_PRINTING.md](API_FILES_PRINTING.md) - File upload and printing - [API_MQTT.md](API_MQTT.md) - MQTT protocol and commands - [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) - AMS and filament data - [API_CAMERA.md](API_CAMERA.md) - Camera and video streaming - [API_REFERENCE.md](API_REFERENCE.md) - Error codes and responses - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication methods --- # Bambu Lab Cloud API - Files & Cloud Printing **Last Updated:** 2025-10-25 This document covers file upload to cloud storage, cloud file management, starting cloud prints, and troubleshooting. --- ## Base URLs **Global:** https://api.bambulab.com **China:** https://api.bambulab.cn **S3 Upload:** https://s3.us-west-2.amazonaws.com/or-cloud-upload-prod/ **Authentication:** Bearer Token (see [API_AUTHENTICATION.md](API_AUTHENTICATION.md)) --- ## CLOUD FEATURES ### Cloud Files and Printing After uploading files to Bambu Cloud, you can list files and start remote prints. #### List Cloud Files ```python from bambulab import BambuClient client = BambuClient("YOUR_TOKEN") # Get all files in cloud storage files = client.get_cloud_files() for f in files: print(f"File: {f['name']}") print(f"ID: {f.get('file_id')}") print(f"URL: {f.get('file_url')}") ``` **What it does:** - Searches multiple endpoints for your files - Returns projects, tasks, uploaded files - Shows file names, IDs, URLs #### Start Cloud Print ```python # Start a print from uploaded file result = client.start_cloud_print( device_id="01234567890ABCD", filename="api_test.3mf" ) print(f"Print started: {result}") ``` **What it does:** - Finds the file by name in cloud storage - Starts printing on specified device - Returns print job information #### Manual Print Start If you know the file ID: ```python result = client.start_print_job( device_id="01234567890ABCD", file_id="012345", file_name="model.3mf", file_url="https://...", # Optional settings={ "layer_height": 0.2, "infill": 20, "speed": 100 } ) ``` #### Complete Upload and Print Workflow ```python from bambulab import BambuClient import time client = BambuClient("YOUR_TOKEN") # Step 1: Upload file print("Uploading file...") result = client.upload_file("my_model.3mf") if result['status_code'] in [200, 201, 204]: print(f"Upload successful: {result['filename']}") # Step 2: Wait for file to register time.sleep(2) # Step 3: List files to verify files = client.get_cloud_files() print(f"Found {len(files)} files in cloud") # Step 4: Start print print_result = client.start_cloud_print( device_id="01234567890ABCD", filename="my_model.3mf" ) print(f"Print started! Job ID: {print_result.get('job_id')}") ``` #### File Listing Details The `get_cloud_files()` method tries multiple endpoints: 1. **Projects endpoint** - Lists projects and their files 2. **Files endpoint** - Direct file listing 3. **Tasks endpoint** - May show files used in print tasks Returns unified list with: - `name` / `file_name` / `title` - File name - `file_id` / `model_id` / `id` - File identifier - `file_url` / `url` - Download/access URL - Other metadata (size, date, etc.) #### Print Job Response When starting a print, you get: ```python { 'job_id': 'job_012345', 'status': 'queued', # or 'pending', 'running' 'device_id': '01234567890ABCD', 'file_name': 'api_test.3mf', 'created_at': '2024-01-01T12:00:00Z', } ``` #### Print Settings Optional settings you can pass: ```python settings = { 'layer_height': 0.2, # mm 'infill': 20, # percent 'speed': 100, # percent 'temperature': 220, # nozzle temp (C) 'bed_temperature': 60, # bed temp (C) 'support': True, # enable supports 'brim': False, # enable brim } client.start_cloud_print( device_id="...", filename="model.3mf", settings=settings ) ``` #### Important Notes **File Availability:** - Uploaded files may take 1-2 seconds to appear in listings - Not all accounts have cloud storage enabled - Some regions may not support remote printing **Limitations:** - Can list uploaded files - Can start prints from cloud files - Can pass print settings - Can get job status - Can't download files from cloud (no download endpoint) - Can't delete files (endpoint unknown) - Can't modify files (must re-upload) - Can't perform real-time print control (use MQTT for monitoring) ### Cloud Video Streaming #### Overview Bambu Lab printers may support video streaming through the cloud when you're not on the local network. #### Getting Cloud Video URL ```python from bambulab import BambuClient client = BambuClient("YOUR_TOKEN") devices = client.get_devices() device_id = devices[0]['dev_id'] # Try to get cloud video stream video_info = client.get_cloud_video_url(device_id) if 'url' in video_info or 'stream_url' in video_info: url = video_info.get('url') or video_info.get('stream_url') print(f"Cloud stream URL: {url}") else: # Fall back to local streaming with TTCode ttcode = video_info.get('ttcode') print("Cloud streaming not available, use local access") ``` #### Availability - Not all accounts have cloud video enabled - May require Bambu Lab Cloud subscription - May be region-specific - If not available, use local streaming (TUTK or local JPEG/RTSP) #### Local vs Cloud Streaming **Local Streaming (Always Available):** - P1/A1: TLS/TCP port 6000 (JPEG frames) - X1: RTSP port 322 - Requires being on same network - No latency - Higher quality **Cloud Streaming (If Available):** - Works from anywhere - Goes through Bambu servers - May have latency - May be lower quality - Requires cloud subscription ### Upload Troubleshooting #### S3 Signature Issues **Error:** `SignatureDoesNotMatch` (403) This is NOT about certificates or X.509. The issue is with **S3 signed URLs**. **What S3 Signed URLs Do:** When you get an upload URL from Bambu's API: ```text https://s3.us-west-2.amazonaws.com/...?AWSAccessKeyId=...&Signature=...&Expires=... ``` AWS S3 pre-calculates a signature based on: - HTTP method (PUT) - URL path - Headers that will be sent - File content (sometimes) If ANY of these don't match, you get `SignatureDoesNotMatch`. **The Fix:** Use minimal/no extra headers: ```python response = requests.put( upload_url, data=file_content, headers={}, # Empty - let requests add only what's needed timeout=300 ) ``` The `requests` library will still add necessary headers like Content-Length automatically, but we're not forcing specific values that might break the signature. **Why This Happens:** S3 signed URLs are very strict: 1. Server generates URL with signature 2. Signature is based on exact request parameters 3. If client changes anything, signature fails 4. This includes adding headers server didn't expect The signed URL IS the authentication. It contains: - `AWSAccessKeyId` - Identifies the account - `Signature` - Proves the URL is valid - `Expires` - URL expiration timestamp **Other Possible Issues:** 1. **File size mismatch** - Make sure file size in get_upload_url() matches actual file 2. **Expired URL** - Signatures expire (check Expires parameter) 3. **Modified content** - File content must match what was specified 4. **Network proxy** - Proxy might add headers breaking signature #### Testing Upload Availability ```python from bambulab import BambuClient client = BambuClient("YOUR_TOKEN") # Test if upload is available try: upload_info = client.get_upload_url(filename="test.3mf", size=012345) if upload_info.get('upload_url') or upload_info.get('urls'): print("Cloud upload is available!") else: print("Cloud upload not available for this account") print("Full response:", upload_info) except Exception as e: print(f"Error checking upload: {e}") ``` #### Upload Troubleshooting Guide **Empty upload_info response:** - Your account may not have cloud storage - Try verifying your account in Bambu Studio - Check if cloud features work in Bambu Studio/Handy **"Cloud upload not available" message:** - This is expected for some accounts - Use local FTP upload instead - Contact Bambu Lab support to enable cloud features **Upload fails with 403/401:** - Token may be expired - get a new one - Account permissions issue - Try refreshing your session in Bambu Studio **Upload times out:** - File may be too large - Network connection issue - Cloud service may be unavailable ### Alternative: Local FTP Upload If cloud upload isn't available, you can upload files directly to the printer via FTP: ```python from bambulab import LocalFTPClient # Connect to printer ftp = LocalFTPClient("012.012.0.012", "01234567") ftp.connect() # Upload file ftp.upload_file("model.3mf", "/model.3mf") # Print it from bambulab import LocalPrintClient printer = LocalPrintClient("012.012.0.012", "01234567") printer.start_print("/model.3mf") ftp.disconnect() ``` --- ## EXAMPLES ### Complete Request Example ```bash curl -X GET "https://api.bambulab.com/v1/iot-service/api/user/device/info?device_id=GLOF01234567901" \ -H "Authorization: Bearer fascvj789VHXDKJVfs7fs9f9..." \ -H "Content-Type: application/json" \ -H "x-bbl-app-certification-id: GLOF01234567901:01234567901" \ -H "x-bbl-device-security-sign: cvhx78xVF78vxhjksdHSjdkjhfksd..." ``` ### Python Example ```python import requests BASE_URL = "https://api.bambulab.com/v1" TOKEN = "your_bearer_token" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", "x-bbl-app-certification-id": "your_cert_id", "x-bbl-device-security-sign": "your_signature" } # Get device info response = requests.get( f"{BASE_URL}/iot-service/api/user/device/info", headers=headers, params={"device_id": "GLOF01234567901"} ) print(response.json()) ``` --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management and print jobs - [API_USERS.md](API_USERS.md) - User tasks and projects - [API_MQTT.md](API_MQTT.md) - MQTT protocol for print control - [API_REFERENCE.md](API_REFERENCE.md) - Error codes - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication --- # Bambu Lab Cloud API - Documentation Index **Last Updated:** 2025-10-25 **Status:** Complete and Modular This is the master index for all Bambu Lab Cloud API documentation. The documentation has been split into focused, logical modules for easier navigation and reference. --- ## Quick Start 1. **Start Here:** [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Learn how to authenticate 2. **Get Devices:** [API_DEVICES.md](API_DEVICES.md) - Bind and manage your printers 3. **Upload Files:** [API_FILES_PRINTING.md](API_FILES_PRINTING.md) - Upload 3MF files and start prints 4. **Real-time Control:** [API_MQTT.md](API_MQTT.md) - Use MQTT for live printer control --- ## Documentation Modules ### Core API Documentation | Document | Focus Area | Lines | Description | |----------|-----------|-------|-------------| | [API_AUTHENTICATION.md](API_AUTHENTICATION.md) | Auth & Security | 387 | Authentication methods, JWT tokens, certificate signing, and security best practices | | [API_DEVICES.md](API_DEVICES.md) | Device Management | 411 | Binding devices, getting device info, print jobs, projects, tasks, and notifications | | [API_USERS.md](API_USERS.md) | User Accounts | 173 | User profiles, preferences, messages, and account management | | [API_FILES_PRINTING.md](API_FILES_PRINTING.md) | Files & Printing | 411 | Cloud file upload (S3), managing files, starting cloud prints, and troubleshooting | | [API_MQTT.md](API_MQTT.md) | Real-time Protocol | 255 | MQTT connection, topics, message formats, device commands, and monitoring | | [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) | AMS & Materials | 414 | AMS unit data, filament information, colors, types, and real-time monitoring | | [API_CAMERA.md](API_CAMERA.md) | Video Streaming | 343 | Camera credentials, TUTK P2P protocol, video streaming, and local JPEG access | | [API_REFERENCE.md](API_REFERENCE.md) | Standards & Codes | 399 | Response codes, error handling, rate limiting, pagination, and conventions | --- ## Documentation by Use Case ### Setting Up Access 1. [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Get your Bearer token 2. [API_USERS.md](API_USERS.md) - Verify your profile 3. [API_DEVICES.md](API_DEVICES.md) - Bind your printer to your account ### Uploading and Printing 1. [API_FILES_PRINTING.md](API_FILES_PRINTING.md) - Upload 3MF files to cloud 2. [API_DEVICES.md](API_DEVICES.md) - Start print job on device 3. [API_MQTT.md](API_MQTT.md) - Monitor print progress in real-time ### Real-time Monitoring 1. [API_MQTT.md](API_MQTT.md) - Connect to MQTT broker 2. [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) - Monitor filament levels 3. [API_CAMERA.md](API_CAMERA.md) - View live camera feed ### Advanced Control 1. [API_MQTT.md](API_MQTT.md) - Send control commands (pause, resume, stop) 2. [API_DEVICES.md](API_DEVICES.md) - Manage multiple printers 3. [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) - Read AMS sensor data --- ## API Endpoints Overview ### Base URLs **Global (International):** - REST API: `https://api.bambulab.com` - MQTT: `us.mqtt.bambulab.com:8883` **China Region:** - REST API: `https://api.bambulab.cn` - MQTT: `cn.mqtt.bambulab.com:8883` ### Endpoint Structure All REST API endpoints follow the pattern: ```text https://api.bambulab.com/v1/{service}/{resource} ``` **Services:** - `/v1/iot-service/api/` - Device and IoT operations - `/v1/user-service/` - User account management - `/v1/design-user-service/` - Design and preferences --- ## Response Format Standards All API responses follow this structure: ```json { "message": "success", "code": null, "error": null, "data": { ... } } ``` Or for newer endpoints: ```json { "code": 0, "message": "Success", "data": { ... } } ``` See [API_REFERENCE.md](API_REFERENCE.md) for complete response code documentation. --- ## Authentication Quick Reference All authenticated requests require: ```http Authorization: Bearer YOUR_TOKEN_HERE Content-Type: application/json ``` Optional security headers: ```http x-bbl-app-certification-id: YOUR_CERT_ID x-bbl-device-security-sign: SIGNED_TIMESTAMP ``` Full details: [API_AUTHENTICATION.md](API_AUTHENTICATION.md) --- ## MQTT Quick Reference **Connection:** ```text Host: us.mqtt.bambulab.com Port: 8883 (TLS) Username: u_{your_user_id} Password: {device_access_code} ``` **Topic Structure:** ```text device/{device_serial}/report (subscribe - receive updates) device/{device_serial}/request (publish - send commands) ``` Full details: [API_MQTT.md](API_MQTT.md) --- ## Data Models ### Device Object ```json { "dev_id": "01234567890ABCD", "name": "P1S 1", "online": true, "print_status": "ACTIVE", "dev_model_name": "C11", "dev_product_name": "P1P", "dev_access_code": "01234567" } ``` See [API_DEVICES.md](API_DEVICES.md) for complete device data structure. ### Task Object ```json { "id": "012345678", "designTitle": "My Print", "deviceId": "01234567890ABCD", "status": "completed", "progress": 100, "startTime": "2024-10-24T10:00:00Z", "endTime": "2024-10-24T11:00:00Z" } ``` See [API_DEVICES.md](API_DEVICES.md) for task management. ### AMS Object ```json { "ams": [{ "id": "0", "humidity": "3", "temp": "25.0", "tray": [ { "id": "1", "tray_type": "PETG", "tray_color": "FF0000FF", "remain": 85 } ] }] } ``` See [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) for AMS data structure. --- ## Python Client Library This repository includes a Python client library for easy API access: ```python from bambulab.bambuclient import BambuClient # Initialize client client = BambuClient(token="your_token_here", region="global") # Get devices devices = client.get_devices() print(f"Found {len(devices)} printers") # Get device info info = client.get_device_info(device_id="01234567890ABCD") print(f"Status: {info['status']}") # Upload file result = client.upload_file("model.3mf", "/path/to/model.3mf") print(f"Uploaded: {result['success']}") # Start print client.start_cloud_print( device_id="01234567890ABCD", file_id="model_id", file_name="model.3mf" ) ``` See the `/bambulab/` directory for full client implementation. --- ## Testing Comprehensive test suite available in `/tests/`: ```bash # Run all tests python tests/manual/test_comprehensive.py # Test specific functionality python tests/unit/test_mqtt.py python tests/unit/test_upload.py ``` Tests cover: - Authentication and token validation - Device binding and management - File upload to S3 - Cloud print starting - MQTT connection and commands - AMS data retrieval - Camera credential fetching --- ## Common Workflows ### Workflow 1: Upload and Print ```python # 1. Get devices devices = client.get_devices() device_id = devices[0]['dev_id'] # 2. Upload file upload_result = client.upload_file("model.3mf", "/path/to/model.3mf") # 3. Start print client.start_cloud_print( device_id=device_id, file_name="model.3mf" ) # 4. Monitor via MQTT mqtt_client.connect(device_id) mqtt_client.subscribe_status() ``` See [API_FILES_PRINTING.md](API_FILES_PRINTING.md) for detailed workflow. ### Workflow 2: Monitor Print Progress ```python # 1. Connect to MQTT mqtt = BambuMQTT(user_id, device_serial, access_code) mqtt.connect() # 2. Subscribe to status def on_status(data): print(f"Progress: {data['mc_percent']}%") print(f"Nozzle: {data['nozzle_temper']}C") print(f"Bed: {data['bed_temper']}C") mqtt.on_message = on_status mqtt.subscribe_status() # 3. Keep listening mqtt.loop_forever() ``` See [API_MQTT.md](API_MQTT.md) for real-time monitoring. ### Workflow 3: Check Filament Levels ```python # Via MQTT (real-time) mqtt.connect() status = mqtt.get_full_status() for ams in status['ams']['ams']: for tray in ams['tray']: if 'tray_type' in tray: print(f"Tray {tray['id']}: {tray['tray_type']}") print(f" Remaining: {tray['remain']}%") print(f" Color: {tray['tray_color']}") ``` See [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) for filament monitoring. --- ## Error Handling Standard error response: ```json { "code": 400, "message": "Bad Request", "error": "Invalid device ID format" } ``` Common error codes: - `400` - Bad Request (invalid parameters) - `401` - Unauthorized (invalid/expired token) - `403` - Forbidden (insufficient permissions) - `404` - Not Found (resource doesn't exist) - `429` - Too Many Requests (rate limit exceeded) - `500` - Internal Server Error See [API_REFERENCE.md](API_REFERENCE.md) for complete error code documentation. --- ## Rate Limits | Endpoint Category | Rate Limit | Window | |-------------------|------------|--------| | Authentication | 5 requests | 1 minute | | Device Queries | 120 requests | 1 minute | | File Upload | 10 uploads | 1 hour | | MQTT Connections | 5 connections | 5 minutes | | User Profile | 60 requests | 1 minute | See [API_REFERENCE.md](API_REFERENCE.md) for detailed rate limiting. --- **Quick Links:** - [Authentication](API_AUTHENTICATION.md) - [Devices](API_DEVICES.md) - [Users](API_USERS.md) - [Files & Printing](API_FILES_PRINTING.md) - [MQTT](API_MQTT.md) - [AMS & Filament](API_AMS_FILAMENT.md) - [Camera](API_CAMERA.md) - [Reference](API_REFERENCE.md) --- # Bambu Lab Cloud API - MQTT Protocol **Last Updated:** 2025-10-25 This document covers MQTT connection, topics, message formats, device commands, and real-time monitoring. --- ## MQTT Brokers **US Broker:** us.mqtt.bambulab.com:8883 **China Broker:** cn.mqtt.bambulab.com:8883 **Dev Broker:** dev.mqtt.bambu-lab.com:8883 **Protocol:** MQTT over TLS (port 8883) **Authentication:** Username (user ID) + Password (access code) --- ## MQTT PROTOCOL ### Connection ```text Broker: us.mqtt.bambulab.com Port: 8883 (TLS) Protocol: MQTT 3.1.1 / 5.0 Authentication: - Username: - Password: - TLS: Required ``` ### Topic Structure **Subscribe to device updates:** ```text device//report device//status printer//state ``` **Publish commands:** ```text device//request printer//command ``` ### Message Format **Print Commands:** ```json { "print": { "command": "start|pause|stop|resume", "sequence_id": "12345", "param": { "file_url": "https://...", "file_name": "model.3mf" } } } ``` **Request Full Status (pushall):** ```json { "pushing": { "command": "pushall" } } ``` This command requests the printer to send a complete status dump including all sensor data, temperatures, positions, AMS status, and current print job information. The response is received on the `device//report` topic. ### MQTT Status Response Structure When you subscribe to `device//report` or request full status with `pushall`, the printer sends comprehensive status data. **Full Status Message Structure:** The response is a nested JSON with a `print` object containing 60+ fields: ```json { "print": { // Temperatures "nozzle_temper": 23.625, "nozzle_target_temper": 0, "bed_temper": 20.71875, "bed_target_temper": 0, "chamber_temper": 5, // Print Progress "gcode_state": "IDLE|RUNNING|PAUSE|FAILED|FINISH", "mc_percent": 45, "mc_remaining_time": 3600, "layer_num": 125, "total_layer_num": 250, // Print Job Info "subtask_name": "model.3mf", "project_id": "012345678", "profile_id": "012345678", "task_id": "012345678", "subtask_id": "012345678", "gcode_file": "cache/012345678.gcode", // Fan Speeds (0-15 scale) "heatbreak_fan_speed": "0", "cooling_fan_speed": "0", "big_fan1_speed": "0", "big_fan2_speed": "0", "fan_gear": 0, // Speed Settings "spd_mag": 100, "spd_lvl": 2, // Print Stage "mc_print_stage": "0-20", "mc_print_sub_stage": 0, "print_type": "idle|cloud_file|local", "stg": [], "stg_cur": 255, // Hardware Info "nozzle_diameter": "0.4", "nozzle_type": "stainless_steel|hardened_steel", "lifecycle": "product", "wifi_signal": "-45dBm", // Errors & Status "print_error": 0, "hms": [ { "attr": 01234567, "code": 65543, "action": 0, "timestamp": 1761352945 } ], // AMS (Automatic Material System) "ams": { "ams": [ { "id": "0", "humidity": "3", "humidity_raw": "28", "temp": "25.0", "tray": [ { "id": "0", "tray_type": "PLA", "tray_color": "FF0000FF", "nozzle_temp_min": "190", "nozzle_temp_max": "230", "remain": 750 } ] } ], "ams_exist_bits": "1", "tray_exist_bits": "2", "tray_now": "255", "version": 2 }, // External Spool (Virtual Tray) "vt_tray": { "id": "254", "tray_type": "PETG", "tray_color": "FFFF00FF", "remain": 0 }, // Camera & Lighting "ipcam": { "ipcam_dev": "1", "ipcam_record": "enable", "timelapse": "disable", "resolution": "1920x1080", "tutk_server": "disable" }, "lights_report": [ { "node": "chamber_light", "mode": "on|off" } ], // Network "net": { "conf": 0, "info": [ { "ip": 3389106368, "mask": 01234567 } ] }, // Firmware Updates "upgrade_state": { "status": "IDLE|UPGRADING", "progress": "", "new_ver_list": [ { "name": "ota", "cur_ver": "01.01.01.01", "new_ver": "01.01.01.01" } ] }, // Command Info "command": "push_status", "msg": 0, "sequence_id": "1628" } } ``` **Key Field Categories:** | Category | Fields | Description | |----------|--------|-------------| | **Temperatures** | `nozzle_temper`, `bed_temper`, `chamber_temper` | Current temperatures in C | | **Progress** | `mc_percent`, `layer_num`, `mc_remaining_time` | Print progress info | | **State** | `gcode_state`, `mc_print_stage`, `print_type` | Current printer state | | **Speeds** | Fan speeds, `spd_mag`, `spd_lvl` | Fan speeds and print speed | | **AMS** | `ams`, `vt_tray` | Filament system status | | **Hardware** | `nozzle_diameter`, `nozzle_type`, `wifi_signal` | Hardware specs | | **Errors** | `print_error`, `hms` | Error codes and HMS messages | | **Camera** | `ipcam`, `lights_report` | Camera and lighting status | **Update Frequency:** - Status messages typically sent every 0.5-2 seconds - Full status on connection or when `pushall` requested - Frequency increases during active printing --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management - [API_AMS_FILAMENT.md](API_AMS_FILAMENT.md) - AMS data via MQTT - [API_CAMERA.md](API_CAMERA.md) - Camera streaming - [API_REFERENCE.md](API_REFERENCE.md) - Error codes - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication --- # Bambu Lab Cloud API - Reference **Last Updated:** 2025-10-25 This document covers response codes, error handling, rate limiting, pagination, and API conventions. --- ## Base URLs **Global:** https://api.bambulab.com **China:** https://api.bambulab.cn **Authentication:** Bearer Token (see [API_AUTHENTICATION.md](API_AUTHENTICATION.md)) --- ## RESPONSE CODES ### Standard Response Format ```json { "code": 0, "message": "Success", "data": { ... } } ``` ### Common Codes | Code | Meaning | |------|---------| | 0 | Success | | 400 | Bad Request | | 401 | Unauthorized | | 403 | Forbidden | | 404 | Not Found | | 429 | Too Many Requests | | 500 | Internal Server Error | ### Application-Specific Codes | Code | Meaning | |------|---------| | 1001 | Invalid Token | | 1002 | Token Expired | | 1003 | Device Not Found | | 1004 | Device Offline | | 1005 | Print Job Failed | | 1006 | File Upload Failed | --- ## ERROR HANDLING ### Error Response Format ```json { "code": 1001, "message": "Invalid token", "error": "TOKEN_INVALID", "details": { "reason": "Token signature verification failed" } } ``` ### Error Codes Found in Code ```text ERR_NETWORK ERR_INVALID_URL ERR_BAD_REQUEST ERR_BAD_RESPONSE ERR_CANCELED ERR_CHECKSUM_MISMATCH ERR_FR_TOO_MANY_REDIRECTS ERR_UPDATER_INVALID_VERSION ``` --- ## RATE LIMITING Expected limits (based on standard practices): - **Authenticated:** 1000 requests/hour - **Device Status:** 10 requests/minute per device - **File Upload:** 10 uploads/hour - **MQTT:** 100 messages/minute --- ## PAGINATION Standard pagination parameters: ```http GET /endpoint?page1&limit20&offset0 Response includes: { "data": [...], "pagination": { "page": 1, "limit": 20, "total": 150, "has_more": true } } ``` --- ## FILE OPERATIONS ### Upload Flow 1. **Request upload URL:** ```http POST /v1/iot-service/api/user/upload Response: { "upload_url": "https://..." } ``` 2. **Upload file to S3/CDN:** ```http PUT Content-Type: application/octet-stream Body: ``` 3. **Confirm upload:** ```http POST /v1/iot-service/api/user/upload/confirm Body: { "file_id": "..." } ``` ### Supported File Types - `.3mf` - 3D Model Format - `.gcode` - G-Code - `.stl` - STereoLithography - `.step` - STEP CAD format --- ## WEBHOOKS The API likely supports webhooks for events: ```text print.started print.completed print.failed device.online device.offline notification.created ``` --- ## TESTING ### Test Environments **Dev:** ```text API: https://api-dev.bambulab.net ``` **QA:** ```text API: https://api-qa.bambulab.net ``` **Pre-production:** ```text API: https://api-pre.bambulab.net API US: https://api-pre-us.bambulab.net ``` --- ## MQTT DEVICE COMMANDS The following MQTT commands can be sent to control printer devices via the MQTT broker. **Topic Format:** `device/{device_id}/request` ### Print Control Commands #### Pause Print **Command:** ```json { "print": { "command": "pause" } } ``` **Description:** Pauses the current print job. --- #### Resume Print **Command:** ```json { "print": { "command": "resume" } } ``` **Description:** Resumes a paused print job. --- #### Stop Print **Command:** ```json { "print": { "command": "stop" } } ``` **Description:** Stops the current print job. --- ### Temperature Control Commands #### Set Nozzle Temperature **Command:** ```json { "print": { "command": "set_nozzle_temp", "param": "" } } ``` **Parameters:** - `param` (integer): Target nozzle temperature in Celsius (e.g., 220) **Description:** Sets the target nozzle/hotend temperature. --- #### Set Bed Temperature **Command:** ```json { "print": { "command": "set_bed_temp", "param": "" } } ``` **Parameters:** - `param` (integer): Target bed temperature in Celsius (e.g., 60) **Description:** Sets the target heated bed temperature. --- #### Set Chamber Temperature **Command:** ```json { "print": { "command": "set_chamber_temp", "param": "" } } ``` **Parameters:** - `param` (integer): Target chamber temperature in Celsius (e.g., 35) **Description:** Sets the target chamber temperature (for printers with heated chambers). --- ### Fan Control Commands #### Set Fan Speed **Command:** ```json { "print": { "command": "set_fan_speed", "param": "" } } ``` **Parameters:** - `param` (integer): Fan speed percentage 0-100 **Description:** Sets the part cooling fan speed. --- #### Set Air Duct Fan **Command:** ```json { "print": { "command": "set_airduct", "param": "" } } ``` **Parameters:** - `param` (integer): Air duct fan speed percentage 0-100 **Description:** Controls the air duct/auxiliary fan speed. --- #### Set Chamber Fan (CTT) **Command:** ```json { "print": { "command": "set_ctt", "param": "" } } ``` **Parameters:** - `param` (integer): Chamber fan speed percentage 0-100 **Description:** Sets the chamber temperature control fan speed. --- ### MQTT Command Examples **Python example using paho-mqtt:** ```python import json import paho.mqtt.client as mqtt # Connection details BROKER = "us.mqtt.bambulab.com" PORT = 8883 DEVICE_ID = "your_device_id" ACCESS_CODE = "your_access_code" # Create MQTT client client = mqtt.Client() client.username_pw_set(username="bblp", password=ACCESS_CODE) client.tls_set() # Connect to broker client.connect(BROKER, PORT, 60) # Send pause command topic = f"device/{DEVICE_ID}/request" command = {"print": {"command": "pause"}} client.publish(topic, json.dumps(command)) # Send temperature command command = {"print": {"command": "set_nozzle_temp", "param": "220"}} client.publish(topic, json.dumps(command)) client.disconnect() ``` --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management - [API_USERS.md](API_USERS.md) - User profiles - [API_FILES_PRINTING.md](API_FILES_PRINTING.md) - File upload - [API_MQTT.md](API_MQTT.md) - MQTT protocol - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication --- # Bambu Lab Cloud API - User Management **Last Updated:** 2025-10-25 This document covers user profiles, preferences, messages, and account management. --- ## Base URLs **Global:** https://api.bambulab.com **China:** https://api.bambulab.cn **Authentication:** Bearer Token (see [API_AUTHENTICATION.md](API_AUTHENTICATION.md)) --- ### User Service (`/v1/user-service/`) Handles user account and profile management. #### User Profile ##### Get User Preferences ```http GET /v1/design-user-service/my/preference Response: { "uid": 123456789, "name": "user_012345678", "handle": "user_012345678", "avatar": "url", "bio": "", "links": [], "backgroundUrl": "url" } ``` ##### Get My Profile ```http GET /v1/user-service/my/profile Response: { "code": 0, "data": { "user_id": "user_012", "email": "0123@01234567890", "username": "JohnDoe", "avatar_url": "https://...", "created_at": "2024-01-01T00:00:00Z", "subscription": { "plan": "pro", "expires_at": "2025-01-01T00:00:00Z" } } } ``` ##### Update Profile ```http PUT /v1/user-service/my/profile Content-Type: application/json Request Body: { "username": "NewUsername", "avatar_url": "https://..." } Response: { "code": 0, "message": "Profile updated" } ``` #### User Messages ##### Get My Messages ```http GET /v1/user-service/my/messages GET /v1/user-service/my/messages?type&after&limit20 Response: { "hits": [ { "id": 0, "type": 6, "taskMessage": { "id": 1, "title": "Untitled", "cover": "https://...", "status": 2, "deviceId": "..." }, "from": { "uid": 2, "name": "User", "avatar": "https://..." }, "createTime": "2022-11-22T02:54:12Z" } ] } ``` #### User Tasks ##### Get My Tasks ```http GET /v1/user-service/my/tasks GET /v1/user-service/my/tasks?deviceId&after&limit20 Response: { "total": 5, "hits": [ { "id": 0, "designId": 0, "modelId": "...", "title": "Untitled", "cover": "https://...", "status": 2, "feedbackStatus": 0, "startTime": "2022-11-22T01:58:10Z", "endTime": "2022-11-22T02:54:12Z", "weight": 12.6, "costTime": 3348, "profileId": 0, "plateIndex": 1, "deviceId": "...", "amsDetailMapping": [], "mode": "cloud_file" } ] } ``` ##### Create Task ```http POST /v1/user-service/my/task Content-Type: application/json Request Body: { "modelId": "...", "title": "Print Job", "deviceId": "...", ... } ``` ##### Get Task by ID ```http GET /v1/iot-service/api/user/task/{task_id} ``` --- ## See Also - [API_DEVICES.md](API_DEVICES.md) - Device management - [API_FILES_PRINTING.md](API_FILES_PRINTING.md) - File upload and printing - [API_MQTT.md](API_MQTT.md) - MQTT protocol - [API_REFERENCE.md](API_REFERENCE.md) - Error codes - [API_AUTHENTICATION.md](API_AUTHENTICATION.md) - Authentication --- # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement via GitHub issues. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. --- # Installation Guide ## Quick Install ### From PyPI (Recommended) ```bash # Complete installation (includes all features) pip install bambu-lab-cloud-api # With development tools only pip install bambu-lab-cloud-api[dev] ``` **Note:** As of v1.0.4, the base install includes all features (API, MQTT, camera, proxy server). No need for `[server]` or `[all]` extras anymore! ### From GitHub (Latest) ```bash # Install directly from GitHub main branch pip install git+https://github.com/coelacant1/Bambu-Lab-Cloud-API.git ``` ### From Source (Development) ```bash # Clone the repository git clone https://github.com/coelacant1/Bambu-Lab-Cloud-API.git cd Bambu-Lab-Cloud-API # Install in development mode pip install -e . # Or with development tools pip install -e ".[dev]" ``` ## Configuration ### For Testing ```bash cd tests cp test_config.json.example test_config.json # Edit test_config.json with your credentials ``` ### For Proxy Server ```bash cd servers cp proxy_tokens.json.example proxy_tokens.json # Edit proxy_tokens.json with your token mappings ``` ### For Compatibility Layer ```bash cd servers cp compatibility_config.json.example compatibility_config.json # Edit compatibility_config.json with your credentials ``` ## Verify Installation ```bash # Test the library python -c "from bambulab import BambuClient; print('Success!')" # Run comprehensive tests cd tests python test_comprehensive.py ``` ## CLI Tools After installation, you can use the command-line tools: ```bash # Query printer status bambu-query --help # Monitor printer in real-time bambu-monitor --help # View camera feed bambu-camera --help ``` ## Dependencies ### Included in Base Install - `requests>=2.25.0` - HTTP API calls - `paho-mqtt>=1.6.0` - MQTT communication - `opencv-python>=4.0.0` - Camera streaming - `flask>=2.0.0` - Proxy server - `flask-cors>=3.0.0` - CORS support - `flask-limiter>=3.5.0` - Rate limiting ### Optional: Development Tools - `pytest>=7.0.0` - Testing framework - `pytest-cov>=4.0.0` - Coverage reporting Install with: `pip install bambu-lab-cloud-api[dev]` ## Troubleshooting ### Import Errors If you get import errors, ensure the package is installed: ```bash pip install -e . ``` ### Missing Dependencies Install all dependencies: ```bash pip install -r requirements.txt ``` ### Permission Errors On Linux/Mac, you may need to use `pip3` instead of `pip`: ```bash pip3 install -e . ``` --- # Security Policy ## Supported Versions | Version | Supported | | ------- | ------------------ | | 0.1.x | :white_check_mark: | ## Reporting a Vulnerability **Please do not report security vulnerabilities through public GitHub issues.** Instead, report them via: - **Email:** Create a security advisory through GitHub's private vulnerability reporting - **GitHub:** Use the "Security" tab -> "Report a vulnerability" ### What to Include - Description of the vulnerability - Steps to reproduce - Potential impact - Suggested fix (if any) ### Response Timeline - **Initial response:** Within 48 hours - **Status update:** Within 7 days - **Fix timeline:** Varies by severity ## Security Best Practices ### Token Management **DO:** - Store tokens in config files (gitignored) - Use environment variables for production - Rotate tokens regularly **DON'T:** - Commit tokens to repositories - Share tokens in public channels - Hardcode tokens in source code - Log tokens in application logs ### Proxy Server Usage - **Strict mode (port 5001):** Read-only operations - recommended for untrusted environments - **Full mode (port 5003):** Complete access - use only in secure, controlled environments - Always use custom token mapping to avoid exposing real Bambu Lab tokens ### API Rate Limiting - Respect Bambu Lab's API rate limits - Implement exponential backoff for retries - Cache responses when appropriate ### Local Network Security - MQTT and local FTP use access codes - treat these as passwords - Use TLS/SSL when available - Isolate printer network when possible ## Known Considerations - **Developer Mode Removal:** This library uses Cloud API as Bambu Lab removed local developer mode - **Access Codes:** Local printer access codes provide full control - protect them - **MQTT:** Messages may contain sensitive printer information ## Scope This project documents public API endpoints. Security issues should focus on: - Authentication handling in the library - Token exposure risks - Server proxy vulnerabilities - Dependency vulnerabilities Out of scope: - Vulnerabilities in Bambu Lab's services (report to Bambu Lab directly) - Physical printer security --- **Last Updated:** October 2025