Руководство по интеграции — TechCon ML Platform
Аудитория: интеграторы и внешние разработчики. Версия: 2.0.8 | Дата: 2026-06-03 Портал: docs.techcon-ml.ru
⚠️ Что важно для новой интеграции — v2.0.8 (2026-06-03)
Для STT канонический путь —
/transcribe/audio_url, аGET /result/{task_id}остаётся обязательным резервным путём даже при включённомwebhook.
POST /transcribe/textудалён из активного runtime-контракта; если текст уже готов, используйте только старый совместимый путьPOST /classify/text.POST /transcribe/audio_urlвозвращает только202 {task_id}.- Для STT старые пути
/classify/textи/classify/audio_urlсохранены только для обратной совместимости.- В теле STT-аудио-запроса используется поле
urlи вложенный объектwebhook, а неaudio_urlилиwebhook_url.- После
202первый запрос кGET /result/{task_id}делайте не раньшеestimated_wait_seconds: обычно60sпри уже запущенном worker и180s, если сервису ещё нужно поднять T4.- Если сервис всё ещё отвечает
202, продолжайте опрос не чаще60s.- Красный
GET /healthв первые минуты cold start сам по себе ещё не доказывает финальный outage, если задача принята и остаётся вqueued/processing.- Адрес
https://stt.dev.techcon-ml.ruнельзя считать обычной готовой средой без отдельной перепроверки.Почему это важно: руководство должно помогать собрать рабочую интеграцию, а не смешивать внешний контракт с внутренними эксплуатационными деталями. Что делать интегратору: строить STT-интеграцию по шаблону из раздела 6.2 и проверять спорные детали по
/stt/API/,openapi.json, live ReDoc на/docsи Swagger UI на/swagger.
1. Обзор платформы
TechCon ML Platform — это 4 независимых API-сервиса для автоматизации технической инспекции зданий. Ниже — краткая карта того, какой сервис за что отвечает и как их обычно используют вместе.
| Сервис | Назначение | Версия |
|---|---|---|
| Дефектоскопия | Классификация дефектов на фотографиях (223 класса) | v0.2.0 |
| STT (Speech-to-Text) | Транскрибация аудиозаписей по голосовым описаниям | v0.8.0 |
| Техпаспорта | Извлечение данных из сканов технических паспортов | v1.0.0 |
| Техпланы (Поиск) | Гибридный поиск по базе ~6000 технических планов | v1.0.0 |
Как сервисы используются вместе
Инспектор осматривает здание
│
├── Фотографирует дефект → Дефектоскопия API → класс дефекта + поверхность
├── Записывает голосовое описание → STT API → текстовая расшифровка
├── Сканирует техпаспорт → Техпаспорта API → структурированные данные
└── Ищет нормативы → Техпланы API → релевантные документы
Обычно данные приходят пакетами: один дефект = 1 фото (обязательно) + 0–1 аудио (опционально). Отдельный аудиофайл без соответствующего фото в этом контуре не предполагается.
2. Адреса сервисов
Production
| Сервис | URL | Основная docs UI | Дополнительная docs UI |
|---|---|---|---|
| Дефектоскопия | https://defects.techcon-ml.ru |
/docs (ReDoc) |
/swagger (Swagger UI), /redoc (совместимый ReDoc-путь) |
| STT | https://stt.techcon-ml.ru |
/docs (ReDoc) |
/swagger (Swagger UI), /redoc (совместимый ReDoc-путь) |
| Техпаспорта | https://passports.techcon-ml.ru |
/docs (Swagger UI) |
/redoc (ReDoc) |
| Техпланы | https://techplans.techcon-ml.ru |
/docs (Swagger UI) |
/redoc (ReDoc) |
Не выводите тип документации только из имени пути: для STT и defectoscopy основная человекочитаемая спецификация теперь живёт на /docs, а не на /redoc.
Тестовая среда
| Сервис | URL |
|---|---|
| Дефектоскопия | https://defects.dev.techcon-ml.ru |
| STT | https://stt.dev.techcon-ml.ru |
| Техпаспорта | https://passports.dev.techcon-ml.ru |
| Техпланы | https://techplans.techcon-ml.ru (только production) |
Перед интеграционными проверками всегда смотрите GET /health нужного сервиса.
Для https://stt.dev.techcon-ml.ru сохраняется отдельная оговорка: этот адрес нельзя считать обычной готовой средой без новой перепроверки; при последней согласованной проверке GET /health там возвращал 502 Bad Gateway.
Файл OpenAPI для импорта в Postman или Insomnia: <base_url>/openapi.json
3. Общий формат ответов
Во всех сервисах, кроме оговорённых исключений, используется формат ok/data.
Успешный ответ
{
"ok": true,
"data": { ... }
}
Ответ с ошибкой
{
"ok": false,
"error": {
"code": "UPPER_SNAKE_CASE",
"message": "Человекочитаемое описание"
}
}
Когда обёртки нет
Не используют ok/data:
- HTML-страницы
- Server-Sent Events (SSE)
- бинарные файлы (PDF, CSV)
- HTTP 204 No Content
Стандартные коды ошибок
| Код | HTTP | Описание |
|---|---|---|
VALIDATION_ERROR |
422 | Неверные входные данные |
NOT_FOUND |
404 | Ресурс не найден (task_id истёк или не существует) |
UNAUTHORIZED |
401 | Токен отсутствует или недействителен |
RATE_LIMIT_EXCEEDED |
429 | Превышено допустимое число запросов. Проверяйте Retry-After и договорённость по конкретному сервису |
INTERNAL_ERROR |
500 | Непредвиденная ошибка сервера |
SERVICE_NOT_READY |
503 | Сервис запускается или ещё не готов |
MODEL_NOT_LOADED |
503 | ML-модель не инициализирована |
REDIS_UNAVAILABLE |
503 | Очередь задач недоступна |
GPU_STARTING |
503 | GPU запускается — повторите запрос позже или дождитесь обработки уже принятой задачи |
TASK_NOT_FOUND |
404 | task_id не найден |
Каждый сервис может добавлять свои коды ошибок. Подробности смотрите в его отдельном справочнике API.
4. Аутентификация
| Сервис | Метод | Как получить токен |
|---|---|---|
| Дефектоскопия | Bearer token | DEFECTOSCOPY_BEARER_TOKENS или DEFECTOSCOPY_BEARER_TOKEN |
| STT | Bearer token | BEARER_TOKENS — основной путь, BEARER_TOKEN — только обратная совместимость |
| Техпаспорта | Bearer token или JWT | Статический: от администратора. JWT: POST /auth/token (24ч) |
| Техпланы | Bearer token | Только для /reports (admin). Основные эндпоинты публичны |
Формат заголовка
Authorization: Bearer <токен>
Публичные эндпоинты (без токена)
Во всех сервисах:
- GET /health — проверка состояния
- GET /metrics — метрики Prometheus (дефектоскопия, STT, техпаспорта — публичный; техпланы — требует Bearer)
5. Проверка готовности сервиса
У всех сервисов есть единый GET /health.
curl -sf https://<service>.techcon-ml.ru/health | jq
Ответ, когда сервис готов:
{
"ok": true,
"data": { ... }
}
Поле
dataразличается по сервисам: - Дефектоскопия:{"model_loaded": true, "gpu": {...}}- STT:{"status": "ok", "model_loaded": true, "version": "0.8.0", ...}- Техпаспорта:{"database": "ok", "workers_online": 1, "version": "1.0.0"}- Техпланы:{"status": "ok", "total_records": 6231}
Ответ, когда сервис не готов:
{
"ok": false,
"error": {
"code": "MODEL_NOT_LOADED",
"message": "Taxonomy or pipeline not initialized"
}
}
Как трактовать ответ:
- HTTP 200 + ok == true → сервис готов принимать запросы;
- HTTP 503 + ok == false → сервис ещё не готов или временно недоступен;
- поле data содержит сервисные подробности: например, version, model_loaded или счётчики.
6. Ключевые эндпоинты
6.1 Дефектоскопия
| Эндпоинт | Метод | Описание | Токен |
|---|---|---|---|
/predict |
POST | Поставить задачу классификации фото в очередь | Да |
/result/{task_id} |
GET | Получить результат классификации | Да |
/health |
GET | Состояние сервиса | Нет |
/metrics |
GET | Prometheus-метрики | Нет |
Шаг 1 — Отправить задачу:
export DEFECTOSCOPY_TOKEN='<токен из внешнего секрет-хранилища>'
curl -X POST https://defects.techcon-ml.ru/predict \
-H "Authorization: Bearer $DEFECTOSCOPY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://storage.yandexcloud.net/techconimg/zT1RP8i7vfpj",
"webhook_url": "https://integrator.example.com/hooks/defectoscopy"
}'
Ответ 202 (задача принята):
{
"ok": true,
"data": {
"task_id": "def-a1b2c3d4e5f6",
"status": "queued",
"status_url": "/result/def-a1b2c3d4e5f6",
"estimated_wait_seconds": 90
}
}
estimated_wait_seconds=90— это только ориентир для первого повторного запроса. Это не гарантированное время готовности и не таймер обратного вызова.
Шаг 2 — Повторно запросить результат:
curl https://defects.techcon-ml.ru/result/def-a1b2c3d4e5f6 \
-H "Authorization: Bearer $DEFECTOSCOPY_TOKEN"
Ответ 202 (ещё обрабатывается):
{
"ok": true,
"data": {
"task_id": "def-a1b2c3d4e5f6",
"status": "processing",
"message": "Задача обрабатывается",
"webhook": {
"configured": true,
"state": "pending",
"attempts": 0
}
}
}
Поле message предназначено для человека. Для машинной логики опирайтесь на status, HTTP-код и итоговые поля, а не на формулировку этого текста.
Ответ 200 (готово, обратный вызов доставлен):
{
"ok": true,
"data": {
"task_id": "def-a1b2c3d4e5f6",
"status": "done",
"result": { "surface": "...", "masters": [...], "defects": [...] },
"processing_time_ms": 432,
"completed_at": "1745271700",
"webhook": {
"configured": true,
"state": "delivered",
"attempts": 1,
"delivery_id": "1b00b33fbad3496eb17ab0fd800d55a7",
"last_attempt_at": "1745271700",
"delivered_at": "1745271700",
"response_status_code": 200
}
}
}
Обратный вызов у defectoscopy:
- включается полем webhook_url;
- отправляется только после done или failed;
- использует заголовки X-Techcon-Event, X-Techcon-Task-ID, X-Techcon-Delivery-ID;
- не переводит успешную задачу из done в failed;
- не имеет отдельного секрета или HMAC-подписи, в отличие от STT.
Не поднимайте в обязательный бизнес-контракт без отдельного согласования точный бюджет повторов, полное расписание задержек или все промежуточные состояния доставки.
Рекомендуемый интервал повторных запросов: первый
GET /result/{task_id}делать не раньшеestimated_wait_seconds, затем повторять опрос с паузой порядка30–60секунд на задачу. TTL результата: 24 часа. Даже при включённом обратном вызове итог нужно дочитывать черезGET /result/{task_id}.
6.2 STT (Транскрибация аудио)
Точный STT-контракт читайте в двух слоях:
- https://docs.techcon-ml.ru/stt/API/ — канонический человекочитаемый справочник на портале;
- https://stt.techcon-ml.ru/openapi.json, https://stt.techcon-ml.ru/docs и https://stt.techcon-ml.ru/swagger — рабочее описание API на стороне сервиса.
| Эндпоинт | Метод | Описание | Токен |
|---|---|---|---|
/transcribe/audio_url |
POST | Поставить задачу транскрибации аудио в очередь | Да |
/result/{task_id} |
GET | Получить статус и результат аудио-задачи | Да |
/taxonomy |
GET | Вспомогательная таксономия | Да |
/classify/text |
POST | Старый совместимый путь для уже готового текста | Да |
/health |
GET | Состояние | Нет |
Старые пути /classify/text и /classify/audio_url сохранены только для обратной совместимости. Путь /transcribe/text удалён из активного runtime-контракта.
Если текст уже получен вне STT, старый совместимый путь POST /classify/text оставляйте только как fallback для старого клиента или ручной проверки; основной production-flow для новой интеграции всё равно строится вокруг аудио-ветки ниже.
Шаг 1 — Отправить аудио на обработку:
curl -X POST https://stt.techcon-ml.ru/transcribe/audio_url \
-H "Authorization: Bearer $STT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://storage.yandexcloud.net/bucket/audio.wav",
"webhook": {
"url": "https://integrator.example/api/stt-callback"
}
}'
Важно для интегратора:
- в теле запроса используется поле url, а не audio_url;
- блок webhook опционален и использует вложенный объект с полями url и secret;
- estimated_wait_seconds — это ориентир до первого полезного опроса, а не гарантия готовности;
- webhook дополняет опрос статуса, но не заменяет его.
Ответ 202 (задача принята):
{
"ok": true,
"data": {
"task_id": "stt-a1b2c3d4e5f6",
"status": "queued",
"status_url": "/result/stt-a1b2c3d4e5f6",
"estimated_wait_seconds": 180,
"webhook": {
"configured": true,
"status": "pending"
}
}
}
Шаг 2 — Повторно запрашивать статус:
Рекомендуемая тактика опроса для STT:
- первый запрос к GET /result/{task_id} делать не раньше значения estimated_wait_seconds;
- если сервис всё ещё отвечает 202, продолжать опрос не чаще 60s;
- webhook не заменяет опрос статуса;
- не считать первые минуты ожидания ошибкой слишком рано, если сервису пришлось поднимать T4 перед обработкой;
- до выхода за estimated_wait_seconds и без других признаков поломки не трактовать один только красный /health как доказательство окончательного отказа;
- Конечный результат хранится 24 часа после done или failed.
curl https://stt.techcon-ml.ru/result/stt-a1b2c3d4e5f6 \
-H "Authorization: Bearer $STT_TOKEN"
Ответ 202 (ещё обрабатывается):
{
"ok": true,
"data": {
"task_id": "stt-a1b2c3d4e5f6",
"status": "processing",
"webhook": {
"configured": true,
"status": "pending"
}
}
}
Ответ 200 (готово):
{
"ok": true,
"data": {
"task_id": "stt-a1b2c3d4e5f6",
"status": "done",
"result": { "transcription": "трещина в несущей стене", "service": "stt" },
"processing_time_ms": 334,
"webhook": {
"configured": true,
"status": "delivered",
"delivery_id": "stt-a1b2c3d4e5f6:done:1234567890"
}
}
}
Если задача завершилась ошибкой, сервис возвращает 200 и статус failed.
При включённом webhook считайте delivery_id ключом дедупликации.
Если для новой интеграции нужна точная матрица кодов ошибок, терминальных статусов и ограничений STT, используйте страницу /stt/API/ как основной человекочитаемый справочник.
6.3 Техпаспорта
| Эндпоинт | Метод | Описание | Токен |
|---|---|---|---|
/upload |
POST | Загрузка скана паспорта | Да |
/api/tasks |
GET | Список задач обработки | Да |
/api/task/{id}/status |
GET | Статус задачи | Да |
/api/task/{id}/result |
GET | Результат извлечения | Да |
/api/v1/create-pdf |
POST | Генерация PDF из данных | Да |
/health |
GET | Состояние (включая workers) | Нет |
Полный цикл:
import httpx
client = httpx.Client(
base_url="https://passports.techcon-ml.ru",
headers={"Authorization": f"Bearer {TOKEN}"}
)
# 1. Загрузить скан
r = client.post("/upload", files={"file": open("scan.pdf", "rb")})
task_id = r.json()["data"]["task_id"]
# 2. Ожидать завершения
import time
while True:
r = client.get(f"/api/task/{task_id}/status")
status = r.json()["data"]["status"]
if status in ("completed", "failed"):
break
time.sleep(2)
# 3. Получить результат
r = client.get(f"/api/task/{task_id}/result")
extracted_data = r.json()["data"]
6.4 Техпланы (Поиск)
| Эндпоинт | Метод | Описание | Токен |
|---|---|---|---|
/search |
POST | Гибридный поиск по техпланам | Нет |
/detail/{uid} |
GET | Детали документа | Нет |
/export |
GET | Экспорт результатов | Нет |
/health |
GET | Состояние | Нет |
Запрос /search:
curl -X POST https://techplans.techcon-ml.ru/search \
-H "Content-Type: application/json" \
-d '{"query": "нормативы по трещинам в стенах", "limit": 10}'
7. Сквозной пример интеграции
Полный цикл обработки одного дефекта (v2.0, асинхронные фото и аудио):
import httpx
import time
# --- Конфигурация ---
DEFECTO_URL = "https://defects.techcon-ml.ru"
STT_URL = "https://stt.techcon-ml.ru"
TECHPLANS_URL = "https://techplans.techcon-ml.ru"
TOKEN = "ваш-токен"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
POLL_INTERVAL = 5 # секунд
POLL_TIMEOUT = 300 # максимум 5 минут ожидания
def poll_result(client: httpx.Client, url: str, task_id: str) -> dict:
"""Опрос до получения результата."""
deadline = time.time() + POLL_TIMEOUT
while time.time() < deadline:
r = client.get(f"{url}/result/{task_id}", headers=HEADERS)
data = r.json()["data"]
if data["status"] == "done":
return data["result"]
if data["status"] == "failed":
raise RuntimeError(f"Задача завершилась ошибкой: {data.get('error')}")
time.sleep(POLL_INTERVAL)
raise TimeoutError(f"Задача {task_id} не завершилась за {POLL_TIMEOUT}с")
with httpx.Client() as client:
# --- 1. Отправить фото дефекта в очередь ---
r = client.post(
f"{DEFECTO_URL}/predict",
json={"image_url": "https://storage.example.com/photo_001.jpg"},
headers=HEADERS,
)
assert r.status_code == 202
defecto_task_id = r.json()["data"]["task_id"]
# --- 2. Отправить аудио в очередь, если оно есть ---
r = client.post(
f"{STT_URL}/transcribe/audio_url",
json={"url": "https://storage.example.com/audio_001.wav"},
headers=HEADERS,
)
assert r.status_code == 202
stt_task_id = r.json()["data"]["task_id"]
# --- 3. Дождаться результатов ---
# Для простоты пример опрашивает задачи по очереди.
defect = poll_result(client, DEFECTO_URL, defecto_task_id)
audio = poll_result(client, STT_URL, stt_task_id)
print(f"Дефект: {defect['surface']} / {defect['defects']}")
print(f"Транскрипция: {audio['transcription']}")
# --- 4. Найти подходящие нормативы ---
r = client.post(
f"{TECHPLANS_URL}/search",
json={"query": f"{defect.get('defects', [''])[0]}", "limit": 5},
)
results = r.json()["data"]
print(f"Найдено нормативов: {len(results)}")
8. Техническая диагностика
Все сервисы отдают метрики в формате Prometheus:
curl -sf https://<service>.techcon-ml.ru/metrics | head -10
Стандартные метрики:
- http_requests_total — количество запросов по handler / method / status
- http_request_duration_seconds — длительность запросов (histogram)
- python_gc_* — метрики сборщика мусора
Панели Grafana: grafana.techcon-ml.ru Проверка доступности: gatus.techcon-ml.ru
9. Ограничения и рекомендации
Ограничения по числу запросов
| Сервис | Ограничение |
|---|---|
| Дефектоскопия | Проверяйте документацию сервиса и Retry-After |
| STT | Значение зависит от среды; проверяйте Retry-After и локальный контракт сервиса |
| Техпаспорта | Проверяйте документацию сервиса |
| Техпланы | Для основных путей ограничение не зафиксировано в этом руководстве |
Рекомендации интегратору
- Ставьте таймауты: 30с для асинхронной постановки задач, 10с для
/health - Проверяйте поле
ok: не полагайтесь только на HTTP-код - Повторяйте запрос при 503: сервис может перезапускаться
- Используйте пакетную обработку там, где она есть: STT
/classify/batch— до 100 элементов за запрос - Проверяйте готовность сервиса перед нагрузкой:
GET /health→ok == true
Ожидаемый профиль нагрузки
- До 10 000 фото + аудио за партию (50 домов × 200 дефектов)
- Данные поступают пакетами, а не в реальном времени
- Задержка в часы допустима
10. Детальные справочники
Полные справочники API каждого сервиса (все эндпоинты, параметры, примеры ответов):
- Дефектоскопия — Справочник API
- STT — Справочник API
- Техпаспорта — Справочник API
- Техпланы — Справочник API
11. Контакты
| Вопрос | Куда обращаться |
|---|---|
| API интеграция | techcon_hub (этот документ) |
| Инфраструктура | techcon_infra_yac |
| Мониторинг | techcon_infra_monitoring |
| Баги в конкретном сервисе | GitHub Issues соответствующего репозитория |
Документ обновляется при изменении API сервисов. Актуальная версия: docs.techcon-ml.ru