Gets a feature flag in the resolved project by key or id.
const url = 'https://api.featureflip.io/api/v1/orgs/example/projects/example/flags/example';const options = {method: 'GET', headers: {Authorization: '<Authorization>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.featureflip.io/api/v1/orgs/example/projects/example/flags/example \ --header 'Authorization: <Authorization>'Authorizations
Section titled “ Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “ Path Parameters ”Header Parameters
Section titled “ Header Parameters ”Optional. An ETag of this resource. The response is 200 only if it is still the current one; otherwise 412 precondition_failed. * or no header always reads.
Responses
Section titled “ Responses ”OK
Public detail representation of a feature flag, returned by
GET .../flags/{flag} and the body of a successful create. Drops internal/dashboard-only
fields present on FeatureFlagDto — notably ProjectId (implicit in the
route) and Staleness (an internal analytics signal, not part of the public contract).
EffectiveExpiresAtUtc is when the flag counts as past expiry, from its own ExpiresAtUtc
or its project’s default lifetime; ExpirySource says which (explicit / project-default),
both null when neither applies.
object
Allowed values: Boolean, String, Number, Json.
A single variation on a flag, as returned in Variations.
object
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
One entry in a resource’s _actions block: may the caller perform it, and if not, why.
object
A flag’s owner as returned on flag reads. Null means the flag is unowned.
object
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
One entry in a resource’s _actions block: may the caller perform it, and if not, why.
object
Example
{ "id": "0197b6a0-5f2a-7c3e-9b4d-1e2f3a4b5c6d", "key": "new-checkout-flow", "name": "New Checkout Flow", "description": "Gates the redesigned checkout experience.", "type": "Boolean", "isArchived": false, "clientSideVisible": false, "tags": [ "checkout", "q3-launch" ], "variations": [ { "id": "0197b6a0-6a1b-7d4f-8c2e-2f3a4b5c6d7e", "key": "true", "name": "Enabled", "value": "true", "description": "Serve the new checkout." }, { "id": "0197b6a0-6a1b-7d4f-8c2e-3a4b5c6d7e8f", "key": "false", "name": "Disabled", "value": "false", "description": "Serve the legacy checkout." } ], "createdAt": "2026-06-01T12:00:00Z", "updatedAt": "2026-06-15T08:30:00Z", "isPermanent": false}Headers
Section titled “ Headers ”Strong ETag of the resource’s whole body as sent to this caller: it changes whenever anything in the body does. Send it back as If-Match on a PUT.
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, next_actions and connection_id 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.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
plan_limit is present only on the plan_limit_reached error: which plan cap the
request would have exceeded, so a client can branch on it without parsing message.
object
object
object
The cap behind a plan_limit_reached error. resource is the capped collection
(projects, environments, flags, webhooks, members);
plan is the plan’s wire name, as GET /api/v1/orgs/{org} returns it; max is
the cap. The environment and flag caps are per project.
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, next_actions and connection_id 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.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
plan_limit is present only on the plan_limit_reached error: which plan cap the
request would have exceeded, so a client can branch on it without parsing message.
object
object
object
The cap behind a plan_limit_reached error. resource is the capped collection
(projects, environments, flags, webhooks, members);
plan is the plan’s wire name, as GET /api/v1/orgs/{org} returns it; max is
the cap. The environment and flag caps are per project.
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.
The resource’s current ETag is not the If-Match one.
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, next_actions and connection_id 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.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
plan_limit is present only on the plan_limit_reached error: which plan cap the
request would have exceeded, so a client can branch on it without parsing message.
object
object
object
The cap behind a plan_limit_reached error. resource is the capped collection
(projects, environments, flags, webhooks, members);
plan is the plan’s wire name, as GET /api/v1/orgs/{org} returns it; max is
the cap. The environment and flag caps are per project.
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, next_actions and connection_id 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.
connection_id is present only on the sso_required error: the organization
requires single sign-on, and this credential didn’t come through its identity provider.
connection_id identifies which SSO connection to sign in with.
plan_limit is present only on the plan_limit_reached error: which plan cap the
request would have exceeded, so a client can branch on it without parsing message.
object
object
object
The cap behind a plan_limit_reached error. resource is the capped collection
(projects, environments, flags, webhooks, members);
plan is the plan’s wire name, as GET /api/v1/orgs/{org} returns it; max is
the cap. The environment and flag caps are per project.
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.