Order endpoints
/print-jobsOrder list
Paginated list of the account's orders, sorted by creation date.
{
"items": [
{
"id": "b6b6c8b0-...",
"model_name": "Кронштейн",
"quantity_pieces": 4,
"material_name": "PETG",
"color_hex": "#000000",
"material_grams": 86.0,
"print_hours": 3.5,
"due_date": "2026-09-01",
"order_notes": "",
"workflow_status": "confirmed",
"printer_id": null,
"printer_name": null
}
],
"total": 1,
"page": 1,
"per_page": 50
}The real response has more fields (cost, discounts, customer, etc.) — only the ones needed for HA integration are shown here. The full set is the same as in the order's web UI.
/print-jobs/{id}Single order
Same structure as the list item above, for a specific id.
GET /print-jobs/b6b6c8b0-... → 200/print-jobs/{id}Update status (or other fields)
Send only the fields you're changing — the rest will remain unchanged.
PUT /print-jobs/b6b6c8b0-...
Content-Type: application/json
{ "workflow_status": "assigned" }A workflow_status value that isn’t in the table below (typo, outdated name) will silently roll the order back to “Negotiation” — the server won’t return an error. Double-check against the status list when sending.
Order statuses
| Value | Name | When to set it |
|---|---|---|
| negotiation | Negotiation | Order created, terms are still being discussed |
| confirmed | Confirmed | Customer confirmed, ready to print |
| modeling | Modeling | Modeling: order confirmed, the maker is preparing the 3D model; materials not deducted yet. New value since 11.0 |
| assigned | Printer assigned | HA has assigned a specific printer/spool to the order |
| printing | Printing | Print is running on the printer |
| print_error | Print error | Klipper/Moonraker reported a print error |
| packing | Packing | Order is being assembled and packed for shipment (incl. from finished-goods stock) |
| delivery | Delivery | Print is ready and on its way to the customer |
| delivered_unpaid | Delivered, awaiting payment | Delivered to the customer, waiting for payment (deferred/instalments); materials already deducted. New value since 11.0 |
| done | Done | Order completed |
| cancelled | Cancelled | Order cancelled |
| closed | Closed | Archived status, hidden from the main list |
Printer endpoints
Read-only — the farm’s printer list and a single printer’s data. Useful for matching an order’s printer_id to a real device, or showing its name/technology in an external system.
/printersPrinter list
All printers on the account, including those grouped into farms.
{
"items": [
{
"id": "3f2a9c10-...",
"name": "Bambu Lab P1S",
"internal_name": "Ферма 1 / принтер 3",
"model": "P1S",
"technology": "fdm",
"group_id": "a1b2c3d4-...",
"is_favorite": false,
"sort_order": 2
}
],
"total": 1,
"page": 1,
"per_page": 50
}The real response has more fields (hours run, cost, internal Bambu/Anycubic Cloud bindings, monitoring agent token) — they're not needed for external automation and aren't shown here.
/printers/{id}Single printer
Same structure as the list item above, for a specific id.
Filament endpoints
Read the material inventory catalog, and deduct weight from a spool as it's used — enough to wire up live tracking from Klipper/Moonraker, Home Assistant or n8n, the same idea as Spoolman's spool-weight endpoint.
/filamentsFilament list
All items in the account's material inventory.
{
"items": [
{
"id": "7c4d1e20-...",
"name": "PETG Black",
"brand": "eSUN",
"type_name": "PETG",
"colors": ["#000000"],
"is_gradient": false,
"spool_weight_grams": 1000.0,
"used_grams": 340.0,
"spool_count": 2,
"low_stock_threshold_grams": 150.0
}
],
"total": 1,
"page": 1,
"per_page": 50
}The spool price (spool_price_rub) is also in the response, but isn’t needed for farm automation and isn’t shown here.
/filaments/{id}Single filament
Same structure as the list item above, for a specific id.
/filaments/{id}/consumeDeduct spool weight
Deducts grams from the spool (FIFO across batches) and returns the updated filament. Use the same filament id as the field above.
Read-only API for your website and Excel
Create a token with Read only access in Settings → Integrations → Access tokens and choose the sections it may read: model catalog, orders, clients, stock, requests. Such a token answers 403 to any request that changes data, and to sections it was not given. The token goes only in the Authorization: Bearer pat_… header — a token inside a link (for example IMPORTDATA in Google Sheets) is deliberately not supported: links end up in browser history and logs.
/read-api/{orders|clients|stock|models|leads}Flat lists with pages, change date and CSV
Parameters: page, per_page (up to 1000), updated_since (ISO date/time — only rows changed since), format=json|csv, delimiter=, or ; (CSV). Orders also take workflow_status and is_paid, models — for_sale=true (storefront), stock — kind=filament|resin|finished. Client personal data (name, phone, email) appears only if the token was created with that option. Limit: 120 requests per minute and 3000 per hour per token.
GET https://api.3dprintpricing.pro/read-api/orders?updated_since=2026-10-01T00:00:00Z&per_page=200
Authorization: Bearer pat_...
GET https://api.3dprintpricing.pro/read-api/stock?format=csv&delimiter=%3BExcel (Power Query)
Data → Get Data → From Other Sources → Blank Query → Advanced Editor, paste the query below, replace the token. The standard “From Web” dialog also works: choose Advanced and add the header Authorization = Bearer pat_…. Refresh the data with Data → Refresh All.
let
Source = Csv.Document(
Web.Contents(
"https://api.3dprintpricing.pro/read-api/orders",
[Query = [format = "csv", per_page = "1000"],
Headers = [Authorization = "Bearer pat_ВАШ_ТОКЕН"]]
),
[Delimiter = ",", Encoding = 65001, QuoteStyle = QuoteStyle.Csv]
),
Promoted = Table.PromoteHeaders(Source, [PromoteAllScalars = true])
in
PromotedGoogle Sheets (Apps Script)
IMPORTDATA cannot send headers, so use Extensions → Apps Script and a short script that runs on a schedule.
function loadOrders() {
const res = UrlFetchApp.fetch(
"https://api.3dprintpricing.pro/read-api/orders?format=csv&per_page=1000",
{ headers: { Authorization: "Bearer pat_YOUR_TOKEN" } }
);
const rows = Utilities.parseCsv(res.getContentText().replace(/^\uFEFF/, ""));
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Orders");
sheet.clear();
sheet.getRange(1, 1, rows.length, rows[0].length).setValues(rows);
}Your own website
For a public storefront the key is not needed: the master profile JSON, the badge.svg badge and the estimate widget are open. Use a read-only token only on your server (never in browser code) and cache the response — for example /read-api/models?for_sale=true.