AdolfReputationBack — API Reference
Версия: 1.2.50 Base URL:
https://your-server.com(dev:http://localhost:8000) Swagger UI:{BASE_URL}/docs
Содержание
- Health
- Reviews — Чтение
- Reviews — Генерация ответов
- Reviews — Модерация
- Reviews — Публикация
- Reviews — История
- Polling (сбор отзывов)
- Statistics (аналитика)
- Settings (настройки)
- Prompt Management (промт генерации)
- Автоматические процессы (Scheduler)
- Схема БД
- Пайплайн обработки
- Миграции
1. Health
GET /
Информация о сервисе.
Ответ:
{
"service": "AdolfReputationBack",
"version": "1.2.50",
"docs": "/docs"
}GET /health
Проверка соединения с БД.
Ответ:
{
"status": "ok",
"db": "connected"
}GET /worker/status
Статус worker'а авто-генерации. Проверяет последний запуск по auto_process_log.
Ответ:
{
"status": "healthy",
"last_run": "2026-03-25T12:00:00",
"age_minutes": 4.2,
"last_action": "auto_generate:success"
}| Поле | Тип | Описание |
|---|---|---|
status | string | never_run / healthy / stale (stale если > 15 мин) |
last_run | datetime? | ISO-дата последнего запуска (null если не запускался) |
age_minutes | float | Минут с последнего запуска |
last_action | string | Тип последней операции |
2. Reviews — Чтение
GET /api/v1/reviews
Список отзывов/вопросов с фильтрацией и пагинацией.
Query-параметры:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
marketplace | string | — | wildberries, ozon, yandex_market |
status | string | — | new, analyzing, pending_review, approved, publishing, published, answered, skipped, escalated, error, manual_required |
item_type | string | — | review, question |
sort_by | string | created_at | Поле сортировки: created_at, rating, wb_created_at |
order | string | desc | Порядок: asc, desc |
rating | int | — | Фильтр по оценке (1–5) |
search | string | — | Поиск по тексту, имени клиента, плюсам, минусам, артикулу (ILIKE) |
date_from | date | — | Начало периода (YYYY-MM-DD), фильтр по wb_created_at |
date_to | date | — | Конец периода (YYYY-MM-DD), фильтр по wb_created_at |
page | int | 1 | Номер страницы (≥ 1) |
page_size | int | 20 | Записей на странице (1–100) |
Ответ: ItemListResponse
{
"items": [ItemResponse],
"total": 150,
"page": 1,
"page_size": 20
}GET /api/v1/reviews/{item_id}
Детали одного отзыва/вопроса.
Ответ: ItemResponse
{
"id": 1,
"wb_id": "12345678",
"item_type": "review",
"marketplace": "wildberries",
"client_name": "Анна",
"client_text": "Отличное платье, хорошо сидит!",
"rating": 5,
"status": "pending_review",
"product_id": 987654,
"vendor_code": "ART-12345",
"pros": "Качество ткани, посадка",
"cons": null,
"wb_created_at": "2026-03-10T12:00:00",
"created_at": "2026-03-10T13:05:00",
"is_viewed": false,
"response": {
"id": 1,
"ai_variants": [
{
"text": "Добрый день, Анна! Благодарим...",
"classification": { "sentiment": "positive", "tags": ["качество"], "scenario": "five_stars" },
"generated_at": "2026-03-10T13:06:00",
"generation_id": "uuid",
"draft_id": "uuid"
}
],
"final_text": null,
"status": "draft",
"manager_notes": null,
"generated_at": "2026-03-10T13:06:00",
"published_at": null,
"wb_error": null,
"marketplace": "wildberries",
"source": "ai"
}
}Поля ItemResponse:
| Поле | Тип | Описание |
|---|---|---|
id | int | Внутренний ID |
wb_id | string | ID на маркетплейсе |
item_type | string | review / question |
marketplace | string | wildberries / ozon / yandex_market |
client_name | string? | Имя покупателя |
client_text | string? | Текст отзыва/вопроса |
rating | int? | Оценка 1–5 (null для вопросов) |
status | string | Текущий статус обработки |
product_id | int? | ID товара на маркетплейсе |
vendor_code | string? | Артикул продавца |
pros | string? | Достоинства |
cons | string? | Недостатки |
wb_created_at | datetime? | Дата создания на маркетплейсе |
created_at | datetime? | Дата загрузки в систему |
is_viewed | bool? | Просмотрен менеджером |
response | ResponseInfo? | Вложенный объект с ответом |
Поля ResponseInfo:
| Поле | Тип | Описание |
|---|---|---|
id | int | ID ответа |
ai_variants | list? | Массив сгенерированных вариантов (макс. 5) |
final_text | string? | Одобренный текст |
status | string? | draft / approved / published / failed |
manager_notes | string? | Заметки менеджера |
generated_at | datetime? | Дата первой генерации |
published_at | datetime? | Дата публикации |
wb_error | string? | Ошибка от маркетплейса |
marketplace | string? | Маркетплейс |
source | string? | ai / manager |
3. Reviews — Генерация ответов
POST /api/v1/reviews/{item_id}/generate
Классификация отзыва + генерация черновика.
Тело запроса (необязательно):
{
"instructions": "Упомяни скидку 20% на следующий заказ"
}Что происходит:
- Статус →
analyzing - Создаётся
ReputationGeneration - Отзыв классифицируется → sentiment, tags, scenario
- Генерируется ответ (50–700 символов, до 3 попыток с валидацией)
- Создаётся
ReputationDraft - Статус →
pending_review
Правила валидации:
| Правило | Условие |
|---|---|
| Длина | 50–700 символов |
| Запрещённые слова | конкуренты, сторонние сайты |
| Извинение для негатива | При rating ≤ 3 обязательно: «сожалеем» / «извин» / «жаль» |
| Чужой маркетплейс | Нельзя упоминать другие площадки |
Ответ: GenerateResponse
{
"item_id": 1,
"generation_id": "uuid",
"draft_id": "uuid",
"draft_text": "Добрый день, Анна! Благодарим за тёплый отзыв...",
"ai_variants": [...]
}POST /api/v1/reviews/{item_id}/regenerate
Генерация нового варианта. Максимум 5 вариантов на один отзыв.
Тело запроса (обязательно):
{
"instructions": "Сделай ответ короче"
}Предусловия: сначала вызвать /generate, количество черновиков < 5.
Ошибки: 400 — лимит превышен или нет базового ответа.
POST /api/v1/reviews/bulk-regenerate
Массовая перегенерация для всех неопубликованных items.
Query-параметры: item_type, marketplace (необязательны).
Ответ:
{
"updated": 12,
"errors": 1,
"total": 13,
"message": "Перегенерировано 12 из 13"
}4. Reviews — Модерация
POST /api/v1/reviews/{item_id}/approve
Одобрение последнего черновика.
Тело запроса (необязательно):
{
"final_text": "Мой отредактированный текст"
}Приоритет текста: final_text из тела → текст черновика → последний вариант ai_variants.
Результат: черновик, ответ и отзыв → approved. Ответ: ItemResponse.
POST /api/v1/reviews/bulk-approve
Массовое одобрение.
Тело запроса:
{
"item_ids": [1, 2, 3]
}Ответ:
{
"approved_count": 3,
"item_ids": [1, 2, 3]
}POST /api/v1/reviews/{item_id}/skip
Пропустить отзыв. Статус → skipped. Ответ: ItemResponse.
POST /api/v1/reviews/{item_id}/escalate
Эскалация. Статус → escalated. Ответ: ItemResponse.
5. Reviews — Публикация
POST /api/v1/reviews/{item_id}/publish
Отправка одобренного ответа на маркетплейс.
Предусловия: response.status — approved или failed.
Маркетплейсы и API:
| Маркетплейс | Отзывы | Вопросы |
|---|---|---|
| Wildberries | POST /api/v1/feedbacks/answer | PATCH /api/v1/questions |
| Яндекс Маркет | POST /v2/businesses/{id}/goods-feedback/comments | POST /v1/businesses/{id}/goods-questions/answers |
| Ozon | POST /v1/review/comment/create | POST /v1/question/answer/create |
Ответ: PublishResponse
{
"item_id": 1,
"publication_id": "uuid",
"status": "published",
"error": null
}status | Описание |
|---|---|
published | Успешно, отзыв → answered |
failed | Ошибка, отзыв → error (автоповтор раз в час) |
6. Reviews — История
GET /api/v1/reviews/{item_id}/history
Полная история: генерации, черновики, публикации.
Ответ:
{
"item_id": 1,
"generations": [
{
"id": "uuid",
"status": "completed",
"analysis_result": { "sentiment": "positive", "scenario": "five_stars" },
"created_at": "2026-03-10T13:05:30",
"completed_at": "2026-03-10T13:05:35"
}
],
"drafts": [
{
"id": "uuid",
"generation_id": "uuid",
"response_text": "Добрый день, Анна!...",
"is_valid": true,
"status": "approved",
"created_at": "2026-03-10T13:05:36"
}
],
"publications": [
{
"id": "uuid",
"draft_id": "uuid",
"published_text": "Добрый день, Анна!...",
"status": "success",
"published_at": "2026-03-10T14:00:00"
}
]
}7. Polling (сбор отзывов)
POST /api/v1/polling/{marketplace}/trigger
Ручной запуск сбора. marketplace: wildberries, ozon, yandex_market.
Query: item_type (review / question). Если не указан — оба типа.
Ответ:
{
"results": [
{
"status": "success",
"marketplace": "wildberries",
"item_type": "review",
"fetched": 45,
"new": 12,
"duplicates": 33
}
]
}Особенности: дедупликация по (marketplace, wb_id). Circuit breaker: 5 ошибок → пауза 60 сек.
GET /api/v1/polling/status
Состояние поллинга по всем маркетплейсам.
Ответ:
{
"states": [
{
"marketplace": "wildberries",
"item_type": "review",
"last_poll_time": "2026-03-10T13:00:00+00:00",
"last_poll_status": "success",
"items_fetched_total": 1500,
"consecutive_errors": 0,
"circuit_breaker_open": false
}
]
}8. Statistics (аналитика)
GET /api/v1/stats
Ежедневная статистика + счётчики неотвеченных + агрегированная сводка.
Query-параметры:
| Параметр | Тип | Описание |
|---|---|---|
date_from | date | YYYY-MM-DD, фильтр по created_at |
date_to | date | YYYY-MM-DD, фильтр по created_at |
marketplace | string | wildberries / ozon / yandex_market |
Ответ: StatsResponse
{
"stats": [StatsItem],
"total": 30,
"counters": {
"total_unanswered": 42,
"by_marketplace": [
{
"marketplace": "wildberries",
"new_reviews": 12,
"new_questions": 5,
"pending_review": 8
}
]
},
"summary": { ... }
}Поля StatsItem:
| Поле | Тип | Описание |
|---|---|---|
date | date | Дата |
marketplace | string | Маркетплейс |
total_items | int | Всего отзывов + вопросов |
reviews_count | int | Только отзывы |
questions_count | int | Только вопросы |
positive_count | int | rating ≥ 4 |
neutral_count | int | rating = 3 |
negative_count | int | rating ≤ 2 |
avg_rating | float? | Средняя оценка |
published_count | int | Опубликовано (всего) |
our_published_count | int | Опубликовано нами |
seller_published_count | int | Опубликовано продавцом |
our_avg_response_time_min | int? | Среднее время ответа — наши |
GET /api/v1/stats/summary
Агрегированные метрики для дашборда.
Query: marketplace (необязательно).
Ответ: DashboardSummary
{
"total_items": 5000,
"avg_rating": 4.3,
"positive_count": 3500,
"published_count": 4200,
"our_published_count": 3000,
"our_avg_response_time_min": 30,
"marketplaces": [
{
"marketplace": "wildberries",
"total": 3000,
"avg_rating": 4.5,
"response_pct": 85,
"our_response_pct": 60
}
]
}POST /api/v1/stats/recompute
Пересчёт аналитики за последние N дней.
Query: days (int, по умолчанию 90, максимум 365).
Ответ:
{
"recomputed_days": 270,
"message": "Пересчитано 270 записей за 90 дней"
}9. Settings (настройки)
GET /api/v1/settings
Все настройки. Ответ: list[SettingResponse].
GET /api/v1/settings/{key}
Одна настройка. Ответ:
{
"key": "auto_generate_enabled",
"value": "true",
"updated_at": "2026-03-10T12:00:00"
}Ошибки: 404 — ключ не найден.
PUT /api/v1/settings/{key}
Создать или обновить. Тело: {"value": "true"}. Ответ: SettingResponse.
10. Prompt Management (промт генерации)
Менеджер может просматривать и редактировать системный промт AI-генерации без деплоя. Дефолтное значение захардкожено в ai_prompts.py; кастомное хранится в app_settings и имеет приоритет.
Менеджер пишет свободный текст (тон, правила, стиль) — данные по отзыву и товару код всегда добавляет сам.
GET /api/v1/prompts
Получить текущий промт.
Ответ:
{
"current_value": "Ты вежливый менеджер...",
"default_value": "Ты представитель бренда...",
"is_customized": true,
"updated_at": "2026-03-30T12:00:00"
}| Поле | Описание |
|---|---|
current_value | Что реально используется при генерации |
default_value | Дефолт из кода — для кнопки «Посмотреть оригинал» |
is_customized | Менеджер изменял промт — для бейджа «изменён» и кнопки «Сбросить» |
updated_at | Дата последнего изменения, null если не менял |
PUT /api/v1/prompts
Сохранить кастомный промт.
Тело: {"value": "Новый текст..."}. Пустая строка → 400.
Ответ: тот же объект с is_customized: true.
DELETE /api/v1/prompts
Сбросить к дефолту (удаляет запись из app_settings).
Ответ: тот же объект с is_customized: false, current_value == default_value, updated_at: null.
11. Автоматические процессы (Scheduler)
Scheduler активен с v1.2.50. Запускается при старте сервера. Backfill убран из автозапуска — для исторических данных: POST /stats/recompute.
Периодические задачи
| Задача | Интервал | Описание |
|---|---|---|
auto_generate_pending | Каждые 5 минут | Берёт до 5 отзывов со статусом new, классифицирует и генерирует черновик. Управляется настройкой auto_generate_enabled в app_settings |
retry_failed_publications | Каждый час | Повторяет публикацию для отзывов со статусом error (до 50 шт.) |
refresh_today_analytics | Каждые 30 минут | Пересчитывает статистику за сегодня и вчера |
Управление авто-генерацией:
PUT /api/v1/settings/auto_generate_enabledсо значением"true"/"false".
12. Схема БД
reputation_products
Данные о товарах (заполняются из AdolfDataSync).
| Поле | Тип | Описание |
|---|---|---|
external_id | BIGINT (PK) | ID товара на маркетплейсе |
marketplace | VARCHAR (PK) | wildberries / ozon / yandex_market |
vendor_code | VARCHAR | Артикул |
title | TEXT | Название |
description | TEXT | Описание |
composition | TEXT | Состав |
size_measurements | JSONB | Размеры |
media_urls | JSONB | Фото |
attributes | JSONB | Характеристики |
Composite PK:
(external_id, marketplace)
reputation_items
Отзывы и вопросы.
| Поле | Тип | Описание |
|---|---|---|
id | INTEGER (PK) | Внутренний ID |
wb_id | VARCHAR(50) | ID на маркетплейсе |
item_type | VARCHAR | review / question |
marketplace | VARCHAR | Маркетплейс |
client_name | VARCHAR | Имя покупателя |
client_text | TEXT | Текст |
rating | INTEGER | 1–5 (null для вопросов) |
status | VARCHAR | Статус (default: new) |
product_id | BIGINT | → reputation_products.external_id |
pros | TEXT | Достоинства |
cons | TEXT | Недостатки |
wb_created_at | DATETIME | Дата создания на маркетплейсе |
created_at | DATETIME | Дата загрузки в систему |
is_viewed | BOOLEAN | Просмотрен |
Статусы:
new → analyzing → pending_review → approved → publishing → answered
└→ error (retry)
new → skipped
new → escalatedreputation_responses
Backward-compatibility слой.
| Поле | Тип | Описание |
|---|---|---|
id | INTEGER (PK) | |
item_id | INTEGER (FK) | → reputation_items.id |
ai_variants | JSONB | Массив вариантов |
final_text | TEXT | Одобренный текст |
status | VARCHAR | draft / approved / published / failed |
manager_notes | TEXT | |
generated_at | DATETIME | |
published_at | DATETIME | |
wb_error | TEXT | Ошибка от маркетплейса |
source | VARCHAR(20) | ai / manager |
reputation_generations
Аудит вызовов генерации.
| Поле | Тип | Описание |
|---|---|---|
id | UUID (PK) | |
item_id | INTEGER (FK) | → reputation_items.id |
status | VARCHAR(20) | pending / processing / completed / failed |
context | JSONB | {client_text, pros, cons, product_context, instructions, rating, item_type} |
analysis_result | JSONB | {sentiment, sentiment_score, tags, category, key_points, scenario} |
error_message | TEXT | |
created_at | DATETIME | |
completed_at | DATETIME |
reputation_drafts
Immutable черновики ответов.
| Поле | Тип | Описание |
|---|---|---|
id | UUID (PK) | |
generation_id | UUID (FK) | → reputation_generations.id |
item_id | INTEGER (FK) | → reputation_items.id |
response_text | TEXT | Текст ответа |
classification | JSONB | Классификация |
is_valid | BOOLEAN | Прошёл валидацию |
status | VARCHAR(20) | draft / approved / rejected |
manager_notes | TEXT | |
created_at | DATETIME |
reputation_publications
Записи публикаций.
| Поле | Тип | Описание |
|---|---|---|
id | UUID (PK) | |
draft_id | UUID (FK) | → reputation_drafts.id |
item_id | INTEGER (FK) | → reputation_items.id |
published_text | TEXT | Опубликованный текст |
status | VARCHAR(20) | success / failed |
error_message | TEXT | |
api_response | JSONB | Полный ответ API маркетплейса |
published_at | DATETIME | |
source | VARCHAR(20) | manual / auto / scheduler |
polling_state
Состояние поллинга.
| Поле | Тип | Описание |
|---|---|---|
marketplace | VARCHAR(30) | |
item_type | VARCHAR(20) | review / question |
last_poll_time | DATETIME(tz) | |
last_poll_status | VARCHAR(20) | success / error / circuit_breaker |
items_fetched_total | INTEGER | Накопительный итог |
consecutive_errors | INTEGER | Ошибки подряд |
circuit_breaker_open | BOOLEAN |
UNIQUE:
(marketplace, item_type)
reputation_analytics
Ежедневная агрегация.
| Поле | Тип | Описание |
|---|---|---|
date | DATE | |
marketplace | VARCHAR(30) | |
total_items | INTEGER | |
reviews_count | INTEGER | |
questions_count | INTEGER | |
positive_count | INTEGER | rating ≥ 4 |
neutral_count | INTEGER | rating = 3 |
negative_count | INTEGER | rating ≤ 2 |
avg_rating | NUMERIC(3,2) | |
published_count | INTEGER | |
our_published_count | INTEGER | |
our_avg_response_time_min | INTEGER |
UNIQUE:
(date, marketplace)
app_settings
Key-value хранилище настроек и промтов.
| Поле | Тип | Описание |
|---|---|---|
key | VARCHAR(100) (PK) | Ключ |
value | TEXT | Значение |
updated_at | DATETIME |
Используемые ключи:
| Ключ | Описание |
|---|---|
auto_generate_enabled | "true" / "false" — управление авто-генерацией |
generation_system_prompt | Кастомный системный промт (если задан менеджером) |
13. Пайплайн обработки
Polling → new → analyzing → pending_review → approved → publishing → answered
└→ error (retry hourly)
→ skipped
→ escalatedТаблицы по этапам:
| Этап | Таблицы |
|---|---|
| Polling | reputation_items (INSERT), polling_state (UPDATE) |
| Generate | reputation_generations, reputation_drafts, reputation_responses, auto_process_log, reputation_items |
| Approve | reputation_drafts, reputation_responses, reputation_items |
| Publish | reputation_publications, reputation_responses, reputation_items, auto_process_log |
14. Миграции
| Файл | Описание |
|---|---|
add_response_source.sql | Добавляет колонку source (VARCHAR(20), default 'manager') в reputation_responses. Backfill: source='ai' для ответов с непустым ai_variants |