Feature flags API
Feature flag — это удаленный переключатель со свойствами, которые SDK считывает для каждого устройства. Этот API управляет флагами приложения: те же операции, что и в разделе Audience → Feature Flags в Control Panel. Чтобы считывать флаги на сайте или в мобильном приложении, используйте Web SDK, Android SDK или iOS SDK.
Базовый URL
Anchor link tohttps://rpc-api.svc-nue.pushwoosh.comВсе конечные точки обслуживаются по HTTPS. Запросы и ответы используют application/json.
Аутентификация
Anchor link toКаждый запрос должен содержать заголовок Authorization с вашим токеном Server API:
Authorization: Api YOUR_API_TOKENДля чтения флагов нужен доступ к приложению. Для создания и изменения — право на управление им.
Соглашения
Anchor link to- Именование полей: тела запросов принимают
lowerCamelCaseилиsnake_case. В ответах используетсяsnake_case, как в объекте флага. - Проценты задаются в базисных пунктах:
percent_bpот0до10000, где2000— это 20%. - Версии: у каждого флага есть
version.Update,SetRulePercentиReshuffleпринимают версию, прочитанную вами последней, и завершаются ошибкойVERSION_CONFLICT, если флаг с тех пор изменился, поэтому одновременные правки никогда не перезаписывают друг друга. Прочитайте флаг заново и повторите запрос. - Статусы:
active,killedилиarchived.Kill,Unkill,ArchiveиRestoreменяют только статус и не принимают версию.
Конечные точки
Anchor link toУ каждой конечной точки REST есть MCP-инструмент с теми же параметрами:
| Метод | Путь | Описание | MCP-инструмент |
|---|---|---|---|
GET | /api/applications/{application_code}/feature_flags | Получить список флагов приложения | list_feature_flags |
GET | /api/applications/{application_code}/feature_flags/{key} | Получить один флаг | get_feature_flag |
POST | /api/applications/{application_code}/feature_flags | Создать флаг | create_feature_flag |
POST | /api/applications/{application_code}/feature_flags/{key} | Заменить название, описание, свойства и правила | update_feature_flag |
POST | /api/applications/{application_code}/feature_flags/{key}/rules/{rule_id}/percent | Изменить охват одного правила | set_feature_flag_rule_percent |
POST | /api/applications/{application_code}/feature_flags/{key}/kill | Выключить флаг для всех | kill_feature_flag |
POST | /api/applications/{application_code}/feature_flags/{key}/unkill | Снова включить выключенный флаг | unkill_feature_flag |
POST | /api/applications/{application_code}/feature_flags/{key}/archive | Архивировать флаг | archive_feature_flag |
POST | /api/applications/{application_code}/feature_flags/{key}/restore | Восстановить архивированный флаг | restore_feature_flag |
POST | /api/applications/{application_code}/feature_flags/{key}/reshuffle | Выбрать новую выборку пользователей | reshuffle_feature_flag |
GET | /api/applications/{application_code}/feature_flags/{key}/history | Получить список изменений флага | list_feature_flag_history |
Все конечные точки, кроме List и History, возвращают { "flag": { ... } } — объект флага после выполнения операции.
Получение списка
Anchor link toGET /api/applications/{application_code}/feature_flags
Запрос принимает следующие параметры:
| Параметр | Где | Тип | Описание |
|---|---|---|---|
application_code | path | string | Код приложения. |
status | query | string | Необязательный. active, killed или archived. Не указывайте, чтобы получить все флаги. |
Возвращает { "flags": [ ... ] } — массив объектов флага.
Получение
Anchor link toGET /api/applications/{application_code}/feature_flags/{key}
Возвращает один флаг с его свойствами, правилами и текущей version.
Создание
Anchor link toСоздает активный флаг. Сервер генерирует rule_id каждого правила.
POST /api/applications/{application_code}/feature_flags
Тело запроса содержит следующие поля:
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
key | string | Да | Соответствует ^[A-Za-z0-9_.-]{1,58}$. Уникален в приложении с учетом архивированных флагов, сравнивается без учета регистра. Изменить позже нельзя. |
name | string | Нет | Отображаемое название, до 255 символов. |
description | string | Нет | Описание. |
properties | массив объектов свойства | Нет | До 50 свойств. |
defaults | object | Да, если есть свойства | Значение каждого свойства для устройств, у которых флаг выключен, с ключами по ключу свойства. Каждое значение должно соответствовать типу свойства. |
rules | массив объектов правила | Нет | Упорядоченные правила, до 10. Решение принимает первое правило, сегмент которого совпадает с устройством. |
Пример запроса
Anchor link to{ "key": "new_checkout", "name": "New checkout", "properties": [ { "key": "button_color", "type": "string" }, { "key": "show_apple_pay", "type": "boolean" } ], "defaults": { "button_color": "blue", "show_apple_pay": false }, "rules": [ { "name": "Beta testers", "filter_code": "XXXXX-XXXXX", "percent_bp": 10000, "overrides": { "button_color": "green", "show_apple_pay": true } }, { "name": "Everyone else", "filter_code": "", "percent_bp": 2000, "overrides": { "button_color": "orange" } } ]}Обновление
Anchor link toЗаменяет название, описание, свойства, значения по умолчанию и правила флага. Статус здесь никогда не меняется. Отправляйте все поля, а не только измененные.
POST /api/applications/{application_code}/feature_flags/{key}
Принимает то же тело, что и Создание, без key, плюс version из последнего чтения. Сохраняйте rule_id каждого существующего правила. Правило без rule_id создается как новое. Тип свойства нельзя изменить после создания свойства.
Изменение процента правила
Anchor link toИзменяет охват одного правила. Пользователи, у которых флаг уже включен, сохраняют его при увеличении процента.
POST /api/applications/{application_code}/feature_flags/{key}/rules/{rule_id}/percent
{ "percentBp": 5000, "version": 3 }Выключение и повторное включение
Anchor link toPOST .../feature_flags/{key}/kill выключает флаг для всех устройств, которые после этого получают значения свойств по умолчанию. Правила и свойства сохраняются.
POST .../feature_flags/{key}/unkill снова включает выключенный флаг с прежними правилами.
Оба запроса принимают пустое тело {}.
Архивация и восстановление
Anchor link toPOST .../feature_flags/{key}/archive прекращает отправку флага на устройства. Архивированный флаг не учитывается в лимите флагов на приложение по тарифу, а его ключ остается зарезервированным.
POST .../feature_flags/{key}/restore возвращает архивированный флаг в статусе killed, поэтому он никогда не включается сам. Вызовите unkill, чтобы снова раскатить его.
Оба запроса принимают пустое тело {}.
Перемешивание
Anchor link toРаспределяет каждого пользователя в новый бакет, поэтому те же проценты выбирают другую выборку пользователей. Часть пользователей, у которых флаг включен, теряет его, а другие получают.
POST /api/applications/{application_code}/feature_flags/{key}/reshuffle
{ "confirm": true, "version": 3 }confirm должен быть true. Иначе запрос завершается ошибкой CONFIRM_REQUIRED.
История изменений
Anchor link toВозвращает изменения флага, начиная с самых новых: кто внес каждое изменение, когда и какие поля изменились. Как и для Get, нужен доступ к приложению. Если приложение или флаг не существует, возвращается 404.
GET /api/applications/{application_code}/feature_flags/{key}/history
Запрос принимает следующие параметры:
| Параметр | Где | Тип | Описание |
|---|---|---|---|
application_code | path | string | Код приложения. |
key | path | string | Ключ флага. |
page | query | integer | Необязательный. Номер страницы, начиная с 0. |
per_page | query | integer | Необязательный. Количество записей на странице: по умолчанию 20, не больше 100. |
Возвращает { "entries": [ ... ], "total": N }, где total — количество записей на всех страницах. Каждая запись содержит следующие поля:
| Поле | Тип | Описание |
|---|---|---|
version | integer | Версия флага, которая получилась в результате этого изменения. |
action | string | create, update, set_percent, kill, unkill, archive, restore или reshuffle. |
user_id | string | ID пользователя Control Panel, который внес изменение. 0 для изменения, сделанного с API-токеном или сервисом Pushwoosh. |
user_email | string | Email этого пользователя. Пустое значение, если пользователь удален или user_id равен 0. |
by_api_token | boolean | true, если изменение сделано с API-токеном. false для изменения, сделанного пользователем или сервисом Pushwoosh. |
api_token_name | string | Название API-токена на момент изменения. Сохраняется после удаления токена. Пустое значение, если у токена нет названия или by_api_token равен false. |
created | string | Время изменения, RFC 3339. |
flag | Объект feature flag | Флаг после изменения. |
changes | array | Поля, которые отличаются от предыдущей версии. Пусто для create и reshuffle, а также для самой старой записи флага, созданного до начала записи истории, потому что более ранней версии для сравнения нет. |
Каждый элемент changes содержит field, before и after. В before и after значения закодированы как JSON-строки, поэтому строковое значение приходит в кавычках. field принимает следующие значения:
field | Что изменилось |
|---|---|
name, description, status | Поле флага с этим именем. |
properties | Свойства и их значения по умолчанию. |
rules[<rule_id>] | Одно правило. Для добавленного правила before пустое. Для удаленного правила after пустое. |
rules.order | Порядок правил. |
Пример ответа
Anchor link to{ "entries": [ { "version": 4, "action": "set_percent", "user_id": "12345", "user_email": "owner@example.com", "by_api_token": false, "api_token_name": "", "created": "2026-10-14T09:30:00Z", "flag": { "key": "new_checkout", "status": "active", "version": 4 }, "changes": [ { "field": "rules[r_1a2b3c4d]", "before": "{\"rule_id\":\"r_1a2b3c4d\",\"name\":\"Beta testers\",\"filter_code\":\"XXXXX-XXXXX\",\"percent_bp\":2000,\"overrides\":{\"button_color\":\"green\"}}", "after": "{\"rule_id\":\"r_1a2b3c4d\",\"name\":\"Beta testers\",\"filter_code\":\"XXXXX-XXXXX\",\"percent_bp\":5000,\"overrides\":{\"button_color\":\"green\"}}" } ] } ], "total": 4}Объект flag в примере сокращен. История записывается для изменений начиная с 13 октября 2026 года. Для флага без записанных изменений записи не возвращаются.
Чтение флагов для устройства
Anchor link toSDK считывают флаги через отдельную конечную точку. Вызывать ее не нужно, если вы используете Web SDK, Android SDK или iOS SDK: они сами выбирают хост и кешируют ответ.
POST https://api.pushwoosh.com/api/v2/device-api/getFeatureFlags
Тело запроса содержит следующие поля:
| Поле | Тип | Описание |
|---|---|---|
application | string | Код приложения. |
hwid | string | HWID устройства. |
etag | string | Необязательный. etag последнего ответа, который есть у устройства. |
Ответ содержит следующие поля:
| Поле | Тип | Описание |
|---|---|---|
flags | object | Флаги с ключами по ключу флага. У каждого есть enabled, rule_id и properties. rule_id равен default, если ни одно правило не совпало, и пуст для выключенного флага. Архивированные флаги не включаются. |
etag | string | Передайте его в следующем запросе. |
not_modified | boolean | true, если отправленный etag актуален. Тогда flags не передается, и устройство сохраняет свою копию. |
partial | boolean | true, если сегменты устройства не удалось сопоставить вовремя. Не кешируйте этот ответ. |
На тарифе без feature flags ответ пустой.
Объекты
Anchor link toОбъект feature flag
Anchor link toКаждая конечная точка возвращает флаг в таком виде:
| Поле | Тип | Описание |
|---|---|---|
application_code | string | Приложение, к которому относится флаг. |
key | string | Ключ флага. |
name | string | Отображаемое название. |
description | string | Описание. |
status | string | active, killed или archived. |
properties | массив объектов свойства | Свойства флага. |
defaults | object | Значение каждого свойства для устройств, у которых флаг выключен. |
rules | массив объектов правила | Упорядоченные правила. |
version | integer | Передавайте его обратно в Update, SetRulePercent и Reshuffle. |
created | string | Время создания, RFC 3339. |
updated | string | Время последнего изменения, RFC 3339. |
last_modified_by_user_id | string | Пользователь Control Panel, последним изменивший флаг. 0, если последнее изменение сделано с API-токеном или сервисом Pushwoosh. |
Объект свойства
Anchor link toСвойство описывает одно значение, которое SDK считывает из флага:
| Поле | Тип | Описание |
|---|---|---|
key | string | Соответствует ^[A-Za-z0-9_]{1,64}$, уникален в пределах флага. |
type | string | string, number, boolean или json. Нельзя изменить после создания свойства. |
Объект правила
Anchor link toПравило определяет, у кого флаг включен и с какими значениями:
| Поле | Тип | Описание |
|---|---|---|
rule_id | string | Генерируется сервером: r_ и 8 шестнадцатеричных цифр, не меняется при обновлениях. Для нового правила оставьте пустым. |
name | string | Название правила. |
filter_code | string | Сегмент, которому должно соответствовать устройство. Пустое значение совпадает с любым устройством. Сегмент может содержать только условия по тегам, местоположению, приложению и спискам. |
percent_bp | integer | Доля подходящих пользователей, у которых флаг включен, 0–10000. Устройство, совпавшее с сегментом, останавливается на этом правиле, даже если не попадает в процент. |
overrides | object | Значения свойств, которые заменяют значения по умолчанию для устройств, у которых это правило включает флаг, с ключами по ключу свойства. |
Ошибки
Anchor link toОтклоненный запрос возвращает один из следующих HTTP-кодов состояния:
| HTTP-статус | Значение |
|---|---|
400 Bad Request | Запрос некорректен (field_violations) либо состояние флага или тариф его не допускают (Type). Форматы тела и причины см. ниже. |
401 Unauthorized | Заголовок Authorization отсутствует или токен недействителен. |
403 Forbidden | Токен не может управлять приложением, или приложение системное. |
404 Not Found | Приложение или флаг не существует. |
409 Conflict | Другой запрос в этот момент изменяет тот же флаг. Повторите запрос. |
500 Internal Server Error | Непредвиденный сбой сервера. Тело: {"message": "Sorry, an unexpected error occurred"}. |
Некорректный запрос возвращает 400 со списком нарушений полей. Каждое нарушение указывает поле, причину и аргументы причины:
{ "code": 3, "message": "validation failed", "details": [ { "@type": "type.googleapis.com/pushwoosh.rpc.errors.v3.BadRequest", "field_violations": [ { "field": "key", "description": "a feature flag with this key already exists in the application", "reason": "KEY_TAKEN", "args": { "key": "new_checkout" } } ] } ]}Запрос, который не допускают состояние флага или тариф, возвращает 400 с одним невыполненным предусловием. Его поля Type и Description пишутся с заглавной буквы:
{ "code": 9, "message": "precondition failed", "details": [ { "@type": "type.googleapis.com/pushwoosh.rpc.errors.v3.FailedPrecondition", "Type": "VERSION_CONFLICT", "Description": "feature flag was changed: version 3 was sent, the current one is 4" } ]}reason нарушения поля и Type невыполненного предусловия принимают следующие значения:
| Причина | Чем вызвана |
|---|---|
KEY_INVALID | Ключ не соответствует ^[A-Za-z0-9_.-]{1,58}$. |
KEY_TAKEN | Этот ключ уже есть у другого флага приложения, включая архивированные. |
TEXT_INVALID | Название или описание слишком длинное или содержит запрещенные символы. |
PROPERTIES_LIMIT | Больше 50 свойств. |
PROPERTY_KEY_INVALID | Ключ свойства некорректен или повторяется. |
PROPERTY_TYPE_INVALID | Тип свойства не string, number, boolean или json. |
PROPERTY_TYPE_IMMUTABLE | Запрос меняет тип существующего свойства. |
VALUE_INVALID | Значение по умолчанию или переопределение отсутствует, не соответствует типу свойства или вложено глубже 5 уровней. |
PROPERTIES_TOO_LARGE | Значения свойств флага превышают 10 000 байт. |
RULES_LIMIT | Больше 10 правил. |
RULE_NOT_FOUND | rule_id не относится ни к одному правилу флага. |
PERCENT_INVALID | percent_bp вне диапазона 0–10000. |
OVERRIDE_UNKNOWN_PROPERTY | Переопределение указывает свойство, которого у флага нет. |
SEGMENT_NOT_FOUND | Сегмент правила не существует или принадлежит другому приложению. |
INVALID_SEGMENT_TYPE | В сегменте правила есть условие, которое флаги не могут вычислить: событие, статический, внешний, последнее обновление или лучшее время отправки. |
FLAG_DEPENDENCY | В сегменте правила есть условие по feature flag, а флаг не может зависеть от другого флага. Возвращается Create, Update и Restore с кодом сегмента в filter_code. |
CONFIRM_REQUIRED | Reshuffle отправлен без confirm: true. |
TAG_CONFLICT | В аккаунте есть пользовательский тег с именем PW_FF_ и ключом флага. |
FEATURE_FLAGS_NOT_ALLOWED | Тариф аккаунта не включает feature flags. |
FLAGS_LIMIT | В приложении уже столько неархивированных флагов, сколько допускает тариф. |
VERSION_CONFLICT | Флаг изменился с момента отправленной вами version. |
PAYLOAD_TOO_LARGE | Флаги приложения заняли бы больше 64 КБ в ответе одному устройству. |
STATUS_CONFLICT | Статус не допускает операцию, например выключение архивированного флага. |