Skip to content

Lists confidently-dead (or, with `staleness=stale`, stale-or-dead) flags the Featureflip Flag Cleanup Action should remove, cursor-paginated, each with its kill `treatment` (true = keep the on-branch, false = keep the off-branch).

GET
/api/v1/orgs/{org}/projects/{project}/flags/removal-candidates
curl --request GET \
--url https://api.featureflip.io/api/v1/orgs/example/projects/example/flags/removal-candidates \
--header 'Authorization: <Authorization>'

Only flags the staleness engine marks at or above the requested tier via a decisive StuckRolledOut/StuckRolledBack reason are returned; ZeroTraffic/CreatedUnused, cross-env-divergent, and archived flags are omitted (no confident code treatment). The ONLY public projection of staleness.

org
required
string
project
required
string
limit
integer format: int32
cursor
string
staleness
string

Minimum staleness tier to include: dead (default) or stale (includes Stale + Dead). Omitted or any unrecognized value falls back to dead — the safe default never widens silently.

OK

Media typeapplication/json

A page of results plus an opaque cursor for the next page, or null when this is the last page. Wire keys are frozen: items (already lowercase under the camelCase policy) and next_cursor (pinned explicitly — the policy alone would emit nextCursor).

object
items
Array<object>
nullable

One dead flag the Featureflip Flag Cleanup Action should remove, returned by GET .../flags/removal-candidates. Treatment is the kill decision: true → keep the flag’s on-branch, false → keep the off-branch. Status is the flag’s staleness tier ("Stale" or "Dead", never "Active") — lets a caller distinguish the two when ?staleness=stale widens the response to include both tiers. This is the ONLY public projection of staleness — PublicFlagResponse and PublicFlagListItem still omit it by design.

object
key
string
nullable
reason
string
nullable
treatment
boolean
status
string
nullable
next_cursor
string
nullable
Examplegenerated
{
"items": [
{
"key": "example",
"reason": "example",
"treatment": true,
"status": "example"
}
],
"next_cursor": "example"
}
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.

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.