diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml
index 2d470c8f2f0..c5b00f59f4f 100644
--- a/.generator/schemas/v2/openapi.yaml
+++ b/.generator/schemas/v2/openapi.yaml
@@ -19568,10 +19568,14 @@ components:
- CONTAINER
- CALLOUTVALUE
Condition:
- description: Targeting condition details.
+ description: |-
+ Targeting condition details. A condition is either an inline
+ predicate with `operator`, `attribute`, and `value`, or a reference to a
+ saved filter with `saved_filter_id`. The inline fields are omitted for saved-filter
+ references.
properties:
attribute:
- description: The user or request attribute to evaluate.
+ description: The user or request attribute to evaluate. Omitted for saved-filter references.
example: "country"
type: string
created_at:
@@ -19586,13 +19590,19 @@ components:
type: string
operator:
$ref: "#/components/schemas/ConditionOperator"
+ saved_filter_id:
+ description: The ID of the saved filter referenced by this condition, or null for inline conditions.
+ example: "550e8400-e29b-41d4-a716-446655440090"
+ format: uuid
+ nullable: true
+ type: string
updated_at:
description: The timestamp when the condition was last updated.
example: "2024-01-01T12:00:00Z"
format: date-time
type: string
value:
- description: Values used by the selected operator.
+ description: Values used by the selected operator. Omitted for saved-filter references.
example: ["US", "CA"]
items:
description: Target value for the selected operator.
@@ -19600,9 +19610,6 @@ components:
type: array
required:
- id
- - operator
- - attribute
- - value
- created_at
- updated_at
type: object
@@ -19633,25 +19640,32 @@ components:
- IS_NULL
- EQUALS
ConditionRequest:
- description: Condition request payload for targeting rules.
+ description: |-
+ Condition request payload for targeting rules. A condition is either an inline
+ predicate with `operator`, `attribute`, and `value`, or a reference to a
+ saved filter with `saved_filter_id`. The two shapes are mutually exclusive.
properties:
attribute:
- description: The user or request attribute to evaluate.
+ description: The user or request attribute to evaluate. Required for inline conditions; omit when `saved_filter_id` is set.
example: "user_tier"
type: string
operator:
$ref: "#/components/schemas/ConditionOperator"
+ saved_filter_id:
+ description: |-
+ The ID of a saved filter to reference as this condition. Mutually exclusive
+ with `operator`, `attribute`, and `value`. When set, the saved filter's
+ targeting rules are evaluated in place of an inline predicate.
+ example: "550e8400-e29b-41d4-a716-446655440090"
+ format: uuid
+ type: string
value:
- description: Values used by the selected operator.
+ description: Values used by the selected operator. Required for inline conditions; omit when `saved_filter_id` is set.
example: ["premium", "enterprise"]
items:
description: Target value for the selected operator.
type: string
type: array
- required:
- - operator
- - attribute
- - value
type: object
ConfigCatCredentials:
description: The definition of the `ConfigCatCredentials` object.
diff --git a/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.java b/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.java
index ba79c235ada..2e5ec9610b2 100644
--- a/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.java
+++ b/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.java
@@ -73,6 +73,9 @@ public static void main(String[] args) {
new ConditionRequest()
.attribute("user_tier")
.operator(ConditionOperator.ONE_OF)
+ .savedFilterId(
+ UUID.fromString(
+ "550e8400-e29b-41d4-a716-446655440090"))
.value(
Arrays.asList("premium", "enterprise"))))))
.type(AllocationType.FEATURE_GATE)
diff --git a/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.java b/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.java
index eb0d514fc58..4feb3f0660f 100644
--- a/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.java
+++ b/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.java
@@ -75,6 +75,9 @@ public static void main(String[] args) {
new ConditionRequest()
.attribute("user_tier")
.operator(ConditionOperator.ONE_OF)
+ .savedFilterId(
+ UUID.fromString(
+ "550e8400-e29b-41d4-a716-446655440090"))
.value(
Arrays.asList(
"premium", "enterprise"))))))
diff --git a/src/main/java/com/datadog/api/client/v2/model/Condition.java b/src/main/java/com/datadog/api/client/v2/model/Condition.java
index b473d63a07b..96445b1835b 100644
--- a/src/main/java/com/datadog/api/client/v2/model/Condition.java
+++ b/src/main/java/com/datadog/api/client/v2/model/Condition.java
@@ -20,13 +20,19 @@
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
+import org.openapitools.jackson.nullable.JsonNullable;
-/** Targeting condition details. */
+/**
+ * Targeting condition details. A condition is either an inline predicate with operator
+ * , attribute, and value, or a reference to a saved filter with
+ * saved_filter_id. The inline fields are omitted for saved-filter references.
+ */
@JsonPropertyOrder({
Condition.JSON_PROPERTY_ATTRIBUTE,
Condition.JSON_PROPERTY_CREATED_AT,
Condition.JSON_PROPERTY_ID,
Condition.JSON_PROPERTY_OPERATOR,
+ Condition.JSON_PROPERTY_SAVED_FILTER_ID,
Condition.JSON_PROPERTY_UPDATED_AT,
Condition.JSON_PROPERTY_VALUE
})
@@ -46,29 +52,25 @@ public class Condition {
public static final String JSON_PROPERTY_OPERATOR = "operator";
private ConditionOperator operator;
+ public static final String JSON_PROPERTY_SAVED_FILTER_ID = "saved_filter_id";
+ private JsonNullable savedFilterId = JsonNullable.undefined();
+
public static final String JSON_PROPERTY_UPDATED_AT = "updated_at";
private OffsetDateTime updatedAt;
public static final String JSON_PROPERTY_VALUE = "value";
- private List value = new ArrayList<>();
+ private List value = null;
public Condition() {}
@JsonCreator
public Condition(
- @JsonProperty(required = true, value = JSON_PROPERTY_ATTRIBUTE) String attribute,
@JsonProperty(required = true, value = JSON_PROPERTY_CREATED_AT) OffsetDateTime createdAt,
@JsonProperty(required = true, value = JSON_PROPERTY_ID) UUID id,
- @JsonProperty(required = true, value = JSON_PROPERTY_OPERATOR) ConditionOperator operator,
- @JsonProperty(required = true, value = JSON_PROPERTY_UPDATED_AT) OffsetDateTime updatedAt,
- @JsonProperty(required = true, value = JSON_PROPERTY_VALUE) List value) {
- this.attribute = attribute;
+ @JsonProperty(required = true, value = JSON_PROPERTY_UPDATED_AT) OffsetDateTime updatedAt) {
this.createdAt = createdAt;
this.id = id;
- this.operator = operator;
- this.unparsed |= !operator.isValid();
this.updatedAt = updatedAt;
- this.value = value;
}
public Condition attribute(String attribute) {
@@ -77,12 +79,13 @@ public Condition attribute(String attribute) {
}
/**
- * The user or request attribute to evaluate.
+ * The user or request attribute to evaluate. Omitted for saved-filter references.
*
* @return attribute
*/
+ @jakarta.annotation.Nullable
@JsonProperty(JSON_PROPERTY_ATTRIBUTE)
- @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public String getAttribute() {
return attribute;
}
@@ -142,8 +145,9 @@ public Condition operator(ConditionOperator operator) {
*
* @return operator
*/
+ @jakarta.annotation.Nullable
@JsonProperty(JSON_PROPERTY_OPERATOR)
- @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public ConditionOperator getOperator() {
return operator;
}
@@ -155,6 +159,37 @@ public void setOperator(ConditionOperator operator) {
this.operator = operator;
}
+ public Condition savedFilterId(UUID savedFilterId) {
+ this.savedFilterId = JsonNullable.of(savedFilterId);
+ return this;
+ }
+
+ /**
+ * The ID of the saved filter referenced by this condition, or null for inline conditions.
+ *
+ * @return savedFilterId
+ */
+ @jakarta.annotation.Nullable
+ @JsonIgnore
+ public UUID getSavedFilterId() {
+ return savedFilterId.orElse(null);
+ }
+
+ @JsonProperty(JSON_PROPERTY_SAVED_FILTER_ID)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+ public JsonNullable getSavedFilterId_JsonNullable() {
+ return savedFilterId;
+ }
+
+ @JsonProperty(JSON_PROPERTY_SAVED_FILTER_ID)
+ public void setSavedFilterId_JsonNullable(JsonNullable savedFilterId) {
+ this.savedFilterId = savedFilterId;
+ }
+
+ public void setSavedFilterId(UUID savedFilterId) {
+ this.savedFilterId = JsonNullable.of(savedFilterId);
+ }
+
public Condition updatedAt(OffsetDateTime updatedAt) {
this.updatedAt = updatedAt;
return this;
@@ -181,17 +216,21 @@ public Condition value(List value) {
}
public Condition addValueItem(String valueItem) {
+ if (this.value == null) {
+ this.value = new ArrayList<>();
+ }
this.value.add(valueItem);
return this;
}
/**
- * Values used by the selected operator.
+ * Values used by the selected operator. Omitted for saved-filter references.
*
* @return value
*/
+ @jakarta.annotation.Nullable
@JsonProperty(JSON_PROPERTY_VALUE)
- @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public List getValue() {
return value;
}
@@ -260,6 +299,7 @@ public boolean equals(Object o) {
&& Objects.equals(this.createdAt, condition.createdAt)
&& Objects.equals(this.id, condition.id)
&& Objects.equals(this.operator, condition.operator)
+ && Objects.equals(this.savedFilterId, condition.savedFilterId)
&& Objects.equals(this.updatedAt, condition.updatedAt)
&& Objects.equals(this.value, condition.value)
&& Objects.equals(this.additionalProperties, condition.additionalProperties);
@@ -267,7 +307,8 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
- return Objects.hash(attribute, createdAt, id, operator, updatedAt, value, additionalProperties);
+ return Objects.hash(
+ attribute, createdAt, id, operator, savedFilterId, updatedAt, value, additionalProperties);
}
@Override
@@ -278,6 +319,7 @@ public String toString() {
sb.append(" createdAt: ").append(toIndentedString(createdAt)).append("\n");
sb.append(" id: ").append(toIndentedString(id)).append("\n");
sb.append(" operator: ").append(toIndentedString(operator)).append("\n");
+ sb.append(" savedFilterId: ").append(toIndentedString(savedFilterId)).append("\n");
sb.append(" updatedAt: ").append(toIndentedString(updatedAt)).append("\n");
sb.append(" value: ").append(toIndentedString(value)).append("\n");
sb.append(" additionalProperties: ")
diff --git a/src/main/java/com/datadog/api/client/v2/model/ConditionRequest.java b/src/main/java/com/datadog/api/client/v2/model/ConditionRequest.java
index 2b2641dd83a..33875b38685 100644
--- a/src/main/java/com/datadog/api/client/v2/model/ConditionRequest.java
+++ b/src/main/java/com/datadog/api/client/v2/model/ConditionRequest.java
@@ -8,7 +8,6 @@
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -18,11 +17,17 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.UUID;
-/** Condition request payload for targeting rules. */
+/**
+ * Condition request payload for targeting rules. A condition is either an inline predicate with
+ * operator, attribute, and value, or a reference to a saved
+ * filter with saved_filter_id. The two shapes are mutually exclusive.
+ */
@JsonPropertyOrder({
ConditionRequest.JSON_PROPERTY_ATTRIBUTE,
ConditionRequest.JSON_PROPERTY_OPERATOR,
+ ConditionRequest.JSON_PROPERTY_SAVED_FILTER_ID,
ConditionRequest.JSON_PROPERTY_VALUE
})
@jakarta.annotation.Generated(
@@ -35,21 +40,11 @@ public class ConditionRequest {
public static final String JSON_PROPERTY_OPERATOR = "operator";
private ConditionOperator operator;
- public static final String JSON_PROPERTY_VALUE = "value";
- private List value = new ArrayList<>();
-
- public ConditionRequest() {}
+ public static final String JSON_PROPERTY_SAVED_FILTER_ID = "saved_filter_id";
+ private UUID savedFilterId;
- @JsonCreator
- public ConditionRequest(
- @JsonProperty(required = true, value = JSON_PROPERTY_ATTRIBUTE) String attribute,
- @JsonProperty(required = true, value = JSON_PROPERTY_OPERATOR) ConditionOperator operator,
- @JsonProperty(required = true, value = JSON_PROPERTY_VALUE) List value) {
- this.attribute = attribute;
- this.operator = operator;
- this.unparsed |= !operator.isValid();
- this.value = value;
- }
+ public static final String JSON_PROPERTY_VALUE = "value";
+ private List value = null;
public ConditionRequest attribute(String attribute) {
this.attribute = attribute;
@@ -57,12 +52,14 @@ public ConditionRequest attribute(String attribute) {
}
/**
- * The user or request attribute to evaluate.
+ * The user or request attribute to evaluate. Required for inline conditions; omit when
+ * saved_filter_id is set.
*
* @return attribute
*/
+ @jakarta.annotation.Nullable
@JsonProperty(JSON_PROPERTY_ATTRIBUTE)
- @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public String getAttribute() {
return attribute;
}
@@ -82,8 +79,9 @@ public ConditionRequest operator(ConditionOperator operator) {
*
* @return operator
*/
+ @jakarta.annotation.Nullable
@JsonProperty(JSON_PROPERTY_OPERATOR)
- @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public ConditionOperator getOperator() {
return operator;
}
@@ -95,23 +93,51 @@ public void setOperator(ConditionOperator operator) {
this.operator = operator;
}
+ public ConditionRequest savedFilterId(UUID savedFilterId) {
+ this.savedFilterId = savedFilterId;
+ return this;
+ }
+
+ /**
+ * The ID of a saved filter to reference as this condition. Mutually exclusive with operator
+ * , attribute, and value. When set, the saved filter's targeting
+ * rules are evaluated in place of an inline predicate.
+ *
+ * @return savedFilterId
+ */
+ @jakarta.annotation.Nullable
+ @JsonProperty(JSON_PROPERTY_SAVED_FILTER_ID)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
+ public UUID getSavedFilterId() {
+ return savedFilterId;
+ }
+
+ public void setSavedFilterId(UUID savedFilterId) {
+ this.savedFilterId = savedFilterId;
+ }
+
public ConditionRequest value(List value) {
this.value = value;
return this;
}
public ConditionRequest addValueItem(String valueItem) {
+ if (this.value == null) {
+ this.value = new ArrayList<>();
+ }
this.value.add(valueItem);
return this;
}
/**
- * Values used by the selected operator.
+ * Values used by the selected operator. Required for inline conditions; omit when
+ * saved_filter_id is set.
*
* @return value
*/
+ @jakarta.annotation.Nullable
@JsonProperty(JSON_PROPERTY_VALUE)
- @JsonInclude(value = JsonInclude.Include.ALWAYS)
+ @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public List getValue() {
return value;
}
@@ -178,13 +204,14 @@ public boolean equals(Object o) {
ConditionRequest conditionRequest = (ConditionRequest) o;
return Objects.equals(this.attribute, conditionRequest.attribute)
&& Objects.equals(this.operator, conditionRequest.operator)
+ && Objects.equals(this.savedFilterId, conditionRequest.savedFilterId)
&& Objects.equals(this.value, conditionRequest.value)
&& Objects.equals(this.additionalProperties, conditionRequest.additionalProperties);
}
@Override
public int hashCode() {
- return Objects.hash(attribute, operator, value, additionalProperties);
+ return Objects.hash(attribute, operator, savedFilterId, value, additionalProperties);
}
@Override
@@ -193,6 +220,7 @@ public String toString() {
sb.append("class ConditionRequest {\n");
sb.append(" attribute: ").append(toIndentedString(attribute)).append("\n");
sb.append(" operator: ").append(toIndentedString(operator)).append("\n");
+ sb.append(" savedFilterId: ").append(toIndentedString(savedFilterId)).append("\n");
sb.append(" value: ").append(toIndentedString(value)).append("\n");
sb.append(" additionalProperties: ")
.append(toIndentedString(additionalProperties))
diff --git a/src/test/resources/com/datadog/api/client/v2/api/feature_flags.feature b/src/test/resources/com/datadog/api/client/v2/api/feature_flags.feature
index df31d246a42..d8238606bff 100644
--- a/src/test/resources/com/datadog/api/client/v2/api/feature_flags.feature
+++ b/src/test/resources/com/datadog/api/client/v2/api/feature_flags.feature
@@ -90,7 +90,7 @@ Feature: Feature Flags
Given new "CreateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
+ And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
When the request is sent
Then the response status is 202 Accepted - Approval required for this change
@@ -99,7 +99,7 @@ Feature: Feature Flags
Given new "CreateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
+ And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
When the request is sent
Then the response status is 400 Bad Request
@@ -108,7 +108,7 @@ Feature: Feature Flags
Given new "CreateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
+ And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
When the request is sent
Then the response status is 409 Conflict
@@ -117,7 +117,7 @@ Feature: Feature Flags
Given new "CreateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
+ And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
When the request is sent
Then the response status is 201 Created
@@ -126,7 +126,7 @@ Feature: Feature Flags
Given new "CreateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
+ And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}}
When the request is sent
Then the response status is 404 Not Found
@@ -449,7 +449,7 @@ Feature: Feature Flags
Given new "UpdateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
+ And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
When the request is sent
Then the response status is 202 Accepted - Approval required for this change
@@ -458,7 +458,7 @@ Feature: Feature Flags
Given new "UpdateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
+ And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
When the request is sent
Then the response status is 400 Bad Request
@@ -467,7 +467,7 @@ Feature: Feature Flags
Given new "UpdateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
+ And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
When the request is sent
Then the response status is 409 Conflict
@@ -476,7 +476,7 @@ Feature: Feature Flags
Given new "UpdateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
+ And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
When the request is sent
Then the response status is 404 Not Found
@@ -485,6 +485,6 @@ Feature: Feature Flags
Given new "UpdateAllocationsForFeatureFlagInEnvironment" request
And request contains "feature_flag_id" parameter from "REPLACE.ME"
And request contains "environment_id" parameter from "REPLACE.ME"
- And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
+ And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "saved_filter_id": "550e8400-e29b-41d4-a716-446655440090", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]}
When the request is sent
Then the response status is 200 OK