The dashboard is built for a person: click into a project, flip a flag, watch it roll out. That is the right tool when a human is in the loop. It is the wrong tool when the thing that needs to change a flag is a CI job, a deploy script, or an internal admin panel. Those need an API.
Featureflip now has one. The Management API is a REST interface for configuring everything the dashboard configures: projects, environments, feature flags, variations, targeting rules, segments, and SDK keys. It is the automation counterpart to the dashboard, and it is separate from the high-throughput serving path your application already uses to read flags. This post covers what the split means, how to authenticate, and a request-by-request walkthrough from nothing to a live, targeted flag. By the end you will also understand the guarantees (idempotency, a single error shape, visible rate limits) that make it safe to script against in a loop.
Key Takeaways
- The Management API configures Featureflip over REST: projects, environments, flags, variations, targeting, segments, and SDK keys, at base URL
https://api.featureflip.iowith every path under/api/v1.- It is a separate surface from the Evaluation API and SDKs. Use the Management API to write configuration; use an SDK to read flags in your app. Configuration is low-frequency and rich; evaluation is high-throughput and stays on the hot path.
- Authenticate with a bearer token: a Personal Access Token (
ffp_, acts as you) for scripting, or a Service Token (ffs_, a machine identity scoped to one organization) for CI and shared automation.- Built for automation: an
Idempotency-Keyon every create so retries never double-create, one frozen JSON error envelope, cursor pagination,X-RateLimit-*headers on every response, and hypermedia_actionsthat tell your code which operations the current token may perform.- Resources are addressed by the same key or slug you see in the dashboard, so a script reads like the product instead of a wall of opaque IDs.
1. Two APIs: configure versus evaluate
Featureflip exposes two API surfaces, and knowing which is which saves you from the most common mistake.
The Management API (https://api.featureflip.io, everything under /api/v1) is the write plane. It creates and updates the configuration of your flags: the flags themselves, their variations, which environments they are on, and the rules that decide who sees what. It is called by humans-once-removed: a CI pipeline, a migration script, an internal tool.
The Evaluation API and the SDKs are the read plane. Your application uses them to answer one question, fast: “what value does this flag have for this user, right now?” That path is built to be lightweight. The server SDKs hold your ruleset in memory and evaluate locally in about the time of a map lookup, with no per-request round trip. That is why the two are separate: putting configuration CRUD on the same path as high-frequency evaluation would slow the part that has to stay fast.
The rule of thumb: if you are changing what a flag is, that is the Management API. If you are reading what a flag says for a given user, that is an SDK or the Evaluation API.
2. Authenticate with a personal or service token
Every request carries a bearer token in the Authorization header:
Authorization: Bearer <your-token>There are two token types, and the difference is identity. A Personal Access Token acts as you: it carries your identity and your role in every organization you belong to. Reach for one when you are scripting locally or exploring the API. You create it under Settings → API Tokens → Personal Access Tokens, and it is prefixed ffp_.
A Service Token is a machine identity scoped to a single organization. It carries an explicit role and, optionally, an allowlist of projects it may touch. It is not tied to a person, so it keeps working after someone leaves the team. That makes it the right token for CI, automation, and shared infrastructure. You create it under Organization Settings → Service Tokens, and it is prefixed ffs_. Both token types are shown once at creation, so store them somewhere your automation can read and a person cannot.
Both tokens act with a role, and roles are hierarchical:
| Role | Can do |
|---|---|
| Owner | Everything, including org settings |
| Admin | Manage projects, flags, members |
| Member | Create and edit flags, targeting, segments |
| Viewer | Read-only |
A write attempted by a token below the required role returns 403 forbidden. A service token whose project allowlist excludes the target project returns 404 not_found for that project, so a scoped token cannot even confirm the existence of projects it is not allowed to see. The full contract is in the authentication docs.
3. Create your first flag over HTTP
Here is the whole path from nothing to a live, targeted flag. It is six requests. Everything sends and receives JSON, and every request carries the Authorization header from the previous section.
Start by finding the organization your token can act in. You can also confirm who the token authenticates as with GET /api/v1/me.
GET /api/v1/orgsNote the key of the organization you want. That value is {org} in the paths below. Now create a project inside it:
curl -X POST https://api.featureflip.io/api/v1/orgs/{org}/projects \ -H "Authorization: Bearer $FF_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "key": "checkout", "name": "Checkout", "description": "Checkout flow experiments" }'That returns 201 Created with the project. Add an environment to it:
POST /api/v1/orgs/{org}/projects/checkout/environments{ "key": "production", "name": "Production" }Then create the flag itself:
POST /api/v1/orgs/{org}/projects/checkout/flags{ "key": "new-checkout", "name": "New checkout", "type": "Boolean", "description": "Rolls out the redesigned checkout", "clientSideVisible": false}The 201 Created response includes the flag’s generated on and off variations and an _actions block. One detail worth internalizing: a new flag is off in every environment until you turn it on. Creating a flag never exposes it to a single user. Enabling it in an environment is a separate, deliberate call:
POST /api/v1/orgs/{org}/projects/checkout/flags/new-checkout/environments/production/toggle{ "enabled": true }The toggle returns 204 No Content. At this point the flag is on and serving its default variation to everyone in production. To serve it to a subset instead, add a targeting rule. This one points at a segment; you can instead pass conditionGroups for attribute-based targeting or rolloutPercentage for a percentage rollout:
POST /api/v1/orgs/{org}/projects/checkout/flags/new-checkout/environments/production/rules{ "description": "Beta users", "variationId": "<on-variation-id>", "userSegmentId": "<segment-id>", "conditionGroups": []}That is the full lifecycle. The quickstart walks the same path with every response body shown in full.
4. What you can automate
The reason to want any of this is that flag configuration stops living only in a browser tab and starts living in your pipeline, where it can be reviewed, repeated, and version-controlled. Four patterns cover most of what teams reach for.
Seed flags in CI. When you stand up a new service or a new environment, its flags should arrive with it, not get hand-created afterward from memory. A script that reads a manifest and calls the create endpoints gives every environment the same flag set every time. Because creates accept an idempotency key (next section), you can rerun the seed job safely.
Keep environments in sync. Promoting a configuration from staging to production by clicking through two dashboards is where drift comes from. Reading the targeting from one environment and writing it to another over the API makes the promotion a repeatable step you can put in a pipeline instead of a checklist.
Automate stale-flag cleanup. Flags are, as Pete Hodgson put it, an inventory that carries a cost. Left alone, that inventory grows. Listing flags over the API, finding the ones that are archived or safe to remove, and scripting the teardown turns flag cleanup from a quarterly chore into a job. The API also enforces flag creation conventions at the source, which pairs well with the CI checks in the naming conventions guide.
Build internal tooling. A Slack command that flips a flag, a back-office toggle your support team can reach, an approval workflow that gates a rollout: all of them are the same REST surface with a different front end. You are not blocked on the dashboard supporting your exact workflow, because you can build the workflow yourself.
Each of these is a scripted dark launch or soft rollout waiting to happen, run from where your team already works.
5. Built for automation, not just reachable
An endpoint you call once by hand and an endpoint you call in a retry loop have different needs. A management API you script against has to behave predictably when a request is retried, when a payload is wrong, and when you are going too fast. Featureflip’s has four properties for exactly this.
Idempotency. Every create accepts an Idempotency-Key header:
Idempotency-Key: 6f9619ff-8b86-d011-b42d-00cf4fc964ffSend a unique key per logical create. If a request with the same token and key is retried, the original result is replayed instead of creating a duplicate. If a second request with the same key arrives while the first is still in flight, it returns 409 idempotency_key_in_progress, so overlapping retries run at most once. That is what makes a rerun of a seed job safe.
One frozen error envelope. Every error, from any endpoint, has the same shape:
{ "error": "validation_failed", "message": "One or more fields are invalid.", "docs_url": "https://featureflip.io/docs/management-api/errors/validation_failed", "fields": { "key": ["Key must be lowercase kebab-case."] }}error is a stable machine-readable code, message is for humans, and docs_url links to the page for that code. Some errors add fields: fields for per-field validation, retry_after when you are rate limited, did_you_mean when you typo a key or slug, and next_actions suggesting follow-up requests. Your error handling reads one shape, not one per endpoint.
Rate limits you can see. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset, so a well-behaved client can slow down before it is told to. When you do exceed the limit, you get 429 rate_limited with a retry_after field and a Retry-After header telling you exactly how long to back off.
Hypermedia _actions. Every resource response includes a small block describing which follow-up operations the current token may perform, and why not when it cannot:
"_actions": { "update": { "allowed": true }, "delete": { "allowed": false, "reason": "requires Member role" }}An internal tool can read _actions to decide which buttons to show for the current token, without hardcoding a copy of the permission model that will drift the first time the roles change. The conventions doc covers all four in detail, and the errors reference lists every code.
6. Pagination and addressing
List endpoints are cursor-paginated. Pass an opaque cursor to fetch the next page:
GET /api/v1/orgs/{org}/projects/{project}/flags?cursor=<next_cursor>The response wraps the items with the next cursor, and a null cursor means there are no more pages:
{ "items": [ /* ... */ ], "next_cursor": "eyJvIjoyNX0" }One quirk worth coding for: because cursors are offset-based, the final “next” page can legitimately come back empty, so treat an empty page as the end rather than an error. On addressing, the pattern is consistent: organizations, projects, flags, environments, and segments are addressed by their key or slug, the same stable identifier you see in the dashboard. Nested resources without a user-facing key, meaning targeting rules and variations, are addressed by the GUID id returned when you create or list them.
7. When to use the API, the SDK, or the dashboard
Three surfaces, three jobs, and the mistake to avoid is using the Management API where an SDK belongs.
| Surface | Use it to | Reach for it when |
|---|---|---|
| Dashboard | Configure flags by hand | A person is making a one-off change |
| Management API | Configure flags programmatically | A pipeline, script, or internal tool changes configuration |
| SDK / Evaluation API | Read a flag’s value for a user | Your application decides what to serve, on the request path |
The Management API is not a flag-reading API. It is not built for the volume or the latency of per-request evaluation, and pointing your application at it to decide what to render would put a network round trip and a rate limit on your hot path. That is the SDK’s job, and the server SDKs evaluate locally in memory precisely so that path stays fast. Use the Management API to set the configuration up; use an SDK to read it out. The feature page has more on the API surface, and the SDK feature page covers the evaluation side.
The shorter version
Featureflip now has a REST Management API at https://api.featureflip.io, with every path under /api/v1. It is the write plane: it configures projects, environments, flags, variations, targeting, and segments, separate from the SDKs that read flags on your application’s hot path. Authenticate with a bearer token, a Personal Access Token (ffp_) for scripting or a Service Token (ffs_) for CI and shared automation. Six requests take you from finding your organization to a live, targeted flag, and a new flag stays off until you deliberately enable it. What makes it safe to script is the automation contract: an Idempotency-Key on every create so retries never double-create, one frozen error envelope across every endpoint, visible X-RateLimit-* headers, and hypermedia _actions that report what the current token may do. Use it to seed flags in CI, sync environments, automate cleanup, and build internal tooling.
Frequently asked questions
Can I manage feature flags through an API?
Yes. The Featureflip Management API is a full REST interface at https://api.featureflip.io/api/v1 for configuring projects, environments, feature flags, variations, targeting rules, segments, and SDK keys. It does everything the dashboard does, driven by code instead of clicks, so you can seed flags in CI, sync environments, and build internal tooling. The overview lists every resource you can manage.
What is the difference between the Management API and the Evaluation API?
The Management API writes configuration: it creates and changes flags, targeting, and environments. The Evaluation API and the SDKs read flags, answering what value a flag has for a given user. Evaluation is high-throughput and stays on your request path, so the server SDKs evaluate locally in memory with no per-request round trip. Configuration is lower-frequency and richer, which is why the two are separate surfaces.
How do I authenticate to the Featureflip Management API?
Send a bearer token in the Authorization header: Authorization: Bearer <token>. Use a Personal Access Token (prefixed ffp_) for personal scripting, which acts as you and carries your role in every organization you belong to. Use a Service Token (prefixed ffs_) for CI and shared automation, which is a machine identity scoped to one organization and keeps working after team changes. Both are created in the dashboard and shown once.
How do I create a feature flag with the API?
Send POST /api/v1/orgs/{org}/projects/{project}/flags with a key, name, and type such as Boolean. The response returns the flag and its generated variations. A new flag is off in every environment until you enable it with a separate call to that environment’s /toggle endpoint, so creating a flag never exposes it to anyone until you deliberately turn it on.
Does the Management API support idempotent retries?
Yes. Every create endpoint accepts an Idempotency-Key header. Send a unique key per logical create, and a retried request with the same token and key replays the original result instead of creating a duplicate. If a second request with the same key arrives while the first is still processing, it returns 409 idempotency_key_in_progress, so overlapping retries execute at most once. This is what makes rerunning a seed or sync job safe.
Featureflip is a focused, flat-priced feature flag platform, and the Management API brings its full configuration surface into your pipeline: create flags, targeting, and segments over REST, with idempotent creates, one predictable error shape, and permission-aware responses that make it safe to automate. The same API also backs the Featureflip MCP server, so AI coding assistants like Claude Code and Cursor can manage your flags without leaving the editor. The Management API quickstart takes you from a token to a targeted flag in a few requests, and you can start on the free Solo plan without a credit card.