Как это устроено

3DP остаётся системой учёта заказов, Home Assistant — системой управления фермой. Заказ имеет неизменяемый идентификатор (id, UUID) с момента создания и до удаления — на него можно смело завязывать QR-метку заказа: даже если вы поменяете количество, цену, клиента или материал, идентификатор не изменится.

3DP  ──REST + webhook──►  Home Assistant  ──Klipper/Moonraker──►  принтер
 ▲                                                                    │
 └──────────────── PUT /print-jobs/{id} (статус) ◄──────────────────┘

Назначение конкретного принтера/катушки (например, через Spoolman) — логика Home Assistant, 3DP в этом не участвует. 3DP лишь отдаёт данные заказа и принимает статус обратно.

Авторизация

Персональный токен (PAT) создаётся в Настройки → Интеграции → Разработчикам → Токены доступа. Передаётся в каждом запросе заголовком:

Authorization: Bearer pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Токен даёт полный доступ ко всем данным аккаунта от вашего имени, без ограничения прав только заказами — то же, чем пользуется плагин слайсера. Заведите для Home Assistant отдельный токен (не переиспользуйте личный) — так его можно отозвать в любой момент, не трогая остальные интеграции.

Эндпоинты заказов

GET/print-jobs

Список заказов

Постраничный список заказов аккаунта, отсортированный по дате создания.

{
  "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
}

В реальном ответе полей больше (себестоимость, скидки, клиент и т.п.) — здесь показаны только те, что нужны для интеграции с HA. Полный набор — как в веб-интерфейсе заказа.

GET/print-jobs/{id}

Один заказ

Та же структура, что и элемент списка выше, для конкретного id.

GET /print-jobs/b6b6c8b0-... → 200
PUT/print-jobs/{id}

Обновить статус (или другие поля)

Присылайте только те поля, которые меняете — остальные останутся как есть.

PUT /print-jobs/b6b6c8b0-...
Content-Type: application/json

{ "workflow_status": "assigned" }

Значение workflow_status, которого нет в таблице ниже (опечатка, устаревшее имя), молча откатит заказ в статус «Согласование» — сервер не вернёт ошибку. Сверяйтесь со списком статусов при отправке.

Статусы заказа

ЗначениеНазваниеКогда выставлять
negotiationСогласованиеЗаказ создан, условия ещё обсуждаются
confirmedПодтверждёнКлиент подтвердил, готов к печати
assignedНазначен принтерHA закрепил конкретный принтер/катушку за заказом
printingПечатьПечать идёт на принтере
print_errorОшибка печатиKlipper/Moonraker сообщил об ошибке печати
deliveryВ доставкеПечать готова, едет к клиенту
doneВыполненЗаказ выполнен
cancelledОтменёнЗаказ отменён
closedЗакрытАрхивный статус, скрыт из основного списка

Настройка webhook

В Настройки → Интеграции → Разработчикам → Webhook укажите URL приёмника в Home Assistant (например, адрес вебхука /api/webhook/…), включите подписку и сохраните — 3DP покажет секрет один раз, скопируйте его сразу. Кнопка «Отправить тестовое событие» шлёт синтетическое событие webhook.test прямо сейчас, не дожидаясь реального заказа — удобно проверить, что HA получает и корректно проверяет подпись.

События order.created / order.status_changed

3DP отправляет POST с JSON-телом на ваш URL при создании заказа и при каждой смене workflow_status. Доставка — best-effort (без повторных попыток при ошибке в MVP), поэтому не полагайтесь только на webhook — для сверки используйте GET /print-jobs.

POST <ваш URL>
Content-Type: application/json
X-3DP-Event: order.status_changed
X-3DP-Signature: sha256=<hex-подпись тела запроса>

{
  "event": "order.status_changed",
  "occurred_at": "2026-08-27T18:32:10.000Z",
  "data": {
    "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": "assigned",
    "printer_id": null,
    "printer_name": null
  }
}

Проверка подписи (псевдокод)

signature_header = "sha256=" + hex(HMAC_SHA256(webhook_secret, raw_request_body))
if signature_header != request.headers["X-3DP-Signature"]:
    reject()  # тело подделано или секрет не совпадает

Пример сценария печати

Сценарий, под который спроектирован этот API (QR-код заказа хранит только его id, вся остальная информация подтягивается из 3DP на лету):

1. На заказ #1258 в 3DP печатается QR со значением ORDER-<id>.
2. HA сканирует QR → GET /print-jobs/{id} → получает материал, цвет, вес, срок.
3. HA сканирует QR принтера и катушки (Spoolman) → сверяет материал/остаток.
4. Печать назначена   → PUT /print-jobs/{id} {"workflow_status": "assigned"}
5. Печать начата      → PUT /print-jobs/{id} {"workflow_status": "printing"}
6. Печать завершена   → PUT /print-jobs/{id} {"workflow_status": "done"}
   (или "print_error" / "cancelled", если печать сорвалась/отменена)
7. Канбан в 3DP сам переезжает в нужную колонку — ничего дополнительно
   вызывать не нужно.

Важные нюансы и ограничения

  • Неизвестное значение workflow_status тихо откатывает заказ в «Согласование» — см. предупреждение в разделе «Эндпоинты заказов».
  • Webhook — best-effort, без автоматических повторов при недоступности вашего сервера. Держите HA доступным на момент событий или сверяйтесь через REST API.
  • Назначение принтера на конкретный заказ 3DP не проверяет само (нет справочника «какой принтер какой материал печатает») — эта логика целиком на стороне HA.
Вопросы по интеграции — через обычную поддержку 3DP.Написать в поддержку