Files
marketing-parser/marketing-analysis-api-updated-fields.md
T
2025-12-03 19:33:49 +05:00

37 KiB

API Документация: Обновленные поля для генерации бизнес-анализа (Frontend/AI Agent)

Обзор изменений

API для генерации маркетингового анализа был обновлен с новыми полями, которые более точно отражают требования бизнес-анализа. Все старые поля были заменены новыми для улучшения качества анализа.


Изменения в структуре запроса

Удаленные поля (больше не используются)

Следующие поля были удалены из API и больше не принимаются:

  • location - заменено на region
  • client - заменено на targetAudience
  • differentiator - заменено на комбинацию businessNiche, strongSide, weakSide

Новые обязательные поля

Поле Тип Обязательный Описание Пример значения
businessNiche string Ниша бизнеса "E-commerce платформы"
product string Продукт или услуга "Разработка мобильных приложений"
targetAudience string Целевая аудитория (детальное описание) "Малый и средний бизнес, владельцы интернет-магазинов"
region string Регион (город Казахстана) "Алматы"
goal string Цель на 6-12 месяцев "Увеличить количество клиентов на 50%"
detailLevel string Уровень детализации анализа "СТАНДАРТНО"
analysisType string Тип анализа "РЫНОК"

Новые опциональные поля

Поле Тип Обязательный Описание Пример значения
strongSide string Сильная сторона бизнеса "Опытная команда разработчиков, быстрая доставка"
weakSide string Слабая сторона бизнеса "Ограниченный маркетинговый бюджет"

Детальное описание полей

1. businessNiche (обязательное)

Описание: Ниша бизнеса, в которой работает компания.

Валидация:

  • Минимальная длина: 3 символа
  • Максимальная длина: 200 символов
  • Разрешены: буквы, цифры, пробелы, дефисы, запятые
  • Паттерн: ^[\p{L}\p{N}\s\-,]+$

Примеры:

"businessNiche": "E-commerce платформы"
"businessNiche": "Образовательные технологии"
"businessNiche": "Финансовые услуги для малого бизнеса"

2. product (обязательное)

Описание: Конкретный продукт или услуга, которую предоставляет компания.

Валидация:

  • Минимальная длина: 3 символа
  • Максимальная длина: 200 символов
  • Разрешены: буквы, цифры, пробелы, дефисы, запятые
  • Паттерн: ^[\p{L}\p{N}\s\-,]+$

Примеры:

"product": "Разработка мобильных приложений"
"product": "Консультации по маркетингу"
"product": "Веб-разработка и дизайн"

3. targetAudience (обязательное)

Описание: Структурированное описание целевой аудитории в формате JSON. Позволяет выбрать гендер, возрастные диапазоны и типы аудитории. Можно выбрать несколько вариантов в каждой категории.

Валидация:

  • Должно быть объектом JSON с полями genders, ageRanges, types
  • Хотя бы одно поле должно быть заполнено и содержать непустой массив
  • Каждое поле должно содержать только допустимые значения

Структура:

{
  "genders": ["Женщины", "Мужчины"],
  "ageRanges": ["20-40", "25-45"],
  "types": ["Семьи", "Молодёжь"]
}

Допустимые значения:

  • genders: ["Женщины", "Мужчины"] - можно выбрать один или оба
  • ageRanges: ["20-40", "25-45", "18-25", "40-60", "60+"] - можно выбрать один или несколько диапазонов
  • types: ["Семьи", "Молодёжь", "Все подряд"] - можно выбрать один или несколько типов

Примеры:

"targetAudience": {
  "genders": ["Женщины"],
  "ageRanges": ["20-40"],
  "types": ["Молодёжь"]
}
"targetAudience": {
  "genders": ["Женщины", "Мужчины"],
  "ageRanges": ["25-45", "40-60"],
  "types": ["Семьи"]
}
"targetAudience": {
  "genders": ["Мужчины"],
  "ageRanges": ["18-25"],
  "types": ["Молодёжь", "Все подряд"]
}

Примечание: Можно выбрать несколько вариантов в каждой категории. Все выбранные значения будут отражены в анализе.


4. region (обязательное)

Описание: Регионы (города Казахстана), в которых работает бизнес. Можно выбрать один или несколько регионов. Это поле заменяет старое поле location.

Валидация:

  • Должно быть массивом строк
  • Минимум один регион должен быть выбран
  • Каждый регион должен быть одним из допустимых городов Казахстана
  • Проверка выполняется через валидатор @ValidRegion

Допустимые значения (точное совпадение):

  • "Алматы"
  • "Астана"
  • "Шымкент"
  • "Караганда"
  • "Актобе"
  • "Тараз"
  • "Павлодар"
  • "Усть-Каменогорск"
  • "Семей"
  • "Костанай"
  • "Кызылорда"
  • "Уральск"
  • "Петропавловск"
  • "Атырау"
  • "Актау"
  • "Туркестан"
  • "Кокшетау"
  • "Талдыкорган"
  • "Экибастуз"
  • "Рудный"

Примеры:

"region": ["Алматы"]
"region": ["Алматы", "Астана", "Шымкент"]
"region": ["Астана", "Караганда"]

Важно:

  • Значения должны точно совпадать с допустимыми городами (регистр важен)
  • Можно выбрать все регионы, перечислив их в массиве
  • Все выбранные регионы будут отражены в анализе

5. goal (обязательное)

Описание: Цель бизнеса на период 6-12 месяцев. Это новое поле, которое помогает AI лучше понять приоритеты бизнеса.

Валидация:

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

Примеры:

"goal": "Увеличить количество клиентов на 50% за следующие 6 месяцев"
"goal": "Выйти на рынок соседних регионов и открыть 3 новых филиала"
"goal": "Повысить узнаваемость бренда и увеличить продажи через онлайн-каналы на 30%"

6. detailLevel (обязательное)

Описание: Уровень детализации анализа. Влияет на объем и глубину генерируемого анализа.

Валидация:

  • Должно быть одним из допустимых значений
  • Проверка выполняется через валидатор @ValidDetailLevel

Допустимые значения (точное совпадение, регистр важен):

  • "КРАТКО" - Краткий анализ (1-2 абзаца)
  • "СТАНДАРТНО" - Стандартный анализ (3-5 абзацев) - рекомендуется по умолчанию
  • "ПОДРОБНО" - Подробный анализ (5-8 абзацев)

Влияние на анализ:

Уровень Длина ответов Количество рекомендаций Детализация стратегии
КРАТКО 1-2 абзаца 3-4 рекомендации Краткая
СТАНДАРТНО 3-5 абзацев 4-6 рекомендаций Стандартная
ПОДРОБНО 5-8 абзацев 6-8 рекомендаций Детальная с обоснованием

Примеры:

"detailLevel": "КРАТКО"
"detailLevel": "СТАНДАРТНО"
"detailLevel": "ПОДРОБНО"

7. strongSide (опциональное)

Описание: Сильная сторона бизнеса. Помогает AI лучше понять конкурентные преимущества.

Валидация:

  • Максимальная длина: 500 символов
  • Разрешены любые символы
  • Может быть пустым или отсутствовать

Примеры:

"strongSide": "Опытная команда разработчиков с 10+ летним опытом, быстрая доставка проектов"
"strongSide": "Уникальная технология, низкие цены, отличная поддержка клиентов"

Примечание: Если поле не указано, AI будет анализировать сильные стороны на основе других данных.


8. weakSide (опциональное)

Описание: Слабая сторона бизнеса. Помогает AI лучше понять области для улучшения.

Валидация:

  • Максимальная длина: 500 символов
  • Разрешены любые символы
  • Может быть пустым или отсутствовать

Примеры:

"weakSide": "Ограниченный маркетинговый бюджет, недостаточная узнаваемость бренда"
"weakSide": "Небольшая команда, ограниченные ресурсы для масштабирования"

Примечание: Если поле не указано, AI будет анализировать слабые стороны на основе других данных.


9. analysisType (обязательное)

Описание: Тип(ы) анализа, которые необходимо провести. Можно выбрать один или несколько типов анализа. При выборе нескольких типов будет создан отдельный анализ для каждого типа.

Валидация:

  • Должно быть массивом строк
  • Минимум один тип анализа должен быть выбран
  • Каждый тип должен быть одним из допустимых значений
  • Проверка выполняется через валидатор @ValidAnalysisType

Допустимые значения:

  • "РЫНОК" - Анализ рынка (размер рынка, динамика роста, сегменты, тренды)
  • "КОНКУРЕНТЫ" - Анализ конкурентов (основные конкуренты, их сильные/слабые стороны, позиционирование)
  • "ЦА" - Анализ целевой аудитории (демография, психография, потребности, поведение)
  • "КАНАЛЫ" - Анализ маркетинговых каналов (эффективность каналов, рекомендации по выбору)
  • "SWOT" - SWOT-анализ (сильные стороны, слабые стороны, возможности, угрозы)

Примеры:

"analysisType": ["РЫНОК"]
"analysisType": ["РЫНОК", "КОНКУРЕНТЫ", "ЦА"]
"analysisType": ["РЫНОК", "КОНКУРЕНТЫ", "ЦА", "КАНАЛЫ", "SWOT"]

Важно:

  • При выборе нескольких типов анализа API создаст отдельные записи анализа для каждого типа
  • В ответе будет возвращен массив с информацией о каждом созданном анализе
  • Каждый анализ будет обрабатываться независимо и иметь свой статус

Полный пример запроса

POST /api/marketing/analysis/start

Пример 1: Один тип анализа, один регион

{
  "businessNiche": "E-commerce платформы",
  "product": "Разработка мобильных приложений для интернет-магазинов",
  "targetAudience": {
    "genders": ["Женщины"],
    "ageRanges": ["25-45"],
    "types": ["Молодёжь"]
  },
  "region": ["Алматы"],
  "goal": "Увеличить количество клиентов на 50% за следующие 6 месяцев и выйти на рынок соседних регионов",
  "detailLevel": "СТАНДАРТНО",
  "strongSide": "Опытная команда разработчиков с 10+ летним опытом, быстрая доставка проектов, использование современных технологий",
  "weakSide": "Ограниченный маркетинговый бюджет, недостаточная узнаваемость бренда в новых регионах",
  "analysisType": ["РЫНОК"]
}

Пример 2: Несколько типов анализа, несколько регионов

{
  "businessNiche": "E-commerce платформы",
  "product": "Разработка мобильных приложений для интернет-магазинов",
  "targetAudience": {
    "genders": ["Женщины", "Мужчины"],
    "ageRanges": ["25-45", "40-60"],
    "types": ["Семьи", "Молодёжь"]
  },
  "region": ["Алматы", "Астана", "Шымкент"],
  "goal": "Увеличить количество клиентов на 50% за следующие 6 месяцев и выйти на рынок соседних регионов",
  "detailLevel": "СТАНДАРТНО",
  "strongSide": "Опытная команда разработчиков с 10+ летним опытом, быстрая доставка проектов",
  "weakSide": "Ограниченный маркетинговый бюджет",
  "analysisType": ["РЫНОК", "КОНКУРЕНТЫ", "ЦА"]
}

Пример 3: Все типы анализа

{
  "businessNiche": "E-commerce платформы",
  "product": "Разработка мобильных приложений для интернет-магазинов",
  "targetAudience": {
    "genders": ["Женщины", "Мужчины"],
    "ageRanges": ["20-40", "25-45"],
    "types": ["Семьи", "Молодёжь", "Все подряд"]
  },
  "region": ["Алматы", "Астана"],
  "goal": "Увеличить количество клиентов на 50% за следующие 6 месяцев",
  "detailLevel": "ПОДРОБНО",
  "analysisType": ["РЫНОК", "КОНКУРЕНТЫ", "ЦА", "КАНАЛЫ", "SWOT"]
}

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

JavaScript/TypeScript

interface TargetAudience {
  genders?: ('Женщины' | 'Мужчины')[];
  ageRanges?: ('20-40' | '25-45' | '18-25' | '40-60' | '60+')[];
  types?: ('Семьи' | 'Молодёжь' | 'Все подряд')[];
}

interface MarketingAnalysisRequest {
  businessNiche: string;
  product: string;
  targetAudience: TargetAudience;
  region: string[];
  goal: string;
  detailLevel: 'КРАТКО' | 'СТАНДАРТНО' | 'ПОДРОБНО';
  strongSide?: string;
  weakSide?: string;
  analysisType: ('РЫНОК' | 'КОНКУРЕНТЫ' | 'ЦА' | 'КАНАЛЫ' | 'SWOT')[];
}

// Список допустимых регионов
const VALID_REGIONS = [
  'Алматы',
  'Астана',
  'Шымкент',
  'Караганда',
  'Актобе',
  'Тараз',
  'Павлодар',
  'Усть-Каменогорск',
  'Семей',
  'Костанай',
  'Кызылорда',
  'Уральск',
  'Петропавловск',
  'Атырау',
  'Актау',
  'Туркестан',
  'Кокшетау',
  'Талдыкорган',
  'Экибастуз',
  'Рудный',
];

// Список уровней детализации
const DETAIL_LEVELS = ['КРАТКО', 'СТАНДАРТНО', 'ПОДРОБНО'] as const;

// Функция для отправки запроса
async function startMarketingAnalysis(
  data: MarketingAnalysisRequest
): Promise<MarketingAnalysisResponse | MarketingAnalysisResponse[]> {
  const response = await fetch(
    'https://api.konturai.kz/api/marketing/analysis/start',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer YOUR_JWT_TOKEN', // Если требуется
      },
      body: JSON.stringify(data),
    }
  );

  const result = await response.json();

  if (!result.success) {
    throw new Error(result.error?.message || 'Failed to start analysis');
  }

  // Если выбрано несколько типов анализа, result.data будет массивом
  return result.data;
}

interface MarketingAnalysisResponse {
  analysisId: string;
  status: string;
  estimatedCompletion: string;
  message: string;
}

// Пример использования
const result = await startMarketingAnalysis({
  businessNiche: 'E-commerce платформы',
  product: 'Разработка мобильных приложений',
  targetAudience: {
    genders: ['Женщины', 'Мужчины'],
    ageRanges: ['25-45'],
    types: ['Молодёжь']
  },
  region: ['Алматы', 'Астана'],
  goal: 'Увеличить количество клиентов на 50% за следующие 6 месяцев',
  detailLevel: 'СТАНДАРТНО',
  strongSide: 'Опытная команда, быстрая доставка',
  weakSide: 'Ограниченный маркетинговый бюджет',
  analysisType: ['РЫНОК', 'КОНКУРЕНТЫ'],
});

// Если выбрано несколько типов анализа, result будет массивом
if (Array.isArray(result)) {
  console.log(`Создано ${result.length} анализов`);
  result.forEach((analysis, index) => {
    console.log(`Анализ ${index + 1}: ${analysis.analysisId}`);
  });
} else {
  console.log('Анализ создан:', result.analysisId);
}

React компонент с формой

import React, { useState } from 'react';

const MarketingAnalysisForm: React.FC = () => {
  const [formData, setFormData] = useState<MarketingAnalysisRequest>({
    businessNiche: '',
    product: '',
    targetAudience: {
      genders: [],
      ageRanges: [],
      types: []
    },
    region: [],
    goal: '',
    detailLevel: 'СТАНДАРТНО',
    strongSide: '',
    weakSide: '',
    analysisType: [],
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    try {
      const analysisId = await startMarketingAnalysis(formData);
      console.log('Analysis started:', analysisId);
      // Перенаправление на страницу с результатами
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Ниша бизнеса *</label>
        <input
          type='text'
          value={formData.businessNiche}
          onChange={(e) =>
            setFormData({ ...formData, businessNiche: e.target.value })
          }
          required
          minLength={3}
          maxLength={200}
        />
      </div>

      <div>
        <label>Продукт / услуга *</label>
        <input
          type='text'
          value={formData.product}
          onChange={(e) =>
            setFormData({ ...formData, product: e.target.value })
          }
          required
          minLength={3}
          maxLength={200}
        />
      </div>

      <div>
        <label>Целевая аудитория *</label>
        <div>
          <div>
            <label>Гендер:</label>
            {['Женщины', 'Мужчины'].map((gender) => (
              <label key={gender}>
                <input
                  type='checkbox'
                  checked={formData.targetAudience.genders?.includes(gender as any)}
                  onChange={(e) => {
                    const genders = formData.targetAudience.genders || [];
                    if (e.target.checked) {
                      setFormData({
                        ...formData,
                        targetAudience: {
                          ...formData.targetAudience,
                          genders: [...genders, gender as any]
                        }
                      });
                    } else {
                      setFormData({
                        ...formData,
                        targetAudience: {
                          ...formData.targetAudience,
                          genders: genders.filter((g) => g !== gender)
                        }
                      });
                    }
                  }}
                />
                {gender}
              </label>
            ))}
          </div>
          <div>
            <label>Возраст:</label>
            {['20-40', '25-45', '18-25', '40-60', '60+'].map((age) => (
              <label key={age}>
                <input
                  type='checkbox'
                  checked={formData.targetAudience.ageRanges?.includes(age as any)}
                  onChange={(e) => {
                    const ageRanges = formData.targetAudience.ageRanges || [];
                    if (e.target.checked) {
                      setFormData({
                        ...formData,
                        targetAudience: {
                          ...formData.targetAudience,
                          ageRanges: [...ageRanges, age as any]
                        }
                      });
                    } else {
                      setFormData({
                        ...formData,
                        targetAudience: {
                          ...formData.targetAudience,
                          ageRanges: ageRanges.filter((a) => a !== age)
                        }
                      });
                    }
                  }}
                />
                {age}
              </label>
            ))}
          </div>
          <div>
            <label>Тип:</label>
            {['Семьи', 'Молодёжь', 'Все подряд'].map((type) => (
              <label key={type}>
                <input
                  type='checkbox'
                  checked={formData.targetAudience.types?.includes(type as any)}
                  onChange={(e) => {
                    const types = formData.targetAudience.types || [];
                    if (e.target.checked) {
                      setFormData({
                        ...formData,
                        targetAudience: {
                          ...formData.targetAudience,
                          types: [...types, type as any]
                        }
                      });
                    } else {
                      setFormData({
                        ...formData,
                        targetAudience: {
                          ...formData.targetAudience,
                          types: types.filter((t) => t !== type)
                        }
                      });
                    }
                  }}
                />
                {type}
              </label>
            ))}
          </div>
        </div>
      </div>

      <div>
        <label>Регион *</label>
        <div>
          {VALID_REGIONS.map((region) => (
            <label key={region}>
              <input
                type='checkbox'
                checked={formData.region.includes(region)}
                onChange={(e) => {
                  if (e.target.checked) {
                    setFormData({
                      ...formData,
                      region: [...formData.region, region]
                    });
                  } else {
                    setFormData({
                      ...formData,
                      region: formData.region.filter((r) => r !== region)
                    });
                  }
                }}
              />
              {region}
            </label>
          ))}
        </div>
      </div>

      <div>
        <label>Цель на 6-12 месяцев *</label>
        <textarea
          value={formData.goal}
          onChange={(e) => setFormData({ ...formData, goal: e.target.value })}
          required
          minLength={10}
          maxLength={500}
        />
      </div>

      <div>
        <label>Уровень детализации анализа *</label>
        <div>
          {DETAIL_LEVELS.map((level) => (
            <label key={level}>
              <input
                type='radio'
                name='detailLevel'
                value={level}
                checked={formData.detailLevel === level}
                onChange={(e) =>
                  setFormData({
                    ...formData,
                    detailLevel: e.target.value as any,
                  })
                }
              />
              {level === 'КРАТКО' && ' Кратко'}
              {level === 'СТАНДАРТНО' && ' Стандартно'}
              {level === 'ПОДРОБНО' && ' Подробно'}
            </label>
          ))}
        </div>
      </div>

      <div>
        <label>Сильная сторона</label>
        <textarea
          value={formData.strongSide}
          onChange={(e) =>
            setFormData({ ...formData, strongSide: e.target.value })
          }
          maxLength={500}
        />
      </div>

      <div>
        <label>Слабая сторона</label>
        <textarea
          value={formData.weakSide}
          onChange={(e) =>
            setFormData({ ...formData, weakSide: e.target.value })
          }
          maxLength={500}
        />
      </div>

      <div>
        <label>Тип анализа *</label>
        <div>
          {['РЫНОК', 'КОНКУРЕНТЫ', 'ЦА', 'КАНАЛЫ', 'SWOT'].map((type) => (
            <label key={type}>
              <input
                type='checkbox'
                checked={formData.analysisType.includes(type as any)}
                onChange={(e) => {
                  if (e.target.checked) {
                    setFormData({
                      ...formData,
                      analysisType: [...formData.analysisType, type as any]
                    });
                  } else {
                    setFormData({
                      ...formData,
                      analysisType: formData.analysisType.filter((t) => t !== type)
                    });
                  }
                }}
              />
              {type === 'РЫНОК' && ' Рынок'}
              {type === 'КОНКУРЕНТЫ' && ' Конкуренты'}
              {type === 'ЦА' && ' Целевая аудитория'}
              {type === 'КАНАЛЫ' && ' Каналы'}
              {type === 'SWOT' && ' SWOT'}
            </label>
          ))}
        </div>
      </div>

      <button type='submit'>Сгенерировать анализ бизнеса</button>
    </form>
  );
};

Валидация на клиенте

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

function validateMarketingAnalysisRequest(data: MarketingAnalysisRequest): {
  valid: boolean;
  errors: Record<string, string>;
} {
  const errors: Record<string, string> = {};

  // Валидация businessNiche
  if (!data.businessNiche || data.businessNiche.trim().length < 3) {
    errors.businessNiche = 'Ниша бизнеса должна содержать минимум 3 символа';
  }
  if (data.businessNiche && data.businessNiche.length > 200) {
    errors.businessNiche = 'Ниша бизнеса не должна превышать 200 символов';
  }

  // Валидация product
  if (!data.product || data.product.trim().length < 3) {
    errors.product = 'Продукт должен содержать минимум 3 символа';
  }
  if (data.product && data.product.length > 200) {
    errors.product = 'Продукт не должен превышать 200 символов';
  }

  // Валидация targetAudience
  if (!data.targetAudience || data.targetAudience.trim().length < 3) {
    errors.targetAudience =
      'Целевая аудитория должна содержать минимум 3 символа';
  }
  if (data.targetAudience && data.targetAudience.length > 300) {
    errors.targetAudience =
      'Целевая аудитория не должна превышать 300 символов';
  }

  // Валидация region
  if (!data.region || !VALID_REGIONS.includes(data.region)) {
    errors.region = 'Выберите допустимый регион из списка';
  }

  // Валидация goal
  if (!data.goal || data.goal.trim().length < 10) {
    errors.goal = 'Цель должна содержать минимум 10 символов';
  }
  if (data.goal && data.goal.length > 500) {
    errors.goal = 'Цель не должна превышать 500 символов';
  }

  // Валидация detailLevel
  if (!data.detailLevel || !DETAIL_LEVELS.includes(data.detailLevel)) {
    errors.detailLevel = 'Выберите допустимый уровень детализации';
  }

  // Валидация strongSide (опциональное)
  if (data.strongSide && data.strongSide.length > 500) {
    errors.strongSide = 'Сильная сторона не должна превышать 500 символов';
  }

  // Валидация weakSide (опциональное)
  if (data.weakSide && data.weakSide.length > 500) {
    errors.weakSide = 'Слабая сторона не должна превышать 500 символов';
  }

  // Валидация analysisType
  const validAnalysisTypes = ['РЫНОК', 'КОНКУРЕНТЫ', 'ЦА', 'КАНАЛЫ', 'SWOT'];
  if (!data.analysisType || !validAnalysisTypes.includes(data.analysisType)) {
    errors.analysisType = 'Выберите допустимый тип анализа';
  }

  return {
    valid: Object.keys(errors).length === 0,
    errors,
  };
}

Миграция со старого API

Если у вас есть код, использующий старые поля, необходимо обновить его следующим образом:

Старый формат (больше не работает):

{
  "product": "Разработка мобильных приложений",
  "location": "Алматы, Казахстан",
  "client": "B2B клиенты",
  "differentiator": "Быстрая разработка за 2 недели",
  "analysisType": "РЫНОК"
}

Новый формат:

{
  "businessNiche": "Разработка программного обеспечения",
  "product": "Разработка мобильных приложений",
  "targetAudience": "B2B клиенты, технологические компании, стартапы",
  "region": "Алматы",
  "goal": "Увеличить количество клиентов на 50% за следующие 6 месяцев",
  "detailLevel": "СТАНДАРТНО",
  "strongSide": "Быстрая разработка за 2 недели, опытная команда",
  "weakSide": "",
  "analysisType": "РЫНОК"
}

Маппинг старых полей на новые:

Старое поле Новое поле(я) Примечание
location region Только название города из списка
client targetAudience Более детальное описание (свободный текст)
differentiator businessNiche, strongSide, weakSide Разделено на несколько полей для лучшего анализа

Обработка ошибок валидации

При ошибках валидации API возвращает следующий формат:

{
  "success": false,
  "message": "Ошибка валидации",
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Ошибка валидации входных данных",
    "details": {
      "businessNiche": "Поле 'businessNiche' должно содержать от 3 до 200 символов",
      "region": "Поле 'region' должно быть одним из допустимых городов Казахстана",
      "detailLevel": "Поле 'detailLevel' должно быть одним из: КРАТКО, СТАНДАРТНО, ПОДРОБНО"
    }
  }
}

Важные замечания

  1. Регистр важен: Значения region, detailLevel и analysisType чувствительны к регистру. Используйте точные значения из списка допустимых.

  2. Все новые поля передаются в OpenAI: Все указанные поля включаются в контекст для генерации анализа, что улучшает качество и релевантность результатов.

  3. Уровень детализации влияет на результат: Выбор detailLevel напрямую влияет на объем и глубину генерируемого анализа.

  4. Опциональные поля улучшают анализ: Хотя strongSide и weakSide опциональны, их указание помогает AI лучше понять бизнес и дать более точные рекомендации.

  5. Обратная совместимость: Старые поля больше не поддерживаются. Необходимо обновить все клиентские приложения.


Поддержка

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

  • analysisId (если есть)
  • Время запроса
  • Описание проблемы
  • Код ошибки (если есть)
  • Пример запроса (без чувствительных данных)