Перейти к основному содержимому

Эксперименты - Console API

Получение списка, создание, чтение и обновление эксперимента. Console API авторизует запрос по OAuth2-scope (см. Авторизацию).

к сведению

Интерактивный контракт с try-it-out - в Справочнике API (Swagger). Пошаговый сценарий интеграции - в сквозном сценарии.

Создание эксперимента

Требуемый scope - edit:experiment:create_experiments.

ЭндпоинтЧто делает
POST /experiments/v1Создаёт эксперимент и возвращает его id. Эксперимент появляется в статусе черновика - для запуска вызовите start.

Как создать эксперимент

  1. Получите допустимые значения из справочников - команды, типы участников, списки участников, пресеты метрик. Имена в теле запроса должны совпадать со значениями из справочников.
  2. Соберите тело запроса: обязательные поля и, при необходимости, метрики, сегменты, блок retro или switchback. Полный список полей - в таблице Поля запроса.
  3. Отправьте POST /experiments/v1 с телом в формате JSON.
  4. Сохраните id из ответа - он нужен для запуска, обновления и остановки эксперимента.
  5. Запустите эксперимент методом start.

Тело запроса

ConsoleCreateExperimentRequest - схема тела запроса (JSON). Ниже перечислены все поля с типами и обязательностью.

Где смотреть детали:

Поля запроса

ПараметрТипОбязательностьОписание
titlestringДаНазвание эксперимента.
labelstringДаУникальный текстовый идентификатор эксперимента (например, new_checkout_flow). В отличие от title, задаёт машинно-удобный ключ, а не отображаемое название.
participantTypestringДаLabel типа участника из справочника participantTypes.
groupsConsoleExperimentGroupIn[]ДаСписок групп эксперимента.
teamstringДаКоманда-владелец из справочника teams.
metricPresetsstring[]ДаПресеты метрик из справочника preset-names.
durationintegerУсловноПлановая длительность A/B-фазы в днях. Обязательно для regular и switchback.
retroConsoleRetroInУсловноПараметры ретро-эксперимента. Обязательно для type = "retro".
switchbackConsoleSwitchbackInУсловноПараметры switchback-эксперимента. Обязательно для type = "switchback".
propagateExposureDaysintegerУсловноЧисло дней запоминания exposure. Обязательно при exposure = "days".
typeenum ExperimentTypeНетТип эксперимента. По умолчанию "regular".
statisticalMethodenum StatisticsMethodНетМетод агрегации метрик. По умолчанию "frequentist".
exposureenum ConsoleExposureTypeНетРежим учёта exposure (all / days). По умолчанию "all".
markupScopeTypeenum ExperimentMarkupScopeTypeНетТип разметки: incoming_traffic, event, segment.
allocationTrafficnumberНетДоля трафика эксперимента в процентах.
segmentsConsoleExperimentSegmentIn[]НетСегменты таргетинга.
comparisonsConsoleExperimentComparisonIn[]НетПары групп для сравнения. Если не заданы - строятся автоматически.
goalMetricsConsoleGoalMetricIn[]НетЦелевые метрики.
counterMetricsConsoleCounterMetricIn[]НетКонтрольные (guardrail) метрики.
layerstringНетНазвание слоя.
useHoldoutstringНетНазвание holdout-группы.
allowedUsersstring[]НетПринудительно включённые пользователи.
excludedUsersstring[]НетИсключённые пользователи.
tagsstring[]НетТеги эксперимента.
descriptionstringНетОписание эксперимента.
issueUrlstringНетСсылка на задачу.
startTimestringНетПлановое время старта эксперимента.
cutFirstDayOffsetbooleanНетОбрезать первый неполный день.
experimentOffsetsinteger[]НетДополнительные смещения в днях.
aggregationWindowsinteger[]НетСкользящие окна агрегации.
expectedExposurePlacestringНетМесто или событие ожидаемой экспозиции.
keepMarkingOnStopbooleanНетСохранять marking при остановке.

ExperimentType, StatisticsMethod, ConsoleExposureType, ExperimentMarkupScopeType - справочники значений в Перечислениях.

Лишние поля в теле запроса отклоняются

Схема запроса использует extra=forbid. Любое поле сверх описанных приводит к ошибке валидации. Проверяйте написание имён полей перед отправкой.

Условная обязательность полей

Часть полей обязательна в зависимости от типа эксперимента и модели экспозиции:

УсловиеОбязательное полеСообщение об ошибке
type = "retro"retroretro is required for retro experiments
type = "switchback"switchbackswitchback is required for switchback experiments
type = regular / switchbackdurationduration is required for regular and switchback experiments
exposure = "days"propagateExposureDayspropagateExposureDays is required when exposure=days

Вложенные объекты

Группа (ConsoleExperimentGroupIn):

ПараметрТипОбязательностьПримерОписание
namestringДа"control"Имя группы.
isControlboolДаtrueПризнак контрольной группы.
weightfloatНет50Вес группы. Если не задан, распределяется равномерно.
descriptionstringНет"baseline"Описание группы.
allowedUserslistНет-Пользователи, допущенные в группу.

Сравнение (ConsoleExperimentComparisonIn):

ПараметрТипОбязательностьПримерОписание
controlstringДа"control"Лейбл контрольной группы.
teststringДа"test"Лейбл тестовой группы.

Сегмент (ConsoleExperimentSegmentIn) и условие (ConsoleExperimentConditionIn). Сегмент содержит список условий conditions, условия внутри сегмента объединяются логикой AND:

ПараметрТипОбязательностьПримерОписание
paramstringДа"platform"Лейбл контекст-параметра.
predicatestringДа"eq"Оператор сравнения.
valuestring | list | int | float | boolДа"android"Значение для сравнения.

Целевая метрика (ConsoleGoalMetricIn) и контрольная метрика (ConsoleCounterMetricIn):

ПараметрТипОбязательностьОписание
namestringДаИмя метрики из справочника objective-meta.
breakdownstringНетСрез метрики.
expectedEffectfloatНетОжидаемый эффект (только для ConsoleGoalMetricIn).
maxDeviationfloatНетДопустимое отклонение (только для ConsoleCounterMetricIn).

Объект retro (ConsoleRetroIn)

Объект обязателен для экспериментов с type = "retro".

ПараметрТипОбязательностьПримерОписание
typeenum RetroTypeДа"parent_experiment"Тип ретро-эксперимента.
startDatedateДа"2026-06-01"Дата начала.
endDatedateДа"2026-06-15"Дата окончания. Должна быть в прошлом.
parentExperimentIdint | nullУсловно123ID родительского эксперимента.

RetroType - справочник значений в Перечислениях.

Объект retro проходит следующие валидации:

УсловиеТребованиеСообщение об ошибке
type = "parent_experiment"parentExperimentId обязателенretro.parentExperimentId is required for parent_experiment
type не parent_experimentparentExperimentId запрещёнretro.parentExperimentId is allowed only for parent_experiment
endDate не в прошломдата должна быть в прошломretro.endDate must be in the past

Объект switchback (ConsoleSwitchbackIn)

Объект обязателен для экспериментов с type = "switchback". Все поля обязательны.

ПараметрТипОбязательностьПримерОписание
clusterIdSetNameslistДа-Имена наборов идентификаторов кластеров.
clusterPercentfloatДа50Процент кластеров (0-100).
windowSizeMinutesint > 0Да60Размер окна в минутах.
burnInMinutesint >= 0Да5Прогрев в минутах.
burnOutMinutesint >= 0Да5Остывание в минутах.
strategyenum SwitchbackStrategyДа"DETERMINISTIC_RANDOM"Стратегия распределения.

SwitchbackStrategy - справочник значений в Перечислениях.

Switchback - прогрев и остывание

Прогрев и остывание не должны заполнять всё окно. Сумма burnInMinutes + burnOutMinutes должна быть строго меньше windowSizeMinutes. Иначе запрос отклоняется с ошибкой burnInMinutes + burnOutMinutes must be less than windowSizeMinutes.

Автоматическое поведение

Если вы не передаёте comparisons, Console API строит их автоматически: находит единственную контрольную группу (isControl) и сравнивает с ней каждую тестовую. Отсутствие контрольной группы даёт ошибку MISSING_CONTROL_GROUP, наличие более одной - DUPLICATE_CONTROL_GROUP.

Если вы не задаёте weight, Console API распределяет вес равномерно: 100 // N на каждую из N групп, остаток добавляет к первым группам.

Формирование запроса

URL:

POST https://<host>/experiments/v1

Заголовки:

Authorization: Bearer <ваш_токен>
Content-Type: application/json

Тело запроса:

{
"title": "Новый флоу оформления",
"label": "new_checkout_flow",
"type": "regular",
"participantType": "user_id",
"team": "checkout",
"duration": 14,
"metricPresets": ["core_metrics"],
"groups": [
{ "name": "control", "isControl": true },
{ "name": "test", "isControl": false }
]
}

Пример успешного ответа:

{
"result": {
"id": 12345
}
}

Расшифровка ответа:

ПараметрТипПримерОписание
idint12345Идентификатор созданного эксперимента.

Чтение

Требуемый scope - read:experiment:read_experiments.

ЭндпоинтЧто возвращает
GET /experiments/v1Список экспериментов. Фильтры: statuses, tags, query; пагинация: page, pageLimit.
GET /experiments/v1/{id}Полную конфигурацию одного эксперимента по id.

Используйте чтение для мониторинга после запуска и сверки статуса перед остановкой.

Обновление эксперимента

Требуемый scope - edit:experiment:update_experiments.

ЭндпоинтЧто делает
PATCH /experiments/v1/{id}Частично обновляет эксперимент. Тело запроса - ConsoleUpdateExperimentRequest, ответ - {ok: true}.

Все поля тела - опциональные, обязательных полей нет. Набор полей совпадает с полями создания. Схема использует extra=forbid.

Условная обязательность при обновлении:

УсловиеТребование
type = "retro"требуется retro
type = "switchback"требуется switchback
exposure = "days"требуется propagateExposureDays
к сведению

В отличие от создания, обновление не требует duration для regular- и switchback-экспериментов.

Ограничения после запуска. У запущенного эксперимента (статус In progress) часть полей конфигурации становится недоступной для изменения. Точный перечень заблокированных полей возвращается в ошибке 400 при попытке их изменить.

Пример правки описания и тегов:

{
"description": "Обновлённое описание",
"tags": ["integration", "updated"]
}

Формат ответа и ошибок

Console API возвращает успешный ответ (200) в конверте {result: <schema>}, а ошибку - в конверте {error: SanitizedErrorBody}. Формат общий для всех методов раздела.

Тело ошибки SanitizedErrorBody содержит три обязательных поля:

ПараметрТипПримерОписание
codestring"validation_error"Машиночитаемый код ошибки.
messagestring"duration is required"Текстовое описание ошибки.
request_idstring | null"a1b2c3d4"Идентификатор запроса для диагностики.

Документированные статусы ответа:

СтатусЗначение
200Успешный ответ.
400Ошибка валидации тела запроса.
401Запрос не авторизован.
403Недостаточно прав (scope).
404Эксперимент не найден.
500Внутренняя ошибка сервера.