Skip to content

Adds a variation to the resolved flag.

POST
/api/v1/orgs/{org}/projects/{project}/flags/{flag}/variations
curl --request POST \
--url https://api.featureflip.io/api/v1/orgs/example/projects/example/flags/example/variations \
--header 'Authorization: <Authorization>' \
--header 'Content-Type: application/json' \
--data '{ "key": "express", "name": "Express Checkout", "value": "express", "description": "One-click express checkout variant." }'

Requires at least Member. Re-fetches the flag via GetFeatureFlagQuery and locates the new variation by the id returned from AddVariationCommand so the response reflects exactly what was persisted.

org
required
string
project
required
string
flag
required
string

Request body for POST /api/v1/orgs/{org}/projects/{project}/flags/{flag}/variations. Named distinctly from the dashboard’s own AddVariationRequest — see PublicCreateEnvironmentRequest for the schemaId-collision rationale (both controllers share one Swagger document).

object
key
string
nullable
name
string
nullable
value
string
nullable
description
string
nullable
Example
{
"key": "express",
"name": "Express Checkout",
"value": "express",
"description": "One-click express checkout variant."
}

Created

Media typeapplication/json

A single variation on a flag, as returned in Variations.

object
id
string format: uuid
key
string
nullable
name
string
nullable
value
string
nullable
description
string
nullable
_actions

Capability hints: which operations the authenticated caller may perform on this resource, each with allowed + optional reason. Computed from the caller’s role and the resource’s state. Injected at runtime; safe to ignore. Present only on top-level resource responses — nested occurrences (e.g. a rule inside a targeting-config response) do not carry it.

object
key
additional properties

One entry in a resource’s _actions block: may the caller perform it, and if not, why.

object
allowed
boolean
reason
string
nullable
Example
{
"id": "0197b6a0-6a1b-7d4f-8c2e-2f3a4b5c6d7e",
"key": "true",
"name": "Enabled",
"value": "true",
"description": "Serve the new checkout."
}
X-RateLimit-Limit
integer

The maximum number of requests permitted per rate-limit window for this caller.

X-RateLimit-Remaining
integer

The number of requests remaining in the current rate-limit window.

X-RateLimit-Reset
integer

The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.

Bad Request

Media typeapplication/json

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
error
string
nullable
message
string
nullable
docs_url
string
nullable
fields
object
key
additional properties
Array<string>
retry_after
integer format: int32
nullable
did_you_mean
Array<string>
nullable
next_actions
Array<object>
nullable
object
method
string
nullable
path
string
nullable
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"
}
]
}
X-RateLimit-Limit
integer

The maximum number of requests permitted per rate-limit window for this caller.

X-RateLimit-Remaining
integer

The number of requests remaining in the current rate-limit window.

X-RateLimit-Reset
integer

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.

Media typeapplication/json

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
error
string
nullable
message
string
nullable
docs_url
string
nullable
fields
object
key
additional properties
Array<string>
retry_after
integer format: int32
nullable
did_you_mean
Array<string>
nullable
next_actions
Array<object>
nullable
object
method
string
nullable
path
string
nullable
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"
}
]
}
X-RateLimit-Limit
integer

The maximum number of requests permitted per rate-limit window for this caller.

X-RateLimit-Remaining
integer

The number of requests remaining in the current rate-limit window.

X-RateLimit-Reset
integer

The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.

Forbidden

Media typeapplication/json

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
error
string
nullable
message
string
nullable
docs_url
string
nullable
fields
object
key
additional properties
Array<string>
retry_after
integer format: int32
nullable
did_you_mean
Array<string>
nullable
next_actions
Array<object>
nullable
object
method
string
nullable
path
string
nullable
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"
}
]
}
X-RateLimit-Limit
integer

The maximum number of requests permitted per rate-limit window for this caller.

X-RateLimit-Remaining
integer

The number of requests remaining in the current rate-limit window.

X-RateLimit-Reset
integer

The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.

Not Found

Media typeapplication/json

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
error
string
nullable
message
string
nullable
docs_url
string
nullable
fields
object
key
additional properties
Array<string>
retry_after
integer format: int32
nullable
did_you_mean
Array<string>
nullable
next_actions
Array<object>
nullable
object
method
string
nullable
path
string
nullable
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"
}
]
}
X-RateLimit-Limit
integer

The maximum number of requests permitted per rate-limit window for this caller.

X-RateLimit-Remaining
integer

The number of requests remaining in the current rate-limit window.

X-RateLimit-Reset
integer

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.

Media typeapplication/json

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
error
string
nullable
message
string
nullable
docs_url
string
nullable
fields
object
key
additional properties
Array<string>
retry_after
integer format: int32
nullable
did_you_mean
Array<string>
nullable
next_actions
Array<object>
nullable
object
method
string
nullable
path
string
nullable
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"
}
]
}
Retry-After
integer

Number of seconds to wait before retrying the request.

X-RateLimit-Limit
integer

The maximum number of requests permitted per rate-limit window for this caller.

X-RateLimit-Remaining
integer

The number of requests remaining in the current rate-limit window.

X-RateLimit-Reset
integer

The UTC time at which the current rate-limit window resets, as a Unix timestamp in seconds.