API reference
Read your feature flags via REST
The GreenFlags read API serves the flags of one environment over plain HTTPS, evaluated at the edge. Any language that can send a GET request can consume it — no SDK required.
Quickstart
- Create your free account — you get a workspace, a project and your environments.
- In the dashboard, open your project → pick an environment (e.g.
production) → API Tokens → create a token. - Copy the token (
gf_…) — it is shown only once and stored hashed on our side. - Call the API:
curl https://app.greenflags.dev/v1/flags \
-H "Authorization: Bearer gf_your_token_here"
Authentication & tokens
Every request authenticates with a Bearer token in the Authorization header.
- Tokens are scoped to one environment. A
productiontoken can only ever readproductionflags — your staging credentials can never leak into prod reads, and vice versa. Create one token per environment. - Shown once, hashed at rest. If you lose a token, revoke it in the dashboard and create a new one — revocation is instant.
- Optional monthly quota per token. You can cap how many reads a token may perform per month; the limit is enforced at the edge.
- Keep it server-side. Treat the token like a password: use it from your backend, serverless functions or build pipeline — don't ship it inside public client-side code.
List all flags
Returns every active flag of the token's environment, with each flag's type and its current evaluated value.
https://app.greenflags.dev/v1/flagscurl https://app.greenflags.dev/v1/flags \
-H "Authorization: Bearer $GREENFLAGS_TOKEN"
Response 200:
{
"success": true,
"data": {
"flags": [
{ "key": "new-checkout", "type": "boolean", "value": true },
{ "key": "banner-text", "type": "string", "value": "Summer sale" }
]
}
}
Get one flag by key
Returns a single flag when you only need one value.
https://app.greenflags.dev/v1/flags/{key}curl https://app.greenflags.dev/v1/flags/new-checkout \
-H "Authorization: Bearer $GREENFLAGS_TOKEN"
Response 200:
{
"success": true,
"data": {
"flag": { "key": "new-checkout", "type": "boolean", "value": true }
}
}
/v1/flags and cache the snapshot for a short interval (30–60s) instead of one request per flag — fewer round trips, fewer billed reads.
Flag types
| Type | value contains | Example |
|---|---|---|
boolean | true / false | true |
string | A string | "Summer sale" |
number | A number | 42 |
json | An arbitrary JSON object | {"theme":"dark"} |
Each flag holds an independent value per environment — flipping it in production never touches staging.
Geofencing
You can scope a flag to a geographic radius in the dashboard. A geofenced flag includes its center and radius in meters:
{
"key": "store-promo",
"type": "boolean",
"value": true,
"geofence": {
"latitude": 19.4326,
"longitude": -99.1332,
"radiusMeters": 1000
}
}
Set the end user's coordinates in an official SDK and the evaluation happens locally in your application — the coordinates are never sent to GreenFlags. Inside the radius, the flag returns its normal value; outside it returns false for boolean flags and null for every other type. Flags without a geofence are unaffected.
Percentage rollouts & variants
From the dashboard you can release a flag gradually to a percentage of your users, or split users across weighted variants for A/B testing. Both are configured per environment and evaluated deterministically per user.
Resolve per user with ?user=
Both read endpoints accept an optional user query parameter — any stable identifier for the end user (user id, email, device id). When present, the API assigns the user and returns only the final value:
curl "https://app.greenflags.dev/v1/flags?user=user-42" \
-H "Authorization: Bearer $GREENFLAGS_TOKEN"
Assignment is deterministic: a hash of {flagKey}:{userKey} maps every user to a bucket from 0 to 99. The same user always receives the same value — on every call, in every SDK, on every platform.
Percentage rollout
A flag with a 30% rollout serves its stored value to users in buckets 0–29. Everyone else receives the off value: false for boolean flags, null for string, number and json flags. Raising the percentage only ever adds users — nobody who already has the feature loses it.
Variants (A/B testing)
Variants split users across several named values with weights that sum to at most 100. If the weights sum to less than 100, the remaining users receive the flag's base value. Without ?user=, the raw configuration is included in the response:
{
"key": "checkout-theme",
"type": "string",
"value": "classic",
"variants": [
{ "name": "A", "weight": 30, "value": "blue" },
{ "name": "B", "weight": 70, "value": "green" }
]
}
With ?user=, the server resolves the variant and the response carries only the assigned value — e.g. { "key": "checkout-theme", "type": "string", "value": "blue" }. A flag can use a percentage rollout or variants in a given environment, never both at once.
Local evaluation in SDKs
Without ?user=, the response includes the raw rollout / variants configuration so the official SDKs can evaluate locally from the cached snapshot — no extra requests per user. Client SDKs (JS/TS, React, Vue, Flutter) take the identity once via setUser("user-42") (with an anonymous fallback id); server SDKs (Go, PHP, Python) take the user per call, e.g. GetFlagForUser("checkout-theme", "user-42").
Errors
Errors always use the same envelope: { "success": false, "error": "CODE", "message": "…" }.
| Status | Code | Meaning |
|---|---|---|
401 | INVALID_TOKEN | Missing, malformed or revoked token. |
404 | FLAG_NOT_FOUND | No active flag with that key in this environment. |
429 | QUOTA_EXCEEDED | The token hit its monthly read quota. |
429 | BILLING_* | The workspace plan ran out of reads for the period — top up or subscribe in the dashboard. |
Prefer an SDK?
Every SDK wraps this same API with the same billing-safe model: one request fetches the whole environment, every read after that is served from memory.
| Platform | Package | Install |
|---|---|---|
| JavaScript / TypeScript | @greenflags/client | npm i @greenflags/client |
| React (hooks) | @greenflags/react | npm i @greenflags/react |
| Vue 3 (composables) | @greenflags/vue | npm i @greenflags/vue |
| Flutter / Dart | greenflags | flutter pub add greenflags |
| Python | greenflags | pip install greenflags |
| Go | greenflags-go | go get github.com/greenflags-dev/greenflags-go |
| PHP / Laravel | greenflags/greenflags-php | composer require greenflags/greenflags-php |
| AI agents (MCP) | @greenflags/mcp | npx @greenflags/mcp |
Example with the TypeScript client — types, snapshot caching and zero runtime dependencies:
import { GreenFlags } from "@greenflags/client";
const flags = new GreenFlags({ token: process.env.GREENFLAGS_TOKEN });
if (await flags.isEnabled("new-checkout")) {
renderNewCheckout();
}
And if you work with AI agents, the @greenflags/mcp server lets assistants manage your flags through the Model Context Protocol.