Все запросы требуют заголовок Authorization: Bearer <токен>
Токены хранятся в src/Presentation.ViewModels/ServerApiCredentials.cs
| Константа | Префикс | Права |
|---|---|---|
| CalibrationBearer | cal_ | Чтение и запись калибровок |
| TrainingEvidenceBearer | tek_ | Загрузка captures, records |
| TrainingEvidenceInventoryBearer | teinv_ | Чтение, листинг, summary |
| DistributionBearer | dist- | Загрузка дистрибутивов |
Флаги DB: CanUploadTrainingEvidence, CanHardDeleteTrainingEvidence, CanUploadDistributions. Превышение лимита → 429.
Возвращает полный активный профиль (включая profileJson) для серийного номера прибора.
| Путь | Описание |
|---|---|
| serial* | Серийный номер прибора (напр. 0454628) |
200: { "schemaVersion":"calibration-profile/v1", "calibrationId":"cal-...", "deviceSerial":"0454628",
"computedAt":"2026-06-18T01:44:53Z", "rmsStereoPx":0.803, "baselineMm":3.556,
"k5Passed":true, "isRecommendedActive":true, "profileJson":{...} }
404: { "errorCode":"calibration_not_found" }
Поиск калибровки по SHA заводской EEPROM прибора. Используется клиентом, когда серийник из EEPROM невалиден (например, прибор 1/11 репортит серийник "11" — номер модели, не уникальный).
Формат eepromSha: 64 hex-символа нижнего регистра, SHA-256 от строки "<block1_hex>\r\n<block2_hex>" (два 80-байтных EEPROM-блока, формат legacy_eeprom_block_pair).
Таблица соответствий: dbo.DeviceEepromKey. Текущие записи: прибор 0454628 (sha 00585a32…).
200: полный active-профиль (тот же формат что /devices/{serial}/active)
404: { "errorCode":"calibration_not_found" } — нет маппинга или нет active-калибровки
422: { "errorCode":"calibration_schema_invalid" } — eepromSha не 64 hex
Б-044 / 2026-07-01. Клиентский резолвер: если /devices/{serial}/active → 404, вычислить eepromSha и обратиться к этому эндпоинту.
Возвращает серийный номер прибора по SHA заводской EEPROM, БЕЗ требования наличия активной калибровки — в отличие от /active, отвечает 200 даже если калибровки ещё нет. Используется для онбординга нового прибора (клиент узнаёт свой серийник по хэшу EEPROM до первой калибровки).
Формат eepromSha: тот же, что у /active (64 hex нижнего регистра).
200: { "deviceSerial":"0454628", "eepromSha":"00585a32...", "createdAt":"2026-07-01T12:46:55Z" }
404: { "errorCode":"eeprom_key_not_found" } — хэш не зарегистрирован
422: { "errorCode":"calibration_schema_invalid" } — eepromSha не 64 hex
B18 / 2026-07-07.
Сохраняет соответствие SHA заводской EEPROM → серийный номер прибора (заполняет dbo.DeviceEepromKey). Используется, когда хэш ещё неизвестен серверу: пользователь вводит серийник вручную, клиент регистрирует пару, дальше /identity и /active резолвят её автоматически.
Идемпотентно: повторная регистрация того же хэша с тем же серийником → 200. С ДРУГИМ серийником → 409 (перезапись запрещена, конфликт).
| Поле тела | Описание |
|---|---|
| deviceSerial* | Серийный номер прибора (ASCII, до 250 симв.) |
| note | Опциональная заметка (до 500 симв.) |
201: { "deviceSerial":"0454628", "eepromSha":"00585a32...", "createdAt":"...", "alreadyRegistered":false }
200: { "deviceSerial":"0454628", "eepromSha":"...", "alreadyRegistered":true } — уже была та же пара
409: { "errorCode":"eeprom_key_conflict", "deviceSerial":"<существующий>" } — хэш занят ДРУГИМ серийником
422: { "errorCode":"calibration_schema_invalid" } — eepromSha не 64 hex, либо deviceSerial отсутствует/невалиден
B18 / 2026-07-07. Валидация серийника против ERP (ItemSn) НЕ выполняется — VeriDepthDB изолирована от IntekDB по Б-044.
Список всех калибровок прибора (метаданные, без profileJson). Используется клиентом для версионного резолва.
200: { "deviceSerial":"0454628", "calibrations":[
{ "calibrationId":"cal-...", "isActive":true, "uploadedAt":"...", "rmsStereoPx":0.803, "baselineMm":3.556 }
] }
| Заголовок | Значение |
|---|---|
| Content-Type* | application/json |
| X-Content-SHA256* | SHA-256 hex тела запроса |
Тело — JSON схемы calibration-profile/v1. Обязательные поля: schemaVersion, calibrationId, deviceSerial, rmsStereoPx, baselineMm, k5Passed, profileJson.
201: { "calibrationId":"cal-...", "storedAt":"...", "isActive":true }
409: { "errorCode":"calibration_already_exists" }
409: { "errorCode":"device_not_registered", "deviceSerial":"..." } — серийник не найден в реестре приборов IntekDB.ItemSn
422: { "errorCode":"calibration_schema_invalid", "details":"..." }
ItemSnID резолвится автоматически из IntekDB.dbo.ItemSn по DeviceSerial (кросс-БД, один сервер) — ручная регистрация в ItemSnCalibration не нужна, если прибор уже стоит на учёте в ERP.
Помечает калибровку удалённой (IsDeleted=1). Данные сохраняются в БД.
200: { "deleted":true }
404: { "errorCode":"calibration_not_found" }
| Заголовок | Описание |
|---|---|
| Content-Type* | image/png |
| X-Content-SHA256* | SHA-256 hex тела (64 символа) |
| X-Artifact-Uid | Стабильный UID артефакта (опц.) |
Тело — бинарный PNG. Сервер извлекает DeviceId, CalibrationRef, HardwareDeviceId из tEXt Metadata внутри PNG. Повторная загрузка идемпотентна.
201/200: { "sha256":"...", "sizeBytes":1048576, "alreadyExisted":false,
"extractedDeviceId":"0454628", "evidenceDeviceId":"0454628",
"hardwareDeviceId":"intek-1_11:vid_192a_pid_0803",
"extractedCalibrationRef":"cal-...", "artifactUid":null }
| Заголовок | Описание |
|---|---|
| Content-Type* | video/x-msvideo |
| X-Format-Version* | stereo-scan-video/v1 |
| X-Content-SHA256* | SHA-256 hex тела |
| X-Device-Id* | ID устройства (напр. 0454628) |
| X-Hardware-Device-Id | Hardware ID (опц.) |
| X-Calibration-Ref | ID калибровки (опц.) |
| X-Artifact-Uid | Стабильный UID артефакта (опц.) |
Тело — AVI-файл, стерео side-by-side (левый|правый кадр, RGB24). Метаданные из заголовков.
201/200: { "sha256":"...", "sizeBytes":123456, "alreadyExisted":false,
"formatVersion":"stereo-scan-video/v1", "sourceClass":"scan",
"evidenceDeviceId":"...", "artifactUid":"..." }
Возвращает бинарный файл (PNG или AVI) с оригинальным Content-Type.
200: <binary body>
404: { "errorCode":"capture_not_found" }
| Параметр | Тип | Описание |
|---|---|---|
| sha256* | path | SHA-256 оригинального capture (64 hex-символа) |
| engine* | query | Идентификатор движка: cre, sgbm, hitnet и т.д. Regex: ^[a-z0-9-]{1,32}$ |
| тело* | Content-Type: image/png | PNG-рендер 3D-превью от клиентского Audit3DPreviewRenderer |
Хранится в dbo.ApiBinaryBlob с scope te-preview-{engineId}. Идемпотентно (upsert по sha256+engine). Требует флаг CanUploadTrainingEvidence.
200: { "stored":true, "captureSha256":"...", "engineId":"cre", "previewSizeBytes":45678 }
400: { "errorCode":"empty_body" | "invalid_payload" | "invalid_engine" }
403: { "errorCode":"forbidden" }
| Параметр | Тип | Описание |
|---|---|---|
| sha256* | path | SHA-256 оригинального capture |
| engine* | query | Идентификатор движка (тот же, что при POST) |
200: <image/png binary> — превью от указанного движка
404: { "errorCode":"preview_not_found" } — превью ещё не загружено
400: { "errorCode":"invalid_engine" }
Для отображения в браузере без токена используйте PreviewImage.aspx?sha={sha}&engine={engineId} (admin-только).
| Заголовок | Значение |
|---|---|
| Content-Type* | application/json |
Тело — JSON схемы training-evidence/v1. Обязательные поля:
{ "schemaVersion":"training-evidence/v1", "evidenceId":"gtpkg-...",
"captureSha256":"<sha256 PNG или видео>",
"deviceId":"0454628", "sourceClass":"point_to_point",
"conditionBucket":"standard", "consent":"explicit_opt_in",
"measurementJson":{...}, "groundTruthJson":{...} }
201/200: { "evidenceId":"...", "alreadyExisted":false }
404: { "errorCode":"capture_not_found" }
422: { "errorCode":"schema_invalid", "details":"..." }
| Query-параметр | Описание | По умолч. |
|---|---|---|
| limit | Кол-во (1–500) | 100 |
| offset | Смещение | 0 |
| deviceId | Фильтр по ID устройства | — |
| sourceClass | point_to_point, scan, … | — |
| conditionBucket | Условие съёмки | — |
| trainableForOwnDeviceBucket | true/false | — |
| hasGroundTruth | true/false | — |
| captureStatus | not_found — осиротевшие (нет живого capture) | — |
200: { "totalRecords":26, "totalCaptures":569, "referencedCaptures":23, "unreferencedCaptures":546,
"byDevice":{...}, "bySourceClass":{...},
"withGroundTruth":26, "trainableForOwnDeviceBucket":22 }
⚠ Endpoint /latest возвращает только версии, у которых есть оба артефакта: windows и linux-x64.
200: { "version":"0.9.7.25", "releasedAt":"...",
"windowsUrl":"/api/distributions/v1/0.9.7.25/windows",
"linuxUrl":"/api/distributions/v1/0.9.7.25/linux-x64",
"windowsSha256":"...", "linuxSha256":"...",
"windowsSizeBytes":156429678, "linuxSizeBytes":53124200 }
404: нет версии с обоими артефактами
В отличие от /latest, не требует наличия ОБОИХ артефактов — берёт самый новый релиз, у которого есть указанная платформа. platform: windows или linux-x64. Именно этот путь использует установщик клиента (DistributionUpdateClient.cs).
200: { "version":"0.9.7.25", "platform":"windows", "downloadUrl":"...", "sha256":"...",
"sizeBytes":78750873, "filename":"...", "releasedAt":"...", "releaseNotes":"..." }
400: distribution_schema_invalid (platform не windows/linux-x64)
404: distribution_not_found (нет ни одного релиза с этой платформой)
B24.2 / 2026-07-07. Портировано с itcworld (эталонная рабочая копия).
Все релизы (не только с обоими артефактами), отсортированы по семантической версии убыв.
200: { "items": [ { "version":"...", "releasedAt":"...", "releaseNotes":"...",
"windows":{...}, "linux_x64":{...} }, ... ] }
B24.2 / 2026-07-07.
Та же структура что /latest. Версия в формате N.N.N.N.
400: distribution_schema_invalid (неверный формат версии) 404: distribution_not_found
Возвращает бинарный архив (zip / tar.gz) для указанной версии и платформы.
Требует CanUploadDistributions=1.
| Заголовок | Значение |
|---|---|
| Content-Type* | application/zip (windows) или application/x-tar (linux) |
| X-Version* | Версия, напр. 0.9.7.26 |
| X-Platform* | windows или linux-x64 |
| X-Content-SHA256* | SHA-256 hex тела |
Все ошибки: { "errorCode":"...", "message":"...", "details":"..." }
| errorCode | HTTP | Значение |
|---|---|---|
| calibration_not_found | 404 | Калибровка не найдена |
| calibration_already_exists | 409 | CalibrationID уже в базе |
| calibration_schema_invalid | 422 | Нарушение схемы calibration-profile/v1 |
| capture_not_found | 404 | Capture по SHA256 не найден |
| schema_invalid | 400/422 | Неверный формат запроса |
| payload_integrity_mismatch | 400 | SHA256 тела не совпал с X-Content-SHA256 |
| method_not_allowed | 405 | Метод не поддерживается для этого пути |
| forbidden | 403 | Ключ не имеет нужного флага |
| distribution_not_found | 404 | Дистрибутив не найден |
| server_error | 500 | Внутренняя ошибка (детали в details) |
| # | Задача | Статус |
|---|---|---|
| Ф-2 | Re-key 701 PNG (через пересылку, без нового endpoint) | Через POST /captures |
| Ф-3 | Relink 14 осиротевших records | Через re-POST /records |
| Ф-6 | Rich EndpointArray (координаты в мм) | Стоп-гейт Владельца |