The flags endpoint is used to evaluate feature flags for a given distinct_id. This means it is the main endpoint not only for feature flags, but also experimentation, early access features, and survey display conditions.
It is a POST-only public endpoint that uses your project API key and does not return any sensitive data from your PostHog instance.
Note: Make sure to send API requests to the correct domain. These are https://us.i.posthog.com for US Cloud, https://eu.i.posthog.com for EU Cloud, and your self-hosted domain for self-hosted instances. Confirm yours by checking your URL from your PostHog instance.
There are 3 steps to implement feature flags using the PostHog API:
Step 1: Evaluate the feature flag value using flags
flags is the endpoint used to determine if a given flag is enabled for a certain user or not.
Note: The groups key is only required for group-based feature flags. If you use it, replace group_type and group_id with the values for your group such as company: "Twitter".
Using evaluation context tags and runtime filtering without SDKs
When making direct API calls to the /flags endpoint, you can control which flags are evaluated using evaluation context tags and runtime filtering.
Evaluation contexts
To filter flags by evaluation context, include the evaluation_contexts field in your request body:
Note: The legacy parameter evaluation_environments is also supported for backward compatibility.
Only flags where at least one evaluation tag matches (or flags with no tags at all) will be returned. For example:
Flag with evaluation context tags ["production", "api", "backend"] + request with ["production", "web"] = ✅ Flag evaluates ("production" matches)
Flag with evaluation context tags ["staging", "api"] + request with ["production", "web"] = ❌ Flag doesn't evaluate (no tags match)
Flag with evaluation context tags ["web", "mobile"] + request with ["production", "web"] = ✅ Flag evaluates ("web" matches)
Flag with no evaluation context tags = ✅ Always evaluates (backward compatibility)
Runtime detection
Evaluation runtime (server vs. client) is automatically detected based on your request headers and user-agent. This determines which flags are available based on their runtime setting (server-only, client-only, or all).
How runtime is detected:
User-Agent patterns - The system analyzes the User-Agent header:
Client-side patterns: Mozilla/, Chrome/, Safari/, Firefox/, Edge/ (browsers), or mobile SDKs like posthog-android/, posthog-ios/, posthog-react-native/, posthog-flutter/
// Browser headers will trigger client runtime detection
},
body:JSON.stringify({
api_key:"<ph_project_api_key>",
distinct_id:"user-id",
evaluation_contexts:["production","web"]
})
});
// This request will only receive flags that:
// 1. Have runtime set to "client" OR "all" (due to browser headers)
// AND
// 2. Have evaluation context tags matching "production" OR "web" (or no tags)
// Note: You can also use the legacy "evaluation_environments" parameter
This allows precise control over which flags are evaluated in different contexts, helping optimize costs and improve security by ensuring flags only evaluate where intended.
Response
The response varies depending on whether you include the config=true query parameter:
Basic response (/flags?v=2)
Use this endpoint when you only need to evaluate feature flags. It returns a response with just the flag evaluation results.
Note: If a feature flag is associated with an experiment that has a holdout group, users in the holdout receive a variant value in the format holdout-{holdout_id} (e.g., holdout-727). You can detect holdout users by checking if the variant starts with holdout-.
Full response with configuration (/flags?v=2&config=true)
Use this endpoint when you need both feature flag evaluation and PostHog configuration information (useful for client-side SDKs that need to initialize PostHog):
// ... other fields, not relevant to feature flags
}
When you receive a response with quotaLimited containing "feature_flags", it means:
Your feature flag evaluations have been temporarily paused because you've exceeded your feature flag quota
If you want to continue evaluating feature flags, you can increase your quota in your billing settings under Feature flags & Experiments or contact support
Step 2: Include feature flag information when capturing events
If you want use your feature flag to breakdown or filter events in your insights, you'll need to include feature flag information in those events. This ensures that the feature flag value is attributed correctly to the event.
Note: This step is only required for events captured using our server-side SDKs or API.
To do this, include the $feature/feature_flag_name property in your event:
To track usage of your feature flag and view related analytics in PostHog, submit the $feature_flag_called event whenever you check a feature flag value in your code.
You need to include two properties with this event:
$feature_flag_response: This is the name of the variant the user has been assigned to e.g., "control" or "test"
$feature_flag: This is the key of the feature flag in your experiment.
Sometimes, you may want to evaluate feature flags using person properties, groups, or group properties that haven't been ingested yet, or were set incorrectly earlier.
You can provide properties to evaluate the flag with by using the person properties, groups, and group properties arguments. PostHog will then use these values to evaluate the flag, instead of any properties currently stored on your PostHog server.
By default, a user's GeoIP properties are set using the IP address they use to capture events on the frontend. You may want to override the these properties when evaluating feature flags. A common reason to do this is when you're not using PostHog on your frontend, so the user has no GeoIP properties.
To override the GeoIP properties used to evaluate a feature flag, provide an IP address in the HTTP_X_FORWARDED_FOR when making your /flags request: