Дефектоскопия — справочник API
Назначение сервиса
Сервис принимает изображение, ставит задачу в очередь и позже возвращает результат классификации.
Для новой интеграции используйте:
- POST /predict — чтобы создать задачу;
- GET /result/{task_id} — чтобы получить статус и итог;
- webhook_url — только как дополнительный обратный вызов, а не как замену повторных запросов.
Базовые адреса
| Среда | URL | Когда использовать |
|---|---|---|
| Промышленная | https://defects.techcon-ml.ru |
основной адрес для интеграции |
| Тестовая | https://defects.dev.techcon-ml.ru |
отдельные тесты среды |
| Локальная | http://localhost:8000 |
локальная разработка |
OpenAPI JSON: <base_url>/openapi.json
Основная ReDoc-поверхность: <base_url>/docs
Вторичная Swagger UI-поверхность: <base_url>/swagger
Совместимый дополнительный ReDoc-путь: <base_url>/redoc
Иерархия источников истины
Если нужен быстрый рабочий сценарий, используйте эту страницу.
Если нужен точный состав полей и схем, сверяйтесь в таком порядке:
1. рабочее поведение промышленного сервиса;
2. openapi.json, live ReDoc на /docs, Swagger UI на /swagger и совместимый ReDoc-путь /redoc этого сервиса;
3. эта страница;
4. общее руководство по интеграции.
Этот портал публикует производную копию принятого сервисного контракта. Если текст на портале расходится с тем, что сейчас отвечает production или показывает live /docs / /swagger, ориентируйтесь на live сервис.
Практическая оговорка: ReDoc-поверхности /docs и /redoc описывают JSON-контракт сервиса, а публичный путь /metrics остаётся отдельным служебным endpoint для Prometheus и может не отображаться в OpenAPI.
Коротко для интегратора
POST /predictсразу возвращает202 Acceptedиtask_id.GET /result/{task_id}— основной способ получить состояние и итог задачи.webhook_urlдобавляет необязательный обратный вызов только после конечного состояния.- Даже при наличии обратного вызова повторные запросы через
GET /result/{task_id}остаются обязательным резервным способом дочитать результат. estimated_wait_seconds=90— только ориентир для первого повторного запроса, а не обещание времени готовности.- После первого ожидания повторяйте
GET /result/{task_id}с паузой порядка30–60секунд на задачу, а не каждые2–5секунд. - Сервис не обещает queue position, точный ETA готовности результата или момент старта GPU.
Аутентификация
Заголовок:
Authorization: Bearer <токен>
Режимы:
- DEFECTOSCOPY_BEARER_TOKENS — основной вариант, список токенов через запятую;
- DEFECTOSCOPY_BEARER_TOKEN — совместимый одиночный токен.
Если обе переменные пусты, авторизация отключена.
Матрица доступа
| Эндпоинт | Метод | Нужен токен |
|---|---|---|
/health |
GET | Нет |
/classes/defects |
GET | Да |
/classes/surfaces |
GET | Да |
/predict |
POST | Да |
/result/{task_id} |
GET | Да |
/metrics |
GET | Нет |
/docs, /swagger, /redoc, /openapi.json |
GET | Нет |
Карта эндпоинтов
| Метод | Путь | Назначение |
|---|---|---|
GET |
/health |
Проверка готовности сервиса |
GET |
/classes/defects |
Список классов дефектов |
GET |
/classes/surfaces |
Список классов поверхностей |
POST |
/predict |
Постановка задачи на классификацию |
GET |
/result/{task_id} |
Статус и итог задачи |
GET |
/metrics |
Метрики Prometheus |
GET /health
Публичная проверка состояния.
Успех 200:
{
"ok": true,
"data": {
"model_loaded": true,
"worker_id": "tc-gpu-t4-01",
"model_version": "v10",
"gpu": {
"name": "Tesla T4",
"vram_used_mb": 1234,
"vram_total_mb": 15360
}
}
}
Если модель ещё не готова:
- HTTP 503
- error.code = "MODEL_NOT_READY"
GET /classes/defects
Возвращает плоский список названий дефектов из текущей модели.
Пример ответа 200:
{
"ok": true,
"data": ["царапина", "трещина"]
}
GET /classes/surfaces
Возвращает список допустимых поверхностей.
Пример ответа 200:
{
"ok": true,
"data": ["металл", "бетон"]
}
POST /predict
Ставит задачу на классификацию изображения.
Ограничения входа
| Поле | Правило |
|---|---|
image_url |
только https:// |
хост image_url |
storage.yandexcloud.net или storage.yc.yandex.net |
priority |
realtime или batch |
webhook_url |
https://; http:// допустим только для localhost / 127.0.0.1 / ::1 |
Тело запроса
{
"image_url": "https://storage.yandexcloud.net/techconimg/zT1RP8i7vfpj",
"priority": "batch",
"webhook_url": "https://integrator.example.com/hooks/defectoscopy"
}
Успешный ответ 202 Accepted
{
"ok": true,
"data": {
"task_id": "def-7a2d8f5d0f31",
"status": "queued",
"status_url": "/result/def-7a2d8f5d0f31",
"estimated_wait_seconds": 90
}
}
Что означает estimated_wait_seconds
- это ориентир для первого повторного запроса;
- это не обещание времени полного завершения;
- это не таймер обратного вызова;
- после первого опроса безопасная рабочая пауза обычно остаётся в диапазоне
30–60секунд на задачу.
Возможные ошибки
401 UNAUTHORIZED422 VALIDATION_ERROR429 RATE_LIMIT_EXCEEDED503 QUEUE_UNAVAILABLE
GET /result/{task_id}
Основной путь для чтения состояния и итога задачи.
Состояния задачи
data.status |
HTTP | Значение |
|---|---|---|
queued |
202 |
задача принята и ждёт обработки |
processing |
202 |
задача обрабатывается |
done |
200 |
классификация завершена успешно |
failed |
200 |
обработка завершилась ошибкой |
Ответ 202 Accepted
{
"ok": true,
"data": {
"task_id": "def-7a2d8f5d0f31",
"status": "processing",
"message": "Задача обрабатывается",
"webhook": {
"configured": true,
"state": "pending",
"attempts": 0
}
}
}
Поле message предназначено для человека. Для логики интеграции и повторных запросов опирайтесь на data.status, HTTP-код и наличие итоговых полей.
Ответ 200 OK для done
{
"ok": true,
"data": {
"task_id": "def-7a2d8f5d0f31",
"status": "done",
"result": {
"surface": "металл",
"masters": [
{"name": "механические", "conf": 0.82}
],
"defects": [
{"name": "царапина", "conf": 0.75}
]
},
"processing_time_ms": 1234,
"completed_at": "1745271700",
"webhook": {
"configured": true,
"state": "delivered",
"attempts": 1,
"delivery_id": "1b00b33fbad3496eb17ab0fd800d55a7",
"last_attempt_at": "1745271700",
"delivered_at": "1745271700",
"response_status_code": 200
}
}
}
Ответ 200 OK для failed
{
"ok": true,
"data": {
"task_id": "def-7a2d8f5d0f31",
"status": "failed",
"error": "Не удалось обработать изображение"
}
}
Блок data.webhook
Если задача создавалась с webhook_url, ответ на повторный запрос может содержать блок data.webhook.
Что можно считать активной опорой для интеграции:
- блок появляется только у задач с webhook_url;
- во время ожидания он может показывать state=pending;
- после успешной доставки он может показывать state=delivered, delivery_id и response_status_code.
Что не нужно поднимать в обязательную бизнес-логику без отдельного согласования:
- полный перечень возможных значений state;
- точное число повторов и интервалы между ними;
- служебные поля, которые не нужны для чтения итогового результата.
Как делать повторные запросы
- первый
GET /result/{task_id}делайте не раньше значенияestimated_wait_seconds; - пока задача в
queuedилиprocessing, повторяйтеGET /result/{task_id}с паузой порядка30–60секунд на задачу; - если сервис только что поднялся или нагрузка выросла, увеличивайте паузу, а не частоту повторов;
- не прекращайте повторные запросы только потому, что обратный вызов уже пришёл;
- прекращайте повторные запросы после итогового ответа
done|failedили после404 TASK_NOT_FOUND, если окно хранения уже закончилось.
Обратный вызов через webhook_url
Что обещает сервис
- обратный вызов включается только для задач, созданных с
webhook_url; - обратный вызов отправляется только после записи итогового результата;
- обратный вызов использует заголовки
X-Techcon-Event,X-Techcon-Task-ID,X-Techcon-Delivery-ID; - тело обратного вызова повторяет итоговый формат
GET /result/{task_id}; - повторные запросы остаются каноническим способом дочитать итог независимо от состояния обратного вызова.
Заголовки обратного вызова
| Заголовок | Значение |
|---|---|
Content-Type |
application/json |
X-Techcon-Event |
defectoscopy.result.terminal |
X-Techcon-Task-ID |
исходный task_id |
X-Techcon-Delivery-ID |
идентификатор одной доставки |
Тело обратного вызова
Тело совпадает с итоговым ответом GET /result/{task_id}:
- для done содержит result, processing_time_ms, completed_at;
- для failed содержит error.
Тексты в message и error человекочитаемы. Для машинной логики интеграции опирайтесь на status, HTTP-код и error.code, а не на формулировку этих полей.
Ограничения и ошибки
Подтверждённые ограничения
| Параметр | Значение |
|---|---|
| TTL результата | 86400 секунд |
estimated_wait_seconds |
90 |
| Лимит запросов | RATE_LIMIT_PER_MINUTE, по умолчанию 1000 |
| Redis | обязателен для /predict и /result/{task_id} |
Коды ошибок
| HTTP | Код | Где | Значение |
|---|---|---|---|
| 401 | UNAUTHORIZED |
защищённые эндпоинты | токен отсутствует или неверен |
| 404 | TASK_NOT_FOUND |
/result/{task_id} |
task_id неизвестен или результат уже удалён по TTL |
| 422 | VALIDATION_ERROR |
/predict |
неверные параметры запроса |
| 429 | RATE_LIMIT_EXCEEDED |
/predict, /result/{task_id} |
превышен лимит запросов |
| 503 | QUEUE_UNAVAILABLE |
/predict, /result/{task_id} |
очередь недоступна |
| 503 | MODEL_NOT_READY |
/health, /classes/* |
модель ещё не загружена |
| 500 | INTERNAL_ERROR |
глобально | внутренняя ошибка |
Что сверять через live /docs
Через ReDoc на /docs удобно проверять:
- полный список эндпоинтов;
- схемы запросов и ответов;
- точные названия полей;
- runtime-примеры для текущего контракта.
Для интегратора эта страница остаётся более удобным кратким объяснением сценария, а live ReDoc на /docs — точной спецификацией полей и схем.