Updates the resolved flag's default variation, strategy, and (optionally) prerequisites in a resolved environment.
const url = 'https://api.featureflip.io/api/v1/orgs/example/projects/example/flags/example/environments/example';const options = { method: 'PUT', headers: {Authorization: '<Authorization>', 'Content-Type': 'application/json'}, body: '{"defaultVariationId":"0197b6a0-6a1b-7d4f-8c2e-3a4b5c6d7e8f","strategy":"PercentageRollout","prerequisites":[{"prerequisiteFlagKey":"checkout-api-enabled","expectedVariationKey":"true"}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://api.featureflip.io/api/v1/orgs/example/projects/example/flags/example/environments/example \ --header 'Authorization: <Authorization>' \ --header 'Content-Type: application/json' \ --data '{ "defaultVariationId": "0197b6a0-6a1b-7d4f-8c2e-3a4b5c6d7e8f", "strategy": "PercentageRollout", "prerequisites": [ { "prerequisiteFlagKey": "checkout-api-enabled", "expectedVariationKey": "true" } ] }'Requires at least Member. A null Prerequisites leaves prerequisites untouched; a non-null list replaces them wholesale.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Body
Section titled “Request Body”Request body for PUT .../flags/{flag}/environments/{env}. Named distinctly from the
dashboard’s own UpdateFlagEnvironmentConfigurationRequest
— see PublicCreateEnvironmentRequest for the schemaId-collision rationale (both
controllers share one Swagger document). Strategy is passed through verbatim to
Strategy
— the existing command validator name-allowlists it (SingleVariation/PercentageRollout/
TargetedRollout or null), so an invalid value surfaces as the handler’s own 400, not a
controller-level guard. A null Prerequisites leaves prerequisites untouched; a
non-null list replaces them wholesale (mirrors UpdateFlagPrerequisitesCommand’s
replace-all semantics).
object
Allowed values: SingleVariation, PercentageRollout, TargetedRollout.
A single prerequisite entry on a flag’s per-environment config. Maps 1:1 onto PrerequisiteDto (read side) and PrerequisiteInput (write side).
object
Example
{ "defaultVariationId": "0197b6a0-6a1b-7d4f-8c2e-3a4b5c6d7e8f", "strategy": "PercentageRollout", "prerequisites": [ { "prerequisiteFlagKey": "checkout-api-enabled", "expectedVariationKey": "true" } ]}Request body for PUT .../flags/{flag}/environments/{env}. Named distinctly from the
dashboard’s own UpdateFlagEnvironmentConfigurationRequest
— see PublicCreateEnvironmentRequest for the schemaId-collision rationale (both
controllers share one Swagger document). Strategy is passed through verbatim to
Strategy
— the existing command validator name-allowlists it (SingleVariation/PercentageRollout/
TargetedRollout or null), so an invalid value surfaces as the handler’s own 400, not a
controller-level guard. A null Prerequisites leaves prerequisites untouched; a
non-null list replaces them wholesale (mirrors UpdateFlagPrerequisitesCommand’s
replace-all semantics).
object
Allowed values: SingleVariation, PercentageRollout, TargetedRollout.
A single prerequisite entry on a flag’s per-environment config. Maps 1:1 onto PrerequisiteDto (read side) and PrerequisiteInput (write side).
object
Example
{ "defaultVariationId": "0197b6a0-6a1b-7d4f-8c2e-3a4b5c6d7e8f", "strategy": "PercentageRollout", "prerequisites": [ { "prerequisiteFlagKey": "checkout-api-enabled", "expectedVariationKey": "true" } ]}Request body for PUT .../flags/{flag}/environments/{env}. Named distinctly from the
dashboard’s own UpdateFlagEnvironmentConfigurationRequest
— see PublicCreateEnvironmentRequest for the schemaId-collision rationale (both
controllers share one Swagger document). Strategy is passed through verbatim to
Strategy
— the existing command validator name-allowlists it (SingleVariation/PercentageRollout/
TargetedRollout or null), so an invalid value surfaces as the handler’s own 400, not a
controller-level guard. A null Prerequisites leaves prerequisites untouched; a
non-null list replaces them wholesale (mirrors UpdateFlagPrerequisitesCommand’s
replace-all semantics).
object
Allowed values: SingleVariation, PercentageRollout, TargetedRollout.
A single prerequisite entry on a flag’s per-environment config. Maps 1:1 onto PrerequisiteDto (read side) and PrerequisiteInput (write side).
object
Example
{ "defaultVariationId": "0197b6a0-6a1b-7d4f-8c2e-3a4b5c6d7e8f", "strategy": "PercentageRollout", "prerequisites": [ { "prerequisiteFlagKey": "checkout-api-enabled", "expectedVariationKey": "true" } ]}Responses
Section titled “Responses”No Content
Headers
Section titled “Headers”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Bad Request
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean and next_actions are ADDITIVE optional keys (null → omitted via
the global DefaultIgnoreCondition = WhenWritingNull), so pre-existing error bodies
are byte-for-byte unchanged when they’re absent.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “Headers”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Authentication is required, or the supplied API token is invalid or expired.
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean and next_actions are ADDITIVE optional keys (null → omitted via
the global DefaultIgnoreCondition = WhenWritingNull), so pre-existing error bodies
are byte-for-byte unchanged when they’re absent.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “Headers”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Forbidden
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean and next_actions are ADDITIVE optional keys (null → omitted via
the global DefaultIgnoreCondition = WhenWritingNull), so pre-existing error bodies
are byte-for-byte unchanged when they’re absent.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “Headers”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Not Found
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean and next_actions are ADDITIVE optional keys (null → omitted via
the global DefaultIgnoreCondition = WhenWritingNull), so pre-existing error bodies
are byte-for-byte unchanged when they’re absent.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “Headers”The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.
Rate limit exceeded. Retry after the interval indicated by the Retry-After header.
The frozen public-API error contract. error codes are stable snake_case strings. Wire keys
are frozen snake_case too (error, message, docs_url, fields,
retry_after) — the global camelCase naming policy would otherwise emit
docsUrl/retryAfter, breaking the published spec. !:JsonPropertyName
always wins over the policy, so these are pinned explicitly rather than relying on the
property names already being lowercase for the single-word ones.
did_you_mean and next_actions are ADDITIVE optional keys (null → omitted via
the global DefaultIgnoreCondition = WhenWritingNull), so pre-existing error bodies
are byte-for-byte unchanged when they’re absent.
object
object
object
Example
{ "error": "not_found", "message": "Flag 'new-checkout-flw' was not found in project 'checkout'.", "docs_url": "https://featureflip.io/docs/management-api/errors/not_found", "did_you_mean": [ "new-checkout-flow" ], "next_actions": [ { "method": "GET", "path": "/api/v1/orgs/acme/projects/checkout/flags" } ]}Headers
Section titled “Headers”Number of seconds to wait before retrying the request.
The maximum number of requests permitted per rate-limit window for this caller.
The number of requests remaining in the current rate-limit window.
The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.