The Flagsmith API
A plain-English tour of how applications and people talk to Flagsmith over the web: the two APIs, how keys work, what each request does, how errors and limits behave, and how to automate everything safely.
Every button you click in the Flagsmith dashboard, and every feature flag your application reads, travels through an API. The dashboard itself is only a friendly face painted on top of it. If you understand the API, you understand how Flagsmith really works, and you gain the power to automate things that would take a person hours of clicking.
This guide explains the Flagsmith API from the ground up. You will learn what an API is, why Flagsmith has more than one, how requests are proven to be allowed, what comes back, what goes wrong, and how to build safe automation around it. We use simple language, everyday comparisons, and plain descriptions rather than code, so the ideas stay clear whatever language your team writes in.
1Why a Feature Flag Platform Needs an API
A flag service is only useful if other programs can reach it quickly and safely.
What an API is
An API, short for application programming interface, is a set of agreed requests that one program can send to another, together with the replies it should expect. It is a contract. If you ask in the agreed way, you get an answer in the agreed shape. The people who built the service can change everything inside, and as long as the contract stays the same, nobody who depends on it is hurt.
Think of a restaurant. You do not walk into the kitchen and cook your own meal. You read a menu, tell the waiter what you want, and the waiter brings your food. The menu is the contract, the waiter is the API, and the kitchen is everything hidden behind it. You do not need to know how the kitchen is arranged, only how to order.
Why Flagsmith is built API-first
Flagsmith is a service that many different programs must talk to. Your website, your phone app, your backend servers, your build pipeline, and your support tools may all need something from it. A single, well-defined API means all of them speak the same language. The dashboard is just one more customer of that API, which is why anything you can do by clicking can usually also be done by a program.
Two very different jobs
The API does two quite different jobs. One job is reading: an application asks “what should I show this user?” thousands of times a second. The other job is managing: a person or a script creates flags, changes their values, and builds rules. These jobs have different traffic, different risks, and different people involved, so Flagsmith splits them into two APIs. Understanding that split is the single most important idea in this guide, and the next chapters build on it.
Most teams never call the API by hand. They use an SDK, which wraps the API in friendly functions. Even so, knowing what happens underneath helps you fix problems quickly, build tools the SDK does not cover, and judge when something is slow or wrong.
2Two APIs, Two Audiences
The SDK API serves your running applications. The Admin API serves people and automation.
The SDK API (also called the Flags API)
The SDK API is what your applications call at runtime. It is small on purpose. It answers questions such as “give me every flag for this environment” or “give me every flag for this particular user, and remember these facts about them.” It is built to be read very often and to answer very fast. It authenticates with an environment key, which identifies one environment of one project.
The Admin API
The Admin API is what the dashboard itself uses, and it is also open to you. It is large. It covers organisations, projects, environments, features, feature states, segments, identities, tags, audit logs, webhooks, and more. It is used to create, change, and delete things. It authenticates with a secret token or an organisation API key, and it can do things your applications should never be able to do, such as delete a flag in production.
A hotel has a front desk where guests ask simple questions, such as “what time is breakfast?” Guests are many and the questions are quick. The hotel also has a back office where staff change room prices, assign rooms, and update the rules. Few people work there and their actions have big effects. The SDK API is the front desk. The Admin API is the back office, and its door is kept locked.
| Question | SDK API | Admin API |
|---|---|---|
| Who calls it? | Your running applications | People, scripts, pipelines, the dashboard |
| Main purpose | Read flag states and values | Create, change, and delete everything |
| Credential | Environment key | Admin token or organisation API key |
| Traffic | Very high | Low to moderate |
| Power | Read-only for flags, plus identity data | Full control, depending on role |
| Where the key may live | Client keys: anywhere. Server keys: servers only | Secrets manager only |
flowchart LR
APP["Web or Mobile App"] -->|"Environment key"| SDKAPI["SDK API"]
SRV["Backend Service"] -->|"Server key"| SDKAPI
DASH["Dashboard"] -->|"User login"| ADMIN["Admin API"]
CI["Pipeline or Script"] -->|"Admin credential"| ADMIN
SDKAPI --> STORE[("Flag Data")]
ADMIN --> STORE
Never mix the two worlds. An Admin credential placed in a mobile app or web page would let anyone who finds it change your production flags. Environment keys and Admin credentials are different tools for different jobs, and they must be stored differently.
3A Short Primer on Web APIs
A few ideas about how web APIs work will make everything else easier to follow.
Requests and responses
Every conversation with the API has two halves. The caller sends a request, and the service sends back a response. A request names what the caller wants and carries any information needed. A response says whether it worked and carries the answer.
The parts of a request
- Address (URL): where the request is going, including the path that names the kind of thing you are asking about, such as flags or identities.
- Method: the verb that says what to do. A GET reads something. A POST creates something. A PUT or PATCH changes something. A DELETE removes something.
- Headers: small labelled notes sent along with the request. This is where the credential goes, and where the caller says what format it speaks.
- Body: the main content, for requests that send data, written in JSON.
JSON
JSON is a simple way to write down information so that any programming language can read it. It arranges data as named fields and lists. For example, an identity might be described by a field for its ID and a list of traits, each with a name and a value. It looks a little like a form that has been filled in.
The parts of a response
- Status code: a number that sums up the result. Numbers beginning with 2 mean success. Numbers beginning with 4 mean the caller made a mistake. Numbers beginning with 5 mean the service had a problem.
- Headers: extra notes about the reply.
- Body: the answer itself, usually in JSON.
REST
Flagsmith follows a style called REST. The idea is that every kind of thing, such as a project or a feature, has its own address, and a small set of verbs act on those addresses in a predictable way. Once you learn how one kind of thing is handled, the others feel familiar.
A library has a catalogue where every book has its own shelf location. To see a book you go to its shelf. To add one, you hand it to the librarian for that section. To remove one, you ask the librarian to take it away. REST is like that: each thing has a place, and a few simple actions work the same way everywhere.
| Verb | Plain meaning | Example in Flagsmith terms |
|---|---|---|
| GET | Read, change nothing | Fetch the flags for an environment |
| POST | Create or submit | Send an identity with traits, or create a feature |
| PUT | Replace the whole thing | Replace a feature’s full definition |
| PATCH | Change part of it | Turn a flag on without touching anything else |
| DELETE | Remove | Delete a retired feature |
4Where the API Sits in the Architecture
Following a request from the caller to the data shows how the pieces cooperate.
The hosted service
When you use the hosted Flagsmith service, the API lives at addresses run by the Flagsmith team. Applications reading flags are usually served by a globally distributed layer, often called the Edge API, which keeps a read-optimised copy of each environment close to the caller. Management requests go to the core API, which writes changes to its main database and then makes sure the serving layer receives the update.
The self-hosted service
When you host Flagsmith yourself, the API is the application server you run, usually built in Python with the Django framework and backed by a relational database. You decide the address. You place a load balancer in front, run several copies, and add caching. The same SDK API and Admin API are available, so your applications can switch between hosted and self-hosted by changing only the address and the key.
flowchart TD
CALLER["Caller"] --> LB["Load Balancer or Gateway"]
LB --> API1["API Instance A"]
LB --> API2["API Instance B"]
API1 --> CACHE["Cache"]
API2 --> CACHE
CACHE --> DB[("Relational Database")]
API1 --> DB
API2 --> DB
API1 --> WORK["Background Worker"]
WORK --> OUT["Webhooks and Integrations"]
Why keep the layers separate
The API handles the request, the cache avoids repeating work, the database remembers everything for good, and the worker handles slow jobs such as sending webhooks so they never delay an answer. Each part can be made bigger or smaller on its own. This is the same shape you will find in almost every busy web service.
Imagine a busy post office. A counter clerk answers customers quickly. A sorting room keeps frequently asked-for items near the front. A large warehouse stores everything permanently. A back room handles slow tasks like special deliveries. A customer talks only to the counter clerk, yet all the other rooms make that quick answer possible.
Addresses, regions, and the exact layout of the hosted service can change over time. Always take the current base address and any regional options from the official documentation rather than from memory or an old article.
5Authentication: Proving You Are Allowed
Every request must carry a credential. Which one depends on which API you are calling.
Why authentication matters
The service must know two things before it answers: who is asking, and what that asker is permitted to do. Authentication answers the first question, and permissions answer the second. A flag platform controls how your product behaves, so these checks are not optional.
Environment keys for the SDK API
Requests to the SDK API carry an environment key in a request header. The key tells Flagsmith which project and environment to read. There are two kinds. A client-side key is safe to place in a web page or mobile app, because it can only fetch flags for an identity and cannot read the full rules. A server-side key is a secret that can read the complete environment configuration, so it must stay on servers you control.
Credentials for the Admin API
Requests to the Admin API carry a stronger credential, also in a header. There are two common kinds. A user token belongs to one person’s account and acts with that person’s permissions. An organisation API key belongs to the organisation and is meant for automation such as pipelines and scripts, so it does not depend on a specific employee staying at the company. Check the current documentation for how the header is written, since the format matters and details can change.
flowchart TD
R["Incoming request"] --> H{"Which API?"}
H -->|"SDK API"| E["Read environment key from header"]
H -->|"Admin API"| T["Read admin credential from header"]
E --> V1{"Key valid?"}
T --> V2{"Credential valid?"}
V1 -->|"Yes"| A1["Answer with that environment's flags"]
V1 -->|"No"| X1["Reject with an authorisation error"]
V2 -->|"Yes"| P{"Permission allows this action?"}
V2 -->|"No"| X2["Reject with an authorisation error"]
P -->|"Yes"| A2["Perform the action"]
P -->|"No"| X3["Reject as forbidden"]
| Credential | Used with | Secret? | Can do |
|---|---|---|---|
| Client-side environment key | SDK API | No, public by design | Fetch flags for an identity |
| Server-side environment key | SDK API | Yes | Fetch flags and the full environment configuration |
| User token | Admin API | Yes | Whatever that person is allowed to do |
| Organisation API key | Admin API | Yes | Automation tasks within its permissions |
Think of an office building. A visitor badge opens the front door and the lobby, and many people hold one. A staff card opens the offices. A master key opens the server room, and only a handful of people carry it. Client keys are visitor badges, server keys are staff cards, and Admin credentials are master keys.
Handling keys safely
- Store secret keys in a secrets manager, never inside source code or chat messages.
- Use a separate key for each environment and each application, so one leak can be cut off without breaking everything.
- Rotate secrets on a schedule and immediately after any suspected exposure or staff change.
- Give automation the smallest permissions that let it do its job.
- Keep keys out of logs and error messages.
A key committed to a public code repository should be treated as already stolen. Remove it, create a new one, and revoke the old one at once. Deleting it from the file is not enough, because the history of the repository still holds it.
6Reading Flags: The Environment-Level Request
The simplest question you can ask Flagsmith is “what are all the flags in this environment?”
What the request looks like
To read flags, the caller sends a GET request to the flags path of the SDK API and includes the environment key in a header. There is no body, because nothing is being created. The request does not say anything about a particular user, so the answer is the same for everybody: the default state and value of every feature in that environment.
What comes back
The response is a list. Each item in the list describes one feature and usually carries four kinds of information: the feature’s identifying number, the feature’s name, whether it is enabled, and its value, which may be empty if the feature is a plain on/off switch. Your application reads the list, finds the feature it cares about by name, and decides what to do.
| Piece of the answer | What it tells you | How your app uses it |
|---|---|---|
| Feature name | The label you gave the feature | To find the right item in the list |
| Enabled | True or false | To decide whether the new code path runs |
| Value | Text, number, or true/false, or empty | To read settings such as a limit or message |
| Feature identifier | A number unique to the feature | For logging and for matching with other data |
When to use this request
The environment-level request suits situations where every user gets the same answer: a site-wide maintenance banner, a global setting, or an application that has no notion of individual users. It is the cheapest request because Flagsmith does not need to look up an identity or test any segment rules.
It is like reading the notice board at the entrance of a school. Everyone who walks in sees the same notices. Nobody is checked against a list first, and the board does not change depending on who is looking at it.
What it does not do
Because no identity is sent, segment overrides and percentage rollouts cannot apply. If you have a rule such as “show this to twenty percent of users,” the environment-level request cannot honour it, because it does not know who is asking. For targeted behaviour you must use the identities request, described next.
If a flag seems to ignore your segment rules, check which request your app is sending. A common cause is an app calling the environment-level request, which has no identity, while the rules expect one.
7Reading Flags for a User: The Identities Request
When you want answers that depend on who the user is, you introduce them to Flagsmith first.
What the request carries
The identities request is a POST. It carries the environment key in a header, and in its body it carries an identifier, which is the unique ID of the user, plus an optional list of traits, which are facts about that user. Each trait has a name and a value. A POST is used, rather than a GET, because the request can change something: it may create the identity the first time it is seen and store or update its traits.
What comes back
The response contains the flags as they apply to that user, after all rules have been evaluated, and it also contains the traits now stored for the identity. Each flag looks like the ones in the environment-level answer, but with the user’s own state and value. If the user belongs to a segment with an override, the override’s answer appears. If the user was placed into one variation of a multivariate flag, that value appears.
sequenceDiagram
participant App as Application
participant API as SDK API
participant Rules as Rule Engine
participant Store as Data Store
App->>API: Send identifier and traits with environment key
API->>Store: Find or create the identity and save traits
Store-->>API: Identity record
API->>Rules: Evaluate segments and rollouts for this identity
Rules-->>API: Final state and value for each feature
API-->>App: Flags plus stored traits
The order of evaluation
Flagsmith starts with the environment default for each feature. It then checks whether this exact identity has a personal override, which wins over everything else. If not, it walks through the segment overrides in priority order and applies the first one whose rules match the traits. For multivariate features it assigns the identity to a variation in a repeatable way. The result is the final list sent back.
Authenticate
The environment key is checked and the right environment is chosen.
Resolve the identity
The identifier is looked up, and a new identity is created if this is the first sighting.
Store the traits
Traits from the request are saved or updated against the identity.
Evaluate
Personal overrides, segment overrides, and rollout buckets are applied in order.
Respond
The final flags and the stored traits are returned to the caller.
Choosing the identifier
The identifier should be stable and unique for each person, and it should be the same in every system that talks to Flagsmith. A customer number from your own database works well. Avoid anything that changes, such as an email address that a person might edit. Avoid personal data where possible, as explained in the security chapter.
Everyday use case: a plan-based feature
A user logs in. Your server sends their customer number as the identifier and their plan name as a trait. Flagsmith matches the plan against a segment, applies the override, and returns the flags. The advanced report page is on for “enterprise” plans and off for the rest. When the customer upgrades, the next request carries the new plan and the page appears.
8Traits: Sending Facts About Your Users
Traits are the raw material of targeting. How you send them decides how good your targeting can be.
What a trait is
A trait is a named fact about an identity. It has a key, such as “plan” or “country”, and a value, such as “pro” or “India”. Values can be text, whole numbers, decimal numbers, or true and false. The type matters, because rules compare values in type-aware ways. “Greater than” makes sense for numbers but not for free text.
Three ways to send traits
- With the identities request. The most common way. Include the traits in the body, and Flagsmith saves them and evaluates rules in one step.
- Through a separate traits request. Some SDKs and workflows update a single trait on its own, without asking for flags.
- As one-time traits. Newer SDKs can send traits for a single evaluation without storing them. This suits short-lived data and sensitive data you prefer not to keep.
Updating and removing traits
Sending a trait with a new value replaces the old value. Sending a trait with an empty value is the usual way to remove it. Check the current documentation for the exact behaviour in your SDK, because details such as how missing traits are treated can differ between versions.
Matching rules and types
| Trait type | Good rule styles | Example |
|---|---|---|
| Text | Equals, not equals, contains, in a list | Country is one of three named countries |
| Whole number | Equals, greater than, less than | Age of account in days is more than thirty |
| Decimal number | Greater than, less than | App version is at least five point two |
| True or false | Equals | Is an employee equals true |
A traits list is like the information on a passenger’s boarding pass: seat class, frequent flyer level, and special needs. The gate agent does not need the passenger’s life story. A few well-chosen facts are enough to decide who boards first.
Common trait mistakes
- Sending numbers as text. A trait sent as the text “5” may not compare the way a number would. Send numbers as numbers.
- Forgetting to send a trait. A rule on a missing trait simply fails to match. Decide what the safe behaviour is for such users.
- Inconsistent names. If one service sends “Plan” and another sends “plan”, rules may match only half your users. Agree on one spelling and case.
- Sending too much. Every extra trait is more data to protect. Send only what your rules actually use.
- Frequently changing traits. A value that changes every minute makes users hop between segments and see unstable behaviour.
Do not put sensitive personal details in traits. A rule that depends on a health detail or an email address creates a privacy burden for no benefit. Use plain categories such as plan and region instead.
9The Environment Document and Local Evaluation
For very busy servers, the best request is the one you rarely have to make.
The idea
With remote evaluation, every flag check is a request to Flagsmith. With local evaluation, a server downloads the full configuration of an environment once, and then answers every flag check from memory. The download is served by a special request that returns what is called the environment document. It contains every feature, every segment, every rule, and every override for that environment.
Who is allowed to ask for it
Because the environment document holds all your targeting rules, only a server-side key may fetch it. A client-side key is refused. This is a deliberate protection: the rules of a company can reveal plans, pricing logic, and internal groupings that should never be visible in a browser.
How the SDK uses it
A server SDK in local mode fetches the document when it starts, then refreshes it on a schedule, commonly about once a minute, though you can change the interval. Between refreshes, each flag check takes the identity and traits from your code, runs the segment rules inside your own process, and returns the answer without leaving the machine.
flowchart LR
SRV["Your Server with SDK"] -->|"Fetch once a minute with server key"| API["SDK API"]
API -->|"Environment document"| SRV
SRV --> MEM["In-memory rules"]
REQ["Thousands of flag checks"] --> MEM
MEM --> ANS["Instant answers"]
| Trade-off | Remote evaluation | Local evaluation |
|---|---|---|
| Latency per check | One network trip | In-memory, near instant |
| Load on Flagsmith | Grows with traffic | Grows only with the number of servers |
| Freshness | Latest at every request | As of the last refresh |
| Where rules are visible | Only inside Flagsmith | Inside your server’s memory |
| Works if the network fails | Needs cached or default values | Keeps working with the last document |
A traveller can phone the airline every time they need a rule about baggage, or they can print the whole baggage policy once and refresh the printout each morning. The printout is faster and works when the phone line is down, but it can be a few hours behind the latest announcement.
Practical advice
Use local evaluation for busy backend services. Protect the server key like any other secret. Watch that the refresh is actually succeeding, because a server that silently stops refreshing will keep using older rules. Track how old the in-memory document is, and raise an alert if it becomes much older than expected.
10What Comes Back: Shapes of Responses and Defaults
Reading a response correctly is as important as sending the request correctly.
Lists and lookups
Flag responses arrive as lists. Your code should convert the list into a lookup by feature name once, then read from that lookup. Looking through the list again on every check wastes time and invites mistakes.
Always handle a missing flag
A flag you ask for might not exist in the response. It may have been deleted, mistyped, or never created in that environment. Never assume it is present. When it is missing, use your safe default and, ideally, log a warning so a human can fix the mismatch.
Treat the value type carefully
A value can be text, a number, or true and false. Check its type before using it, and handle an empty value as a normal case rather than an error. A flag that is on but has no value is perfectly valid; it simply has no extra setting attached.
Safe defaults
Every flag check in your code needs a default: what to do when no answer arrives, or the answer is unusable. Choose defaults that favour safety. A new, unfinished feature should default to off. A protective kill switch should default to its protective state. Defaults are the quiet hero of reliable flag use.
flowchart TD
CALL["Request flags"] --> OK{"Valid response received?"}
OK -->|"Yes"| FIND{"Flag present in the list?"}
OK -->|"No"| DEF["Use safe default"]
FIND -->|"Yes"| USE["Use state and value"]
FIND -->|"No"| DEF
Everyday use case: a deleted flag
A team removes an old flag from Flagsmith but forgets one place in the code that still reads it. Because that code has a safe default of “off”, the old behaviour simply continues, and a logged warning leads the team to the leftover check. Without a default, the same mistake could have caused an error for every user.
Wrap your flag checks in one small helper of your own, with the default built in. Then every part of your code handles missing or broken answers the same way, and you have a single place to improve later.
11The Admin API: Managing Everything
The Admin API is the back office. It can create, read, change, and delete every kind of thing in Flagsmith.
A family of resources
The Admin API is organised around resources, which are the kinds of things Flagsmith keeps. Each resource has its own address, and the same verbs work on each in a similar way. The main resources mirror the concepts you already know.
Organisations
The top-level container holding teams and projects.
Projects
One product or application and its list of features.
Environments
Development, Staging, Production, each with its own keys and states.
Features
The named flags and config values defined in a project.
Feature states
The on/off state and value of a feature within one environment.
Segments
Saved groups of users defined by rules over traits.
Identities
The known users, with their traits and personal overrides.
Audit logs and webhooks
History of changes and automatic notifications.
Features versus feature states
This distinction trips up many newcomers. A feature is the definition: its name, its description, its type. It exists once per project. A feature state is how that feature behaves in one environment: whether it is on, and which value it carries. If you have three environments, each feature has three feature states. To turn a flag on in Production, you change its feature state in the Production environment, not the feature itself.
flowchart TD
ORG["Organisation"] --> PROJ["Project"]
PROJ --> FEAT["Feature definition"]
PROJ --> ENVD["Environment: Development"]
PROJ --> ENVP["Environment: Production"]
FEAT --> FSD["Feature state in Development"]
FEAT --> FSP["Feature state in Production"]
ENVD --> FSD
ENVP --> FSP
A restaurant menu lists a dish called “spicy noodles”. That is the feature. Each branch of the restaurant then decides whether the dish is available today and how spicy it is. Those branch decisions are the feature states. The dish is defined once, but each branch controls its own version.
Learning the resource map
Flagsmith publishes interactive documentation for its API, based on a standard description format. For a self-hosted installation, the same documentation is usually available from your own server. Browsing it is the fastest way to see every resource, every field, and every allowed action for the version you run.
12Managing Features and Feature States
The two jobs people most often automate: creating a flag, and flipping it.
Creating a feature
To create a flag, a script sends a POST to the features resource of a project, carrying the feature’s name and optional details such as a description, a type, an initial value, and tags. The service replies with the newly created feature, including its identifying number. After that, the feature exists in every environment of the project, usually off by default.
Changing a feature state
To turn a flag on or off, or to change its value, a script changes the feature state belonging to the target environment. It finds the right feature state, then sends a PATCH or PUT request with the new on/off setting or value. Changing a state in Production takes effect for applications on their next fetch or refresh.
Common workflows
Create on feature branch
When a developer starts a feature, a script creates the flag in the project so teammates can use it right away.
Enable in lower environments
After a successful build, the pipeline turns the flag on in Development and Staging for testing.
Release in stages
A scheduled or manual step raises the percentage in Production at agreed times.
Retire
After the launch, a cleanup task deletes the flag and the code that reads it.
Bulk work
When you must change many flags, a script can list the features of a project and loop through them. For example, a task may add a tag to every flag older than a chosen age, or copy a set of flag states from Staging to a new environment. Take care with bulk changes in Production. Test the script in a lower environment first and make it print what it would change before it changes anything.
Deleting a feature through the API removes it for the whole project, in every environment, and any code still reading it will fall back to its default. Confirm that nothing depends on the flag before a script deletes it.
Everyday use case: a creation step in the pipeline
A team agrees that every new feature needs a flag with a standard name and an owner tag. A pipeline step checks the pull request for a flag name, calls the Admin API to create it if it does not exist, and adds the author as owner. This removes a manual chore and guarantees every flag has a name and an owner from the first day.
13Segments, Overrides, and Identities in the Admin API
Targeting rules are data too, and the Admin API lets you manage them like any other resource.
Segments
A segment is created in a project with a name and a list of rules. Each rule has conditions that compare a trait to a value with an operator. Rules can be combined, so a segment can require several conditions together. A script that creates segments is helpful when many projects need the same group definitions, such as “internal staff” or “enterprise customers”.
Segment overrides
A segment override attaches a segment to a feature in one environment, with its own on/off state and value. The order of overrides matters because the first matching one wins, so the API lets you view and change the priority. Managing the order by script reduces the risk of a human accidentally putting a general rule above a restrictive one.
Identities and personal overrides
The Admin API can list identities, look up a specific one, view its traits, and set identity overrides that pin a feature for exactly that person. Support teams use this to give one customer early access or to switch off a feature for one person having trouble. Because identities hold user information, access to them should be limited, and deleting an identity is the usual way to honour a request to remove someone’s data.
| Task | Resource touched | Who usually does it |
|---|---|---|
| Create a reusable group of users | Segment | Product or engineering |
| Give a group early access | Segment override on a feature state | Product manager |
| Let one customer try a feature | Identity override | Support or customer success |
| Remove a person’s stored data | Identity | Privacy or support team |
Think of the guest list for a venue. A segment is a named list such as “press” or “sponsors”. An override says what the list is allowed to do, such as entering through a side door. An identity override is a handwritten note for one person: “let Asha in, even though she is not on any list.” The manager can edit lists and notes, but should be careful, because each edit changes who gets in.
Record why each identity override exists, perhaps in a tag or a ticket reference. Months later, nobody remembers why one person was pinned, and unexplained overrides are a common source of confusion.
14Audit Logs, Webhooks, and Governance Through the API
Reading history and reacting to changes are as important as making them.
Audit logs
The Admin API exposes the audit log, a record of who changed what and when. A script can read recent entries to build a daily summary, feed another tool, or look for unusual activity, such as many production changes outside working hours. Because the log is data, you can search it, filter it by project or time, and keep a copy in your own long-term storage.
Webhooks
A webhook is an automatic message that Flagsmith sends to an address you provide whenever something happens, such as a flag being changed. You can create and manage webhooks through the API. The receiving side is a small web service that accepts the message and acts on it, perhaps posting to a chat channel, refreshing a cache, or opening a ticket.
sequenceDiagram
participant Eng as Engineer
participant Admin as Admin API
participant Hook as Webhook Sender
participant Recv as Your Receiver
participant Chat as Team Chat
Eng->>Admin: Change a flag in Production
Admin->>Hook: Queue a change notification
Hook->>Recv: Send message to your address
Recv->>Chat: Post who changed what
Recv-->>Hook: Acknowledge receipt
Verifying webhooks
Anyone who learns the address of your receiver could send it fake messages. Protect it. Flagsmith can sign webhook messages with a shared secret, so your receiver can check that the message truly came from Flagsmith and was not altered on the way. Confirm the current signing options in the documentation, and always reject messages that fail the check.
Change requests and scheduling
In plans that include them, change requests let one person propose a change and another approve it, and scheduled changes let a change happen at a future time. These can be driven through the API as well, which allows teams to build their own approval flows in the tools they already use.
A bank keeps a statement of every transaction, and it sends you a text message when money leaves your account. The audit log is the statement, and the webhook is the text message. One lets you look back, and the other tells you the moment something happens.
15Lists, Pages, Filters, and Bulk Operations
A project with hundreds of flags cannot be returned in one reply, so list requests come in pages.
Pagination
When you ask for a list of things in the Admin API, the answer is usually split into pages. The response typically includes the total count, a link to the next page when there is one, a link to the previous page, and the items for the current page. To collect everything, your script follows the link to the next page until none remains. A common bug is to read only the first page and conclude that the rest does not exist.
A phone book is too big to read at once, so it is split into pages. You read a page, and if the name you want is not on it, you turn to the next one. Pagination works the same way: take a page, check whether another follows, and keep going until the book ends.
flowchart TD
S["Request first page"] --> R["Read the items"]
R --> N{"Is there a next page link?"}
N -->|"Yes"| G["Request the next page"]
G --> R
N -->|"No"| D["Done: all items collected"]
Filtering and searching
Many list requests accept filters, so you can ask only for features with a certain tag, or only for items matching a search word. Use filters rather than downloading everything and sorting it yourself. It is faster, kinder to the service, and less likely to hit limits.
Ordering
Lists often allow you to choose the order, such as by name or by creation date. When your script depends on the order, ask for it explicitly rather than assuming a default, so a change in the service’s behaviour cannot break your logic.
Doing many things at once
When a task touches many items, there are three common approaches. You can send requests one after another, which is simple and gentle. You can send a few at the same time, which is faster but must stay within rate limits. Or you can use a bulk request if the resource offers one. Whatever you choose, make the script safe to run twice: if it stops halfway, running it again should finish the job without creating duplicates.
Build every script with a “dry run” mode that only prints what it would do. Review that output before running for real. This one habit prevents most expensive automation accidents.
16Status Codes and Handling Errors
Things go wrong. A good caller reads the status code and responds sensibly to each kind of failure.
The families of status codes
Every response begins with a three-digit number. The first digit tells the family. Numbers starting with 2 mean the request succeeded. Numbers starting with 4 mean the request itself was faulty, so repeating it unchanged will fail again. Numbers starting with 5 mean the service had trouble, so trying again later may work.
| Code | Plain meaning | What your code should do |
|---|---|---|
| 200 or 201 | Success or created | Use the result |
| 204 | Success with nothing to return | Carry on, typical after a delete |
| 400 | The request was malformed or invalid | Fix the request; do not retry unchanged |
| 401 | Credential missing or not valid | Check the key; alert a human |
| 403 | Valid credential, but not allowed | Review permissions; do not retry |
| 404 | Thing not found | Check names and identifiers |
| 409 | Conflict with current state | Reload, merge, then try again |
| 429 | Too many requests | Slow down and retry after a wait |
| 500, 502, 503, 504 | The service had a problem | Retry with backoff; use defaults meanwhile |
Reading the error message
Error responses usually include a short explanation in the body that names the field or rule that caused the problem. Log it. A message such as “this field is required” saves hours of guessing. For SDK calls, remember that an error from Flagsmith should never become an error for your user. Fall back to the safe default and report the problem quietly.
If a shop assistant says “we do not stock that item,” asking again will not help. That is a 4 type answer. If they say “the till is broken, please come back in ten minutes,” trying again later is sensible. That is a 5 type answer. Reading the difference prevents both wasted effort and needless giving up.
Do not hide failures
An automation that fails silently is worse than one that fails loudly. If a pipeline step could not turn on a flag, the pipeline should fail, not carry on as if everything were fine. Raise an alert, include the status code and message, and make it easy for a person to see what was not done.
17Rate Limits, Retries, and Backoff
Shared services protect themselves from overload. A polite caller slows down when asked and never hammers a struggling service.
Why limits exist
A service shared by many customers must stop any single caller from using more than a fair share. Limits protect everyone from accidents, such as a script stuck in a loop, and from abuse. The exact limits depend on the plan, the endpoint, and whether you host the service yourself, so check the current documentation and your own plan rather than assuming a number.
What happens when you hit one
When you ask too often, the service answers with the status code meaning “too many requests”. Many services also include a hint about how long to wait. A good client reads that hint, waits at least that long, and then tries again.
Retrying wisely
Retrying is useful for temporary problems and harmful for permanent ones. Retry on server errors, on timeouts, and on “too many requests”. Do not retry on mistakes such as an invalid request or a rejected credential, because the outcome will not change.
Exponential backoff with jitter
Exponential backoff means waiting longer after each failed attempt: for example one second, then two, then four, then eight. Jitter means adding a small random amount to each wait. Without jitter, a thousand clients that all failed at the same moment will all retry at the same moment, and the struggling service is hit by a second wave. With jitter, the retries spread out and the service can recover.
flowchart TD
A["Send request"] --> B{"Success?"}
B -->|"Yes"| OK["Use the answer"]
B -->|"No, temporary problem"| C{"Attempts left?"}
B -->|"No, permanent problem"| F["Stop and report"]
C -->|"Yes"| W["Wait longer, plus a random amount"]
W --> A
C -->|"No"| D["Use safe default and report"]
Imagine a crowd trying to leave a stadium through a single gate that has jammed. If everyone pushes at once, the jam gets worse. If people step back and try again at slightly different moments, the gate clears. Backoff with jitter is the polite step back.
Setting a budget
Retries must have a limit, both in number and in total time. A flag lookup in the middle of a web request cannot wait thirty seconds. For runtime reads, use a very short timeout and few or no retries, and rely on defaults and caches. Save the patient retry loops for background jobs and automation, where waiting costs little.
Retrying a request that creates something can create it twice. Before retrying a create, check whether the first attempt actually succeeded, or design the request so repeating it is harmless.
18Performance and Scalability of the API
Flag reads sit on the hot path of your product, so the API must be fast and must stay fast as you grow.
Read-heavy by nature
Flags are written rarely and read constantly. A flag may change once a week and be read a hundred million times. Systems with this shape reward caching and copying data close to the reader, and nearly all of the performance story for the SDK API is about making reads cheap.
Where speed comes from
- A serving layer near the caller. The hosted service keeps a read-optimised copy of each environment in a store at the edge, which shortens the journey.
- Caching. Repeated reads are answered from a fast cache rather than the main database.
- Small answers. A list of flags is a compact reply that travels quickly.
- Local evaluation. The fastest request is the one that never leaves your server.
- Persistent connections. Reusing one secure connection for many requests saves the cost of setting it up each time.
An example with simple numbers
These numbers are made up to show the idea. Suppose a backend of fifty servers handles ten thousand page views a second, and each page checks four flags. If each check were its own request, the flag service would see forty thousand requests a second. If each page fetched all flags in one call, it would see ten thousand a second. With local evaluation, each of the fifty servers refreshes about once a minute, so the service sees under one request a second. The checks still happen forty thousand times a second, but they are answered from memory.
Scaling the Admin API
The Admin API sees far less traffic, but heavy automation can still strain it. Spread bulk jobs over time, use filters, and avoid asking for the entire list of identities when you only need one. If you host the service yourself, add more API instances behind a load balancer, add read replicas for the database, and push slow work to background workers.
Usage analytics and its cost
SDKs can report how often each flag is evaluated, which helps you find unused flags. That reporting is sent in batches rather than on every check, so its load is small. If you build your own client on the raw API, you may choose to batch such reports in the same way.
A town library with one reference desk gets overwhelmed if every visitor asks the librarian each question. Handing out a printed guide, refreshed every morning, removes nearly all the questions. The librarian can then focus on the rare question that truly needs a fresh answer.
19Reliability: Timeouts, Fallbacks, and Circuit Breakers
The flag service must never become the thing that takes your product down.
Assume it will fail someday
Every network service has bad moments. A well-built application plans for the day when a flag request is slow or fails, and makes sure the effect on users is small or invisible.
Timeouts
Give every flag request a short timeout, often well under a second for runtime reads. A request that waits forever ties up resources and can drag your whole application down with it.
The layers of fallback
- Use the live answer if it arrives in time.
- If not, use the last good answer from a cache in your own process.
- If there is no cached answer, use the safe default written in your code.
Circuit breakers
A circuit breaker is a small piece of logic that stops calling a failing service for a while. After a number of failures, the breaker opens, and calls skip the service and go straight to the fallback. After a pause, the breaker allows a trial request. If it succeeds, normal service resumes. This protects both your application, which stops wasting time, and the flag service, which gets a chance to recover.
stateDiagram-v2
[*] --> Closed
Closed --> Open: "Too many failures"
Open --> HalfOpen: "Wait period ends"
HalfOpen --> Closed: "Trial request succeeds"
HalfOpen --> Open: "Trial request fails"
It is exactly like the circuit breaker in a house. When too much current flows, the breaker trips and cuts the power so the wiring does not catch fire. After you fix the cause, you switch it back on and test it. An API circuit breaker cuts off calls to a failing service for the same protective reason.
High availability when self-hosting
If you run the service yourself, make the API highly available. Run several instances in separate zones, put a load balancer with health checks in front, use a database with automatic failover and tested backups, and monitor the whole chain. Because many applications depend on the flag service, it deserves the same care as your most important systems.
Practice the failure. In a staging environment, block the network path to the flag service and watch how your application behaves. If the result surprises you, fix the defaults and fallbacks before production teaches the same lesson.
20Security of the API
An API that controls product behaviour deserves the care you would give to any production control panel.
Use encrypted connections only
Every request must travel over HTTPS, which encrypts the content so that eavesdroppers cannot read keys or data. Refuse any configuration that allows plain, unencrypted requests, especially for the Admin API.
Least privilege
Give each credential only the power it needs. A pipeline that only turns flags on and off in Staging should not be able to delete projects. Use separate credentials for separate jobs, so that a leak in one place has a limited effect.
Protect secrets throughout their lives
- Keep secrets in a dedicated secrets manager and inject them when the program starts.
- Never print keys in logs, error messages, or chat messages.
- Rotate credentials on a schedule and when people leave.
- Scan your code repositories automatically for accidentally committed keys.
- Revoke any key you cannot account for.
Client-side keys are public
A client-side environment key can be read by anyone who opens your web page or inspects your app. It is designed for that. It is safe only because it cannot read your full rules or change anything. Never place a server-side key or an Admin credential in front-end code, mobile apps, or public repositories.
Flags are not permissions
A flag fetched through the API tells your application what to show. It does not stop a determined person from calling your own back-end directly. Any action that must be restricted needs a permission check on the server. Use flags to decide what is shown, and use authorisation to decide what is allowed.
The mistake
A team puts a server-side key into a mobile app because “it is easier than building a small back-end service”.
Why it fails
Anyone can unpack the app and read the key. With it they can download your complete targeting rules, including plans, internal groups, and unreleased feature names.
The fix
Use the client-side key in apps, and keep the server-side key on your own servers. If you need server-side power for an app, route the request through a small service you control.
Data minimisation
Send only the traits your rules need. Prefer internal numeric identifiers over email addresses. Remember that anything stored against an identity is data you must be able to delete on request.
Control and review access
Limit who can change Production, use approval workflows for sensitive flags where your plan supports them, and review the list of users and API keys regularly. Keep the audit log enabled and watch it for surprises.
21Monitoring, Logging, and Observability
You cannot fix what you cannot see. Make your use of the API visible.
Measure your calls
For every call to Flagsmith, record how long it took and whether it succeeded. Graph the speed and the failure rate. A creeping increase in response time often warns of trouble long before users notice. Track fallbacks too: every time your code falls back to a default, count it. A sudden rise in fallbacks means something is wrong with the API path.
Measure staleness
If you use local evaluation, record the age of the environment document held in memory. A server that has silently stopped refreshing will serve old rules, and only an age graph will reveal that.
Log what matters, and no more
- Log: the endpoint, the status code, the duration, and the name of the flag or resource involved.
- Do not log: keys, tokens, or personal details from traits.
- Add context: a request identifier that ties a Flagsmith call to the user request that caused it.
Mark changes on your graphs
A flag change is a production change. Use webhooks or integrations to send flag changes to your monitoring tool, so a vertical line appears on your error graph at the moment the flag was flipped. When something breaks, the first question is always “what changed?”, and this makes the answer instant.
| What to watch | Why it matters | Typical signal of trouble |
|---|---|---|
| Call duration | Flag reads sit on the hot path | Slow growth in response time |
| Failure rate | Shows service or network problems | Rising errors or timeouts |
| Fallback count | Shows how often defaults are used | A sudden jump |
| Document age | Shows whether local evaluation refreshes | Age far above the refresh interval |
| Admin changes | Shows who changed production | Changes at odd hours or by unknown users |
A car dashboard has a speedometer, a fuel gauge, and a warning light for the engine. You do not wait for the car to stop moving to find out something was wrong. Good monitoring gives your API usage the same kind of dashboard, so problems show up as small warning lights instead of big breakdowns.
22Versions, Documentation, and Staying Compatible
APIs evolve. Knowing how to read the docs and stay compatible keeps your integrations from breaking quietly.
Versions in the address
Web APIs commonly include a version in the path, so that the service can improve without breaking existing callers. Flagsmith’s current main version appears in its paths. When a new version appears, the old one is normally kept for a time, so you can migrate calmly. Always read the release notes of the version you run, especially for a self-hosted installation, where you decide when to upgrade.
Interactive documentation
The API is described in a standard machine-readable format, and the documentation lets you browse every resource, field, and allowed action, and often try requests from the page. For a self-hosted server, the same documentation for your exact version is usually served by the server itself. When you doubt what a field does, the documentation for your version is the authority, ahead of any article, including this one.
Write tolerant clients
Services add new fields to responses over time. A tolerant client ignores fields it does not recognise instead of failing. A strict client that rejects unknown fields will break the day a harmless field is added. Likewise, do not depend on the order of fields or on undocumented behaviour.
Test against upgrades
Before upgrading a self-hosted Flagsmith, run your automated tests and scripts against a staging copy of the new version. Pay attention to changes in authentication, pagination, and the shape of responses. After the upgrade, watch your error rates and fallback counts for unusual changes.
flowchart LR
R["Read release notes"] --> S["Upgrade a staging copy"]
S --> T["Run tests and scripts"]
T --> D{"All healthy?"}
D -->|"Yes"| P["Upgrade production"]
D -->|"No"| F["Fix and test again"]
F --> T
P --> W["Watch errors and fallbacks"]
Details in this guide, such as exact paths, header formats, and field names, can change between versions. Treat the documentation for your own version as the final word, and use this guide to understand the ideas.
23The API or an SDK? Making the Choice
Most of the time an SDK is the right tool. Sometimes calling the API directly is better.
What an SDK adds
An SDK, or software development kit, wraps the API in friendly functions for a particular language. It handles building requests, reading responses, caching, default values, local evaluation, and sometimes background refreshing and retries. It saves effort and avoids many mistakes.
When the raw API is the better choice
- No SDK exists for your language or platform.
- You are writing a small script, such as a one-off report or a cleanup task.
- You need an Admin API feature that the SDK does not expose, which is the usual case, since SDKs focus on reading flags.
- You are building your own tool, such as a chat bot that flips flags or a dashboard that shows flag status.
| Situation | Best choice | Reason |
|---|---|---|
| Application reading flags at runtime | SDK | Caching, defaults, and local evaluation built in |
| Busy backend service | SDK in local mode | Near-instant checks with minimal load |
| Pipeline creating and flipping flags | Admin API | SDKs do not manage resources |
| Language without an SDK | SDK API directly | Nothing else is available |
| Reporting and cleanup scripts | Admin API | Needs lists, filters, and audit data |
Keep your own thin layer
Whatever you choose, put a small layer of your own between your application code and Flagsmith, with a simple method such as “is this feature enabled for this user”. This keeps defaults, logging, and error handling in one place. It also makes it easier to change tools later, or to adopt the OpenFeature standard, which defines a vendor-neutral way to ask for flags and has providers that connect it to Flagsmith.
You could build a table from raw wood using only a saw and nails, or use a ready-made kit with all the parts cut and labelled. The kit is quicker and safer for the usual table. But if you want a very unusual shape, you go back to the saw. SDKs are the kit, and the raw API is the saw.
24Automating with the Admin API
The real prize of the Admin API is doing automatically what would otherwise be slow, repetitive, and easy to get wrong.
Pipelines
A delivery pipeline can call the Admin API at several points. It can create the flag a new feature needs, enable it in test environments after a build passes, and check that production flags have owners before a release. Because the pipeline records what it did, you gain an automatic history alongside the audit log.
Infrastructure as code
Some teams describe their flags, segments, and environments in files kept under version control and apply them with a tool, so that the setup can be reviewed, repeated, and rebuilt. A community or vendor-supported provider for popular infrastructure tools exists for Flagsmith, which lets you manage resources this way. Check the current documentation for what is supported. The benefit is that changes go through code review, like any other change.
Chat-based operations
A small chat bot can call the Admin API to answer questions such as “is the new checkout on in production?” or to flip a flag after the right person confirms. This puts the controls where the team already talks. Keep it safe by requiring approval for production changes, restricting who may use it, and logging every command.
Hygiene jobs
Scheduled jobs can keep the flag list tidy. One job lists flags older than a chosen age and posts them to the owning team. Another finds flags that are on for everybody and have been for months, which are candidates for removal. Another reports identity overrides that were created long ago. These small jobs prevent the slow build-up of clutter.
flowchart LR
SCHED["Scheduler"] --> JOB["Hygiene job"]
JOB -->|"List features and ages"| ADMIN["Admin API"]
ADMIN --> JOB
JOB --> REP["Report of old or unowned flags"]
REP --> CHAT["Team chat or ticket"]
Rules for safe automation
- Use a dedicated credential with the least power needed, never a person’s token.
- Provide a dry-run mode and read its output before the first real run.
- Make scripts safe to run twice.
- Fail loudly and alert a human on errors.
- Respect rate limits and use backoff.
- Keep scripts in version control and review changes to them.
- Record what was changed and why, in the tool’s own log or in a ticket.
Everyday use case: the Monday flag report
Every Monday a scheduled job reads the list of features, finds those older than ninety days with no recent changes, and posts them to the team chat grouped by owner. Owners reply with “keep” or “remove”. Within a quarter, the number of stale flags falls sharply, and nobody had to remember to check.
25Design Patterns for Using the API
A handful of proven shapes cover most real integrations.
Pattern 1: Decide at the edge, pass it along
In a system of many small services, the first service to receive a request asks for the flags once and passes the decision to the others in the request context. This keeps every service consistent for the same user, and saves repeated calls. Analogy: a relay race where one baton is handed from runner to runner, rather than each runner picking up a new one.
Pattern 2: A flag service wrapper
All application code asks one small internal module, “is this enabled for this user”, and only that module talks to Flagsmith. Defaults, logging, caching, and error handling live there. Analogy: a hotel concierge who deals with every outside company so that guests never have to.
Pattern 3: Local evaluation for busy servers
High-traffic backends download the environment document, refresh it on a schedule, and answer every check from memory. Analogy: a printed rulebook refreshed each morning rather than a phone call for every question.
Pattern 4: A backend-for-frontend
For web and mobile apps, a small back-end service asks Flagsmith with a server-side key and returns only the flags the app needs. The app never holds a powerful key and never sees the full rules. Analogy: a waiter who reads the kitchen’s rulebook and tells you only what you may order.
Pattern 5: Server-side rendering with flags
A web server fetches the flags before drawing a page and sends them with the page, so the user never sees a flicker between the old and new designs. Analogy: setting the stage before the curtain opens, instead of rearranging furniture while the audience watches.
Pattern 6: Reconcile on a schedule
A scheduled job compares the flags in the project with the flags actually referenced in your code and reports any that exist in only one of them. Analogy: a stock-take that compares the shelf with the inventory list.
flowchart LR
APP["Mobile or Web App"] -->|"Ask for needed flags"| BFF["Your Back-End Service"]
BFF -->|"Server key, local evaluation"| FS["Flagsmith"]
BFF --> APP
Choosing a pattern
Start with the simplest pattern that fits: an SDK with a wrapper. Add local evaluation when traffic grows. Add a back-end-for-frontend when you need to protect rules or reduce what apps hold. Add edge decisions when many services must agree. Complexity should arrive only when a real need arrives.
26Anti-Patterns and Common Mistakes
These are the traps that catch teams over and over. Learn them once and save yourself the pain.
One request per flag check
Code that sends a separate request for each flag, on each page, creates enormous traffic and slows every page.
The fix
Fetch all flags once per request or use local evaluation, then read from memory.
No timeout and no default
A flag request with no time limit and no fallback turns a small service delay into a full application outage.
The fix
Always set a short timeout and a safe default, and test the failure path on purpose.
Admin credentials in the wrong place
A powerful token pasted into a build file, a chat, or a public repository can let a stranger change production.
The fix
Use a secrets manager, narrow permissions, and rotation. Revoke anything that has been exposed.
Reading only the first page
A script that does not follow the next-page link sees only part of the list and makes wrong decisions, such as deleting flags it believes are unused.
The fix
Always loop until there is no next page, and compare totals.
Retrying blindly
Retrying immediately and forever, or retrying errors that cannot succeed, adds load to a struggling service and delays real fixes.
The fix
Retry only temporary failures, with growing waits, random jitter, and a limit.
More mistakes to avoid
- Using the wrong key kind. A client-side key cannot fetch the environment document, and a server-side key must never be public.
- Mixing up environments. Pointing a test app at the Production key is a classic way to flip real flags by accident.
- Trusting a flag for security. A flag hides a button. It does not lock the door behind it.
- Letting local evaluation go stale unnoticed. Track the age of the document and alert on it.
- Running scripts without a dry run. A bulk change that runs for the first time in Production is a gamble.
- Hard-coding addresses. The base address belongs in configuration, so you can switch between hosted and self-hosted or between regions.
- Ignoring unknown fields. Strict parsing that fails on new fields breaks on harmless upgrades.
27Best Practices Checklist
If you remember only a few pages of this guide, make them these.
Right key, right place
Client keys in apps, server keys on servers, Admin credentials only in secrets managers.
One key per use
Separate credentials per environment and per application, so a leak has a small reach.
Timeout plus default
Every runtime flag read has a short timeout and a safe fallback.
Read once, use many times
Fetch all flags together, or use local evaluation on busy servers.
React to the code
Retry temporary failures with backoff and jitter. Fix and report permanent ones.
Follow every page
Loop until there is no next page, and use filters to ask for less.
Dry run first
Print what would change, review it, then apply, and make scripts safe to repeat.
Watch and mark
Graph call speed, failures, and fallbacks, and mark flag changes on your charts.
Send the minimum
Use internal IDs and simple categories, never sensitive personal details.
One thin wrapper
Keep all Flagsmith calls behind a small module of your own.
Rehearse in staging
Test scripts and apps against a new version before upgrading production.
Automate the clean-up
Scheduled reports on old flags and old overrides keep clutter from growing.
A starter routine
If you are new to the Flagsmith API, begin in a test project. Read flags with an environment key, then send an identity with a trait and watch the answer change. Next, use an Admin credential to create a flag and flip it, and read the audit log entry that appears. Finally, write a small dry-run script that lists your features and their ages. In an afternoon you will have touched every important idea in this guide.
28Real-World Usage Scenarios
Common ways teams use the two APIs together. These are general practices, not claims about any named customer.
A safe payment-provider switch
An online store replaces its payment provider. A pipeline creates a flag through the Admin API, and the checkout code reads it through the SDK API. Staff go first, then one percent of customers, then more, with the rollout steps applied by a script at agreed times. When error graphs stay flat, the last step turns the flag on for everyone, and a cleanup job later removes the flag.
Support tools that unlock features
A support agent uses an internal tool to give one customer early access to a feature. Behind the tool, a small service calls the Admin API to create an identity override for that customer. Each use is logged, and a weekly job lists overrides older than thirty days for review.
Mobile apps and old versions
A travel app sends its version number as a trait on every identities request. A segment matches version six and above, and the new booking screen is attached to that segment. Users on older versions never see a screen their app cannot draw.
A busy backend with local evaluation
A video service runs hundreds of servers. Each downloads the environment document once a minute and answers all flag checks in memory. During a traffic spike, an engineer turns off a heavy recommendation row with one Admin API call from a chat bot, and within a minute every server has the new rules, while the rest of the experience carries on.
Compliance reporting
A regulated company copies the audit log through the Admin API into its own long-term storage every night. Auditors can see who changed which flag, and when, without needing access to the Flagsmith dashboard.
Environment cloning for new teams
When a new team joins, a script creates a project with the standard environments, copies the agreed segments, and creates the common flags with default states. What took half a day of clicking now takes minutes and is the same every time.
In all of these stories there are two sets of people. Visitors come and ask quick questions at the front desk, and staff work in the back office changing the rules. The two APIs let both groups do their jobs at once, without getting in each other’s way.
29Advantages, Disadvantages, and Trade-offs
A fair look at what the API design gives you and what it asks of you.
Advantages
- Everything the dashboard does can be automated.
- A clear split between a fast read API and a powerful management API.
- Two kinds of environment keys, so apps hold safe, limited credentials.
- Local evaluation removes nearly all runtime network traffic on servers.
- Standard REST and JSON work from any language.
- Interactive documentation for the exact version you run.
- Audit logs and webhooks give visibility into changes.
- Open source, so self-hosting keeps data and traffic in your control.
Disadvantages
- Two APIs and several credentials to learn and protect.
- Powerful credentials are a serious risk if mishandled.
- Local evaluation trades freshness for speed.
- Rate limits and retries need careful handling in automation.
- Self-hosting makes you responsible for uptime, scaling, and upgrades.
- Details can change between versions, so scripts need testing on upgrades.
- Raw API use means writing your own caching, defaults, and error handling.
The main trade-offs, in plain words
| Choice | You gain | You give up |
|---|---|---|
| Local evaluation | Speed and tiny load | Instant freshness; rules sit in server memory |
| Remote evaluation | Latest answers, rules stay private | A network trip for each check |
| SDK | Convenience and safety | Some control and Admin features |
| Raw API | Full control | You build caching and error handling |
| Hosted service | Little operating effort | Some control over hosting details |
| Self-hosted | Full control of data and network | You run and secure it |
30Troubleshooting Guide
When something looks wrong, work through the cause by symptom.
| Symptom | Likely cause | What to check |
|---|---|---|
| Every request is rejected as unauthorised | Wrong, missing, or revoked credential | Header name and spelling, key for the right environment, whether the key was rotated |
| Request is refused as forbidden | Valid credential without permission | Role of the user or key, and the action attempted |
| Flags return but segment rules never apply | No identity was sent | Use the identities request, not the environment-level one |
| Segment rule does not match | Trait missing, misspelled, or wrong type | Trait name and case, and number versus text |
| Change in dashboard not visible in the app | Caching or refresh interval | Local evaluation refresh time, app caches, and the environment used |
| Fetching the environment document fails | Client-side key in use | Use a server-side key for that request |
| List seems incomplete | Only the first page was read | Follow next-page links to the end |
| Requests suddenly rejected for volume | Rate limit reached | Request rate, retry loops, and batching; add backoff with jitter |
| Slow flag lookups | Network trip per check or no connection reuse | Use local evaluation, caching, and persistent connections |
| Flag exists but code gets the default | Name mismatch or wrong environment | Exact name, environment key, and logs of fallbacks |
| Webhook receiver not triggered | Wrong address or blocked network path | Webhook address, firewall rules, and delivery history |
A calm routine for any problem
Check what changed
Read the audit log and recent deployments before looking anywhere else.
Read the status code
The first digit tells you whether the fault is with the request or with the service.
Confirm the basics
Right address, right key, right environment, right identity.
Reproduce in isolation
Make the same request from a simple tool, outside your application, to see if it behaves the same way.
Fix, then add a guard
Once fixed, add a log, an alert, or a test so the same problem is caught earlier next time.
31A Worked Walkthrough: One Feature from Idea to Launch
Let us follow a single feature through both APIs, step by step, to see how all the pieces fit together.
Imagine a team building a new “saved carts” feature for an online store. The team wants to release it safely, to a few customers first. Here is how the two APIs help at each stage.
Step 1: Create the flag with the Admin API
When the developer opens the pull request, a pipeline step calls the Admin API with a pipeline credential. It asks for the features of the project, finds that no flag called “saved-carts” exists, and creates one with a description, an owner tag, and an initial state of off. The reply carries the new feature’s identifying number, which the pipeline records in the pull request comments.
Step 2: Read the flag with the SDK API
The new code reads the flag through the SDK, using the server-side key and local evaluation. The code asks “is saved carts enabled for this customer?” and, if the answer is missing for any reason, defaults to off. Because the flag is off everywhere, merging the code changes nothing for customers.
Step 3: Turn it on for testing
After the build passes, the pipeline calls the Admin API to change the feature state of “saved-carts” to on in the Development and Staging environments. Testers now see the feature. Production is untouched, since it has its own feature state.
Step 4: Target staff and a beta group
A product manager creates a segment for staff using a trait that marks employees, and a second segment for customers who joined the beta programme. Segment overrides turn the flag on for both groups in Production. The application already sends the customer number and these traits with the identities request, so the rules apply at once.
Step 5: A gradual rollout
The team adds a percentage rule, starting at one percent of all customers. Each time they widen the audience, they update the rule through the Admin API, on a schedule agreed in advance. A webhook posts each change to the team chat, and the monitoring tool marks each change on the error graph.
Step 6: A problem appears, and is solved quickly
At ten percent, the error graph rises for customers using a certain older app version. The on-call engineer uses the chat bot, which calls the Admin API, to turn the flag off in Production. Within about a minute, every server has refreshed its document and the errors stop. The team adds a rule using the app version trait so that only versions able to handle the feature receive it, and resumes the rollout.
Step 7: Launch and clean up
At one hundred percent, the team waits a week. Then a cleanup task confirms through the audit log and the usage reports that the flag is on for everyone, and removes the flag and the old code path. The code ends up simpler than before.
sequenceDiagram
participant Dev as Developer Pipeline
participant Admin as Admin API
participant App as Application Servers
participant SDK as SDK API
participant Team as Team Chat
Dev->>Admin: Create flag and add owner
App->>SDK: Download environment document
Dev->>Admin: Enable in Development and Staging
Dev->>Admin: Add segment overrides and one percent rule
Admin->>Team: Webhook announces each change
App->>SDK: Refresh document each minute
Dev->>Admin: Widen rollout, or switch off if needed
Dev->>Admin: Delete flag after launch
Think of opening a new ride at a theme park. Engineers prepare it behind a fence, staff test it, a small group of guests try it, and the queue is opened slowly to everyone. If a fault appears, the operator presses a stop button and the ride halts at once. The Admin API is the control room with the buttons, and the SDK API is the loudspeaker that tells every gate what to do.
32A Production-Readiness Checklist for API Use
Before you depend on the Flagsmith API in production, walk through these questions with your team.
| Area | Question to answer | A good answer sounds like |
|---|---|---|
| Keys | Where does each key live, and who can read it? | Secrets are in a manager, and client-side keys are the only ones in front-end code |
| Environments | Could a test app reach production flags? | Each environment has its own keys, and apps load the right one from configuration |
| Defaults | What does every flag do when no answer arrives? | Each flag has a safe default, tested by cutting the network on purpose |
| Timeouts | How long may a flag read wait? | A short, deliberate timeout with a cached fallback |
| Speed | How many requests will we send at peak? | We read once per request or use local evaluation, and we have estimated the numbers |
| Freshness | How old may our answers get? | We know the refresh interval, and critical flags refresh faster |
| Errors | Which failures do we retry? | Only temporary ones, with backoff, jitter, and a limit |
| Automation | Can a script harm production? | Narrow credentials, dry runs, safe repeats, and loud failures |
| Visibility | Will we notice a problem quickly? | We graph call speed, failures, fallbacks, and document age, and mark flag changes |
| Privacy | What personal data do we send? | Only internal IDs and simple categories, with a way to delete an identity |
| Governance | Who may change production flags? | A named small group, with approvals for sensitive flags and the audit log enabled |
| Recovery | If we self-host, can we restore it? | Backups exist, and the restore has been tested |
| Upgrades | How will we test a new version? | We rehearse scripts and apps against a staging copy first |
How to use the checklist
Hold a short review meeting before your first production launch, and again each time your use grows in a major way. Go through each row and ask for a real answer, not a hope. Any row where the team shrugs is a row where something will eventually go wrong. Write down the gaps, give each an owner, and fix the most dangerous first.
Turn the checklist into a standing agenda item for your regular flag review. Teams that look at their API usage together every few months catch drifting keys, forgotten overrides, and silent refresh failures before any of them cause an incident.
33Glossary of Terms
Every important word in this guide, in one place.
| Term | Meaning |
|---|---|
| API | An agreed set of requests and replies that lets one program talk to another. |
| SDK API | The Flagsmith API your applications call to read flags and identity data. |
| Admin API | The Flagsmith API used to create, change, and delete resources; used by the dashboard and by automation. |
| Edge API | A globally distributed serving layer that answers flag reads near the caller. |
| REST | A style of web API in which each kind of thing has its own address and a few verbs act on it. |
| JSON | A simple text format for sending structured data. |
| Header | A labelled note sent along with a request or response, such as the one that carries a credential. |
| Status code | A three-digit number summarising the result of a request. |
| Environment key | The credential used with the SDK API to identify one environment. |
| Client-side key | A public environment key safe to place in browsers and apps. |
| Server-side key | A secret environment key that can read full rules; for servers only. |
| User token | An Admin API credential that acts with one person’s permissions. |
| Organisation API key | An Admin API credential meant for automation, not tied to one person. |
| Identity | A unique ID representing one user, device, or account. |
| Trait | A fact about an identity, used by segment rules. |
| Segment | A saved group of identities defined by rules over traits. |
| Feature | The definition of a flag or config value, shared by all environments of a project. |
| Feature state | How a feature behaves in one environment: its on/off setting and value. |
| Environment document | The full configuration of an environment, downloaded for local evaluation. |
| Local evaluation | Answering flag checks inside your own server from a downloaded document. |
| Pagination | Splitting a long list into pages that are fetched one at a time. |
| Rate limit | A cap on how many requests a caller may make in a period. |
| Exponential backoff | Waiting longer after each failed attempt before retrying. |
| Jitter | A small random amount added to waits so that many clients do not retry together. |
| Circuit breaker | Logic that stops calling a failing service for a while to let it recover. |
| Webhook | An automatic message sent to an address you choose when something happens. |
| Audit log | A record of who changed what and when. |
| OpenFeature | An open standard that defines a vendor-neutral way to ask for flags. |
34Frequently Asked Questions
35Summary and Key Takeaways
The Flagsmith API is the foundation under every flag, every rule, and every dashboard click. It is split into two parts with two audiences: a fast, read-focused SDK API for your running applications, and a broad, powerful Admin API for people and automation. Learn the split, keep the keys in the right places, plan for failure, and automate carefully, and the API becomes one of your strongest tools for shipping safely.
Key Takeaways
- Two APIs: the SDK API reads flags for applications; the Admin API manages everything and is used by the dashboard and by automation.
- Keys decide power: client-side keys are public and limited, server-side keys are secret and read full rules, and Admin credentials can change production.
- Identities unlock targeting: send a stable identifier and a few well-chosen traits to get personalised answers; without an identity, everyone gets the same default.
- Speed comes from not asking: fetch flags together, cache, and use local evaluation on busy servers, accepting a short refresh delay.
- Plan for failure: use short timeouts, layered fallbacks, safe defaults, circuit breakers, and retries with backoff and jitter.
- Automate safely: least-privilege credentials, dry runs, safe repeats, loud failures, and respect for rate limits and pagination.
- Stay secure and visible: use HTTPS, protect and rotate secrets, send minimal data, watch call speed and fallbacks, and mark every flag change on your graphs.