功能开关 API
功能开关是一种带有属性的远程开关,SDK 会为每台设备读取这些属性。此 API 管理应用程序的功能开关,其操作与控制面板中 Audience → Feature Flags 的操作相同。要在网站或移动应用中读取功能开关,请使用 Web SDK、Android SDK 或 iOS SDK。
基础 URL
Anchor link tohttps://rpc-api.svc-nue.pushwoosh.com所有端点都通过 HTTPS 提供服务。请求和响应均使用 application/json。
身份验证
Anchor link to每个请求都必须包含一个 Authorization 标头,其中包含您的 服务器 API 令牌:
Authorization: Api YOUR_API_TOKEN读取功能开关需要拥有该应用程序的访问权限。创建和更改功能开关需要拥有管理该应用程序的权限。
- 字段命名: 请求正文接受
lowerCamelCase或snake_case。响应使用snake_case,与 功能开关对象 中一致。 - 百分比 以基点表示:
percent_bp取值范围为0到10000,其中2000表示 20%。 - 版本: 每个功能开关都带有一个
version。Update、SetRulePercent和Reshuffle接收您上次读取到的版本,如果功能开关在此之后发生了变化,则会失败并返回VERSION_CONFLICT,因此并发编辑永远不会相互覆盖。请重新读取功能开关并重试。 - 状态:
active、killed或archived。Kill、Unkill、Archive和Restore仅更改状态,不接收版本。
每个 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": { ... } },即操作完成后的 功能开关对象。
GET /api/applications/{application_code}/feature_flags
请求接收以下参数:
| 参数 | 位置 | 类型 | 描述 |
|---|---|---|---|
application_code | path | string | 应用代码。 |
status | query | string | 可选。active、killed 或 archived。省略则列出所有功能开关。 |
返回 { "flags": [ ... ] },即由 功能开关对象 组成的数组。
GET /api/applications/{application_code}/feature_flags/{key}
返回单个功能开关及其属性、规则和当前 version。
创建一个 active 状态的功能开关。服务器会为每条规则生成 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" } } ]}替换功能开关的名称、描述、属性、默认值和规则。此处永远不会更改状态。请发送所有字段,而不仅仅是更改过的字段。
POST /api/applications/{application_code}/feature_flags/{key}
接收与 创建 相同但不含 key 的正文,并加上您上次读取到的 version。保留每条现有规则的 rule_id。没有 rule_id 的规则会作为新规则创建。属性创建后,其类型无法更改。
SetRulePercent
Anchor link to更改单条规则的发布比例。比例增大时,已经获得该功能开关的用户会保留它。
POST /api/applications/{application_code}/feature_flags/{key}/rules/{rule_id}/percent
{ "percentBp": 5000, "version": 3 }Kill 和 Unkill
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。如果变更是通过 API 令牌或由 Pushwoosh 服务进行的,则为 0。 |
user_email | string | 该用户的电子邮件地址。如果用户已被删除或 user_id 为 0,则为空。 |
by_api_token | boolean | 如果变更是通过 API 令牌进行的,则为 true。如果变更由用户或 Pushwoosh 服务进行,则为 false。 |
api_token_name | string | 变更发生时 API 令牌的名称。删除令牌后该名称仍会保留。如果令牌没有名称或 by_api_token 为 false,则为空。 |
created | string | 变更时间,RFC 3339 格式。 |
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 对象已做简化。历史记录从 2026 年 10 月 13 日起记录变更。没有已记录变更的功能开关不返回任何条目。
读取设备的功能开关
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;对于已关闭的功能开关,rule_id 为空。已归档的功能开关不包含在内。 |
etag | string | 在下一次请求中发送它。 |
not_modified | boolean | 如果发送的 etag 是最新的,则为 true。此时将省略 flags,设备保留其副本。 |
partial | boolean | 如果未能及时匹配设备的细分,则为 true。请勿缓存此响应。 |
在不包含功能开关的套餐中,响应为空。
功能开关对象
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 | 最后更改该功能开关的控制面板用户。如果最后一次更改是通过 API 令牌或由 Pushwoosh 服务进行的,则为 0。 |
属性对象
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 | 对于此规则开启的设备,用于替换默认值的属性值,以属性键为键。 |
被拒绝的请求会返回以下 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 | 规则细分包含功能开关条件,而功能开关不能依赖另一个功能开关。由 Create、Update 和 Restore 返回,细分代码位于 filter_code 中。 |
CONFIRM_REQUIRED | 发送 Reshuffle 时未带 confirm: true。 |
TAG_CONFLICT | 账户中存在名为 PW_FF_ 后跟功能开关键的自定义标签。 |
FEATURE_FLAGS_NOT_ALLOWED | 账户的套餐不包含功能开关。 |
FLAGS_LIMIT | 应用程序中未归档的功能开关数量已达到套餐允许的上限。 |
VERSION_CONFLICT | 自您发送的 version 以来,功能开关已发生变化。 |
PAYLOAD_TOO_LARGE | 应用程序的功能开关在单台设备的响应中将超过 64 KB。 |
STATUS_CONFLICT | 当前状态不允许该操作,例如关闭已归档的功能开关。 |