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

  1. Create your free account — you get a workspace, a project and your environments.
  2. In the dashboard, open your project → pick an environment (e.g. production) → API Tokens → create a token.
  3. Copy the token (gf_…) — it is shown only once and stored hashed on our side.
  4. 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.

List all flags

Returns every active flag of the token's environment, with each flag's type and its current evaluated value.

GET https://app.greenflags.dev/v1/flags
curl 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.

GET 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 }
  }
}
Tip: if your app reads several flags, prefer one call to /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

Typevalue containsExample
booleantrue / falsetrue
stringA string"Summer sale"
numberA number42
jsonAn 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.

Privacy and safety: geofencing is a local, fail-open targeting feature. If no coordinates are set, the flag keeps its normal value, so do not use a geofence as an authorization or security boundary.

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").

Combining with geofencing: rules chain with AND — the geofence is evaluated first; only users inside the radius are then bucketed by rollout or variants. If an input is missing (no coordinates, or no user), that rule is skipped and the rest still apply.

Errors

Errors always use the same envelope: { "success": false, "error": "CODE", "message": "…" }.

StatusCodeMeaning
401INVALID_TOKENMissing, malformed or revoked token.
404FLAG_NOT_FOUNDNo active flag with that key in this environment.
429QUOTA_EXCEEDEDThe token hit its monthly read quota.
429BILLING_*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.

PlatformPackageInstall
JavaScript / TypeScript@greenflags/clientnpm i @greenflags/client
React (hooks)@greenflags/reactnpm i @greenflags/react
Vue 3 (composables)@greenflags/vuenpm i @greenflags/vue
Flutter / Dartgreenflagsflutter pub add greenflags
Pythongreenflagspip install greenflags
Gogreenflags-gogo get github.com/greenflags-dev/greenflags-go
PHP / Laravelgreenflags/greenflags-phpcomposer require greenflags/greenflags-php
AI agents (MCP)@greenflags/mcpnpx @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.

Ready to ship behind flags? Create your token now — free to start, no credit card required.