# API Документация: Маркетинговый анализ (Frontend/AI Agent)

## Базовый URL

```
https://api.konturai.kz
```

## Обзор

API для генерации маркетингового анализа на основе данных о бизнесе. Процесс состоит из двух этапов:

1. **Запуск анализа** - создание задачи и начало асинхронной обработки
2. **Получение результатов** - проверка статуса и получение готового отчета

Анализ выполняется асинхронно и занимает примерно 5-10 минут.

---

## Эндпоинты

### 1. Запуск маркетингового анализа

**POST** `/api/marketing/analysis/start`

Создает новую задачу на генерацию маркетингового анализа и запускает асинхронную обработку.

#### Заголовки запроса

```
Content-Type: application/json
```

#### Тело запроса (JSON)

| Поле             | Тип    | Обязательный | Описание                       | Пример значения                  |
| ---------------- | ------ | ------------ | ------------------------------ | -------------------------------- |
| `product`        | string | ✅           | Название продукта или услуги   | "Веб-разработка"                 |
| `location`       | string | ✅           | Географическая локация работы  | "Алматы, Казахстан"              |
| `client`         | string | ✅           | Тип целевой аудитории          | "B2B клиенты"                    |
| `differentiator` | string | ✅           | Уникальные особенности бизнеса | "Быстрая разработка за 2 недели" |

#### Валидация полей

**`product`** (string, обязательное)

-   Минимальная длина: 3 символа
-   Максимальная длина: 200 символов
-   Разрешены: буквы, цифры, пробелы, дефисы, запятые

**`location`** (string, обязательное)

-   Минимальная длина: 2 символа
-   Максимальная длина: 150 символов
-   Разрешены: буквы, цифры, пробелы, запятые, дефисы

**`client`** (string, обязательное)

-   Допустимые значения (точно):
    -   `"B2B клиенты"`
    -   `"B2C клиенты"`
    -   `"Частные лица"`
    -   `"Корпорации"`
    -   `"Малый бизнес"`

**`differentiator`** (string, обязательное)

-   Минимальная длина: 10 символов
-   Максимальная длина: 500 символов
-   Разрешены любые символы

#### Пример запроса

```json
{
    "product": "Разработка мобильных приложений",
    "location": "Нур-Султан, Казахстан",
    "client": "B2B клиенты",
    "differentiator": "Специализируемся на быстрой разработке MVP за 4 недели с использованием современных технологий"
}
```

#### Пример успешного ответа (200 OK)

```json
{
    "success": true,
    "message": "Анализ запущен успешно",
    "data": {
        "analysisId": "507f1f77bcf86cd799439011",
        "status": "processing",
        "estimatedCompletionTime": "2025-01-20T15:38:00",
        "message": "Анализ запущен успешно. Результаты будут готовы в течение 5-10 минут."
    }
}
```

#### Структура ответа

| Поле                           | Тип     | Описание                                                  |
| ------------------------------ | ------- | --------------------------------------------------------- |
| `success`                      | boolean | Флаг успешности операции                                  |
| `message`                      | string  | Сообщение о результате операции                           |
| `data.analysisId`              | string  | Уникальный идентификатор анализа (MongoDB ObjectId)       |
| `data.status`                  | string  | Статус анализа: `"processing"`                            |
| `data.estimatedCompletionTime` | string  | ISO 8601 дата/время ожидаемого завершения (LocalDateTime) |
| `data.message`                 | string  | Информационное сообщение для пользователя                 |

#### Пример ошибки валидации (400 Bad Request)

```json
{
    "success": false,
    "message": "Ошибка валидации",
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "Ошибка валидации входных данных",
        "details": {
            "product": "Поле 'product' должно содержать от 3 до 200 символов",
            "client": "Поле 'client' должно быть одним из: B2B клиенты, B2C клиенты, Частные лица, Корпорации, Малый бизнес"
        }
    }
}
```

---

### 2. Получение результата анализа

**GET** `/api/marketing/analysis/{analysisId}`

Возвращает статус и результаты анализа по идентификатору.

#### Параметры пути

| Параметр     | Тип    | Описание              |
| ------------ | ------ | --------------------- |
| `analysisId` | string | Идентификатор анализа |

#### Пример запроса

```
GET /api/marketing/analysis/507f1f77bcf86cd799439011
```

#### Пример ответа (когда анализ завершен - 200 OK)

```json
{
    "success": true,
    "message": "Операция выполнена успешно",
    "data": {
        "analysisId": "507f1f77bcf86cd799439011",
        "status": "completed",
        "createdAt": "2025-01-20T15:30:00",
        "completedAt": "2025-01-20T15:38:00",
        "report": {
            "summary": "Краткое резюме анализа...",
            "targetAudience": {
                "description": "Описание целевой аудитории...",
                "channels": ["Instagram", "LinkedIn", "Telegram"]
            },
            "recommendations": ["Рекомендация 1", "Рекомендация 2", "Рекомендация 3"],
            "strategy": {
                "duration": "2 недели",
                "channels": ["Instagram", "Telegram", "21MC"],
                "contentTypes": ["посты", "сторис", "баннеры"]
            },
            "pdfUrl": "/api/marketing/analysis/507f1f77bcf86cd799439011/download"
        }
    }
}
```

#### Пример ответа (когда анализ еще обрабатывается - 200 OK)

```json
{
    "success": true,
    "message": "Операция выполнена успешно",
    "data": {
        "analysisId": "507f1f77bcf86cd799439011",
        "status": "processing",
        "createdAt": "2025-01-20T15:30:00",
        "completedAt": null,
        "report": null
    }
}
```

#### Статусы анализа

| Статус       | Описание                      |
| ------------ | ----------------------------- |
| `queued`     | Запрос в очереди на обработку |
| `processing` | Анализ выполняется            |
| `completed`  | Анализ завершен успешно       |
| `failed`     | Анализ завершился с ошибкой   |

#### Структура ответа

| Поле                                     | Тип     | Описание                                               |
| ---------------------------------------- | ------- | ------------------------------------------------------ |
| `success`                                | boolean | Флаг успешности операции                               |
| `message`                                | string  | Сообщение о результате операции                        |
| `data.analysisId`                        | string  | Уникальный идентификатор анализа                       |
| `data.status`                            | string  | Статус анализа                                         |
| `data.createdAt`                         | string  | ISO 8601 дата/время создания                           |
| `data.completedAt`                       | string  | ISO 8601 дата/время завершения (null если не завершен) |
| `data.report`                            | object  | Объект с результатами (null если не завершен)          |
| `data.report.summary`                    | string  | Краткое резюме анализа                                 |
| `data.report.targetAudience`             | object  | Информация о целевой аудитории                         |
| `data.report.targetAudience.description` | string  | Описание целевой аудитории                             |
| `data.report.targetAudience.channels`    | array   | Список рекомендуемых каналов                           |
| `data.report.recommendations`            | array   | Список рекомендаций (массив строк)                     |
| `data.report.strategy`                   | object  | Маркетинговая стратегия                                |
| `data.report.strategy.duration`          | string  | Длительность кампании (например, "2 недели")           |
| `data.report.strategy.channels`          | array   | Каналы коммуникации (массив строк)                     |
| `data.report.strategy.contentTypes`      | array   | Типы контента (массив строк)                           |
| `data.report.pdfUrl`                     | string  | URL для скачивания PDF отчета                          |

#### Пример ошибки (404 Not Found)

```json
{
    "success": false,
    "message": "Анализ не найден",
    "error": {
        "code": "NOT_FOUND",
        "message": "Анализ с указанным ID не найден"
    }
}
```

---

### 3. Скачивание PDF отчета

**GET** `/api/marketing/analysis/{analysisId}/download`

Возвращает PDF файл с полным маркетинговым отчетом.

#### Параметры пути

| Параметр     | Тип    | Описание              |
| ------------ | ------ | --------------------- |
| `analysisId` | string | Идентификатор анализа |

#### Пример запроса

```
GET /api/marketing/analysis/507f1f77bcf86cd799439011/download
```

#### Успешный ответ (200 OK)

-   **Content-Type**: `application/pdf`
-   **Content-Disposition**: `attachment; filename="marketing_analysis_507f1f77bcf86cd799439011_1234567890.pdf"`
-   **Body**: Бинарные данные PDF файла

#### Ошибки

-   **404 Not Found** - Анализ не найден или PDF еще не сгенерирован
-   **500 Internal Server Error** - Ошибка при получении файла

---

## Обработка ошибок

### Коды ошибок

| Код                     | HTTP статус | Описание                        |
| ----------------------- | ----------- | ------------------------------- |
| `VALIDATION_ERROR`      | 400         | Ошибка валидации входных данных |
| `NOT_FOUND`             | 404         | Ресурс не найден                |
| `INTERNAL_SERVER_ERROR` | 500         | Внутренняя ошибка сервера       |

### Формат ошибки

```json
{
    "success": false,
    "message": "Описание ошибки",
    "error": {
        "code": "ERROR_CODE",
        "message": "Детальное сообщение об ошибке",
        "details": {
            "field1": "Сообщение об ошибке для поля 1",
            "field2": "Сообщение об ошибке для поля 2"
        }
    }
}
```

**Примечание**: Поле `details` присутствует только для ошибок валидации (`VALIDATION_ERROR`).

---

## Примеры использования

### JavaScript/TypeScript (Fetch API)

#### Запуск анализа

```javascript
async function startMarketingAnalysis(data) {
    const response = await fetch('https://api.konturai.kz/api/marketing/analysis/start', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            product: 'Разработка мобильных приложений',
            location: 'Нур-Султан, Казахстан',
            client: 'B2B клиенты',
            differentiator: 'Специализируемся на быстрой разработке MVP за 4 недели'
        })
    });

    const result = await response.json();

    if (result.success) {
        console.log('Analysis ID:', result.data.analysisId);
        return result.data.analysisId;
    } else {
        console.error('Error:', result.error);
        throw new Error(result.error.message);
    }
}
```

#### Проверка статуса и получение результата

```javascript
async function getAnalysisResult(analysisId) {
    const response = await fetch(`https://api.konturai.kz/api/marketing/analysis/${analysisId}`);

    const result = await response.json();

    if (result.success) {
        const { status, report } = result.data;

        if (status === 'completed' && report) {
            console.log('Analysis completed!');
            console.log('Summary:', report.summary);
            console.log('Recommendations:', report.recommendations);
            return report;
        } else if (status === 'processing') {
            console.log('Analysis is still processing...');
            return null; // Повторить запрос позже
        } else if (status === 'failed') {
            throw new Error('Analysis failed');
        }
    } else {
        throw new Error(result.error.message);
    }
}
```

#### Полный цикл с polling

```javascript
async function waitForAnalysisCompletion(analysisId, maxAttempts = 60, intervalMs = 10000) {
    for (let i = 0; i < maxAttempts; i++) {
        const result = await getAnalysisResult(analysisId);

        if (result) {
            return result; // Анализ завершен
        }

        // Ждем перед следующей проверкой
        await new Promise((resolve) => setTimeout(resolve, intervalMs));
    }

    throw new Error('Analysis timeout');
}

// Использование
async function runFullAnalysis() {
    try {
        // 1. Запускаем анализ
        const analysisId = await startMarketingAnalysis({
            product: 'Веб-разработка',
            location: 'Алматы, Казахстан',
            client: 'B2B клиенты',
            differentiator: 'Быстрая разработка за 2 недели'
        });

        console.log(`Analysis started: ${analysisId}`);

        // 2. Ждем завершения (проверяем каждые 10 секунд, максимум 10 минут)
        const report = await waitForAnalysisCompletion(analysisId, 60, 10000);

        // 3. Используем результаты
        console.log('Report summary:', report.summary);
        console.log('Channels:', report.targetAudience.channels);
        console.log('PDF URL:', report.pdfUrl);

        return report;
    } catch (error) {
        console.error('Error:', error);
    }
}
```

#### Скачивание PDF

```javascript
async function downloadPdf(analysisId) {
    const response = await fetch(`https://api.konturai.kz/api/marketing/analysis/${analysisId}/download`);

    if (!response.ok) {
        throw new Error('Failed to download PDF');
    }

    const blob = await response.blob();
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `marketing_analysis_${analysisId}.pdf`;
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
    document.body.removeChild(a);
}
```

### Python

```python
import requests
import time

BASE_URL = "https://api.konturai.kz"

def start_analysis(product, location, client, differentiator):
    response = requests.post(
        f"{BASE_URL}/api/marketing/analysis/start",
        json={
            "product": product,
            "location": location,
            "client": client,
            "differentiator": differentiator
        }
    )
    response.raise_for_status()
    data = response.json()

    if data["success"]:
        return data["data"]["analysisId"]
    else:
        raise Exception(data["error"]["message"])

def get_analysis_result(analysis_id):
    response = requests.get(
        f"{BASE_URL}/api/marketing/analysis/{analysis_id}"
    )
    response.raise_for_status()
    return response.json()["data"]

def wait_for_completion(analysis_id, max_attempts=60, interval=10):
    for _ in range(max_attempts):
        result = get_analysis_result(analysis_id)

        if result["status"] == "completed":
            return result["report"]
        elif result["status"] == "failed":
            raise Exception("Analysis failed")

        time.sleep(interval)

    raise Exception("Analysis timeout")

# Использование
analysis_id = start_analysis(
    product="Разработка мобильных приложений",
    location="Нур-Султан, Казахстан",
    client="B2B клиенты",
    differentiator="Быстрая разработка MVP за 4 недели"
)

print(f"Analysis started: {analysis_id}")

report = wait_for_completion(analysis_id)
print(f"Summary: {report['summary']}")
print(f"Channels: {report['targetAudience']['channels']}")
```

---

## Рекомендации по интеграции

### 1. Polling стратегия

Рекомендуется проверять статус анализа каждые 10-15 секунд. Максимальное время ожидания - 10-15 минут.

### 2. Обработка ошибок

Всегда проверяйте поле `success` в ответе и обрабатывайте ошибки соответствующим образом.

### 3. Валидация на клиенте

Перед отправкой запроса рекомендуется валидировать данные на клиенте:

-   Проверка длины полей
-   Проверка допустимых значений для `client`
-   Проверка обязательных полей

### 4. UX рекомендации

-   Показывайте индикатор загрузки во время обработки
-   Отображайте примерное время завершения
-   Предоставьте возможность отменить ожидание и проверить результат позже
-   Сохраняйте `analysisId` для последующей проверки статуса

### 5. Кэширование

После получения результатов можно кэшировать их локально, используя `analysisId` как ключ.

---

## Примечания

1. **Формат даты**: Все даты возвращаются в формате ISO 8601 без timezone (LocalDateTime)
2. **Идентификаторы**: Используются MongoDB ObjectId (24 символа hex)
3. **Асинхронность**: Анализ выполняется асинхронно, не блокируя запрос
4. **Таймауты**: Рекомендуется устанавливать таймаут на запросы (минимум 30 секунд для запуска анализа)
5. **Rate Limiting**: В будущем может быть добавлено ограничение на количество запросов

---

## Поддержка

При возникновении проблем с API обращайтесь в техническую поддержку с указанием:

-   `analysisId` (если есть)
-   Время запроса
-   Описание проблемы
-   Код ошибки (если есть)
