Flagship API Reference
Binding API (Workers)
The binding is available as env.FLAGS (type Flagship from @cloudflare/workers-types).
Evaluation Methods
All methods are async, never throw, and return the defaultValue on errors.
| Method | Signature | Returns |
|---|---|---|
get | get(flagKey, defaultValue?, context?) | Promise<unknown> |
getBooleanValue | getBooleanValue(flagKey, defaultValue, context?) | Promise<boolean> |
getStringValue | getStringValue(flagKey, defaultValue, context?) | Promise<string> |
getNumberValue | getNumberValue(flagKey, defaultValue, context?) | Promise<number> |
getObjectValue | getObjectValue<T>(flagKey, defaultValue, context?) | Promise<T> |
getBooleanDetails | getBooleanDetails(flagKey, defaultValue, context?) | Promise<FlagshipEvaluationDetails<boolean>> |
getStringDetails | getStringDetails(flagKey, defaultValue, context?) | Promise<FlagshipEvaluationDetails<string>> |
getNumberDetails | getNumberDetails(flagKey, defaultValue, context?) | Promise<FlagshipEvaluationDetails<number>> |
getObjectDetails | getObjectDetails<T>(flagKey, defaultValue, context?) | Promise<FlagshipEvaluationDetails<T>> |
Parameters (shared across all methods)
| Parameter | Type | Required | Description |
|---|---|---|---|
flagKey | string | Yes | Flag key to evaluate |
defaultValue | varies | Yes (except get) | Fallback if evaluation fails or flag not found |
context | FlagshipEvaluationContext | No | Attributes for targeting rules ({ userId: "user-42", country: "US" }) |
Types
type FlagshipEvaluationContext = Record<string, string | number | boolean>;
interface FlagshipEvaluationDetails<T> {
flagKey: string;
value: T;
variant?: string; // name of the matched variation
reason?: string; // "TARGETING_MATCH" | "DEFAULT" | "DISABLED" | "SPLIT"
errorCode?: string; // "TYPE_MISMATCH" | "GENERAL"
errorMessage?: string;
}Example
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const enabled = await env.FLAGS.getBooleanValue("new-feature", false, {
userId: "user-42",
});
return new Response(enabled ? "Feature on" : "Feature off");
},
};OpenFeature SDK
Package: @cloudflare/flagship
Server Provider (FlagshipServerProvider)
For Workers, Node.js, and server-side JavaScript.
With binding (recommended inside Workers):
import { OpenFeature } from "@openfeature/server-sdk";
import { FlagshipServerProvider } from "@cloudflare/flagship";
await OpenFeature.setProviderAndWait(
new FlagshipServerProvider({ binding: env.FLAGS }),
);
const client = OpenFeature.getClient();
const enabled = await client.getBooleanValue("new-checkout", false, {
targetingKey: "user-42",
});With app ID (Node.js / non-Worker runtimes):
import { OpenFeature } from "@openfeature/server-sdk";
import { FlagshipServerProvider } from "@cloudflare/flagship";
await OpenFeature.setProviderAndWait(
new FlagshipServerProvider({
appId: "<APP_ID>",
accountId: "<ACCOUNT_ID>",
authToken: "<API_TOKEN>",
}),
);
const client = OpenFeature.getClient();
const enabled = await client.getBooleanValue("new-checkout", false, {
targetingKey: "user-42",
});Client Provider (FlagshipClientProvider)
For browser applications. Pre-fetches flags on init, evaluates synchronously.
import { OpenFeature } from "@openfeature/web-sdk";
import { FlagshipClientProvider } from "@cloudflare/flagship";
await OpenFeature.setProviderAndWait(
new FlagshipClientProvider({
appId: "<APP_ID>",
accountId: "<ACCOUNT_ID>",
authToken: "<API_TOKEN>",
prefetchFlags: ["promo-banner", "dark-mode"],
}),
);
await OpenFeature.setContext({ targetingKey: "user-42", plan: "enterprise" });
const client = OpenFeature.getClient();
// Synchronous — no await needed
const showBanner = client.getBooleanValue("promo-banner", false);Important: Only flags listed in prefetchFlags are available. Unlisted flags return FLAG_NOT_FOUND.
SDK Hooks
import { LoggingHook, TelemetryHook } from "@cloudflare/flagship";
OpenFeature.addHooks(new LoggingHook(), new TelemetryHook());REST API (Flag Management)
FIRST: Check Prerequisites
Before making any REST API calls (create, read, update, delete, toggle flags), verify these environment variables are set:
| Variable | Purpose | How to get |
|---|---|---|
CLOUDFLARE_ACCOUNT_ID | Account identifier | Dashboard URL or wrangler whoami |
CLOUDFLARE_API_TOKEN | Bearer token for API auth | Create API token with Flagship permissions |
FLAGSHIP_APP_ID | Target app UUID | Dashboard under Compute > Flagship, or GET /apps endpoint |
Check with:
echo "CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID:-(not set)}"
echo "CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN:-(not set)}"
echo "FLAGSHIP_APP_ID=${FLAGSHIP_APP_ID:-(not set)}"If any are missing, ask the user to provide them before proceeding.
Base URL and Auth
Base URL: https://api.cloudflare.com/client/v4/accounts/{account_id}/flagship
Authentication: Authorization: Bearer <API_TOKEN>
Response envelope:
// Success
{ "success": true, "data": <T> }
// Error
{ "success": false, "error": "message" }App Endpoints
| Method | Path | Description |
|---|---|---|
GET | /apps | List all apps |
GET | /apps/{app_id} | Get app |
POST | /apps | Create app ({ "name": "my-app" }) |
PUT | /apps/{app_id} | Update app ({ "name": "new-name" }) |
DELETE | /apps/{app_id} | Delete app |
App name constraints: alphanumeric + hyphens + underscores, 1-64 chars.
Flag Endpoints
| Method | Path | Description |
|---|---|---|
GET | /apps/{app_id}/flags?limit=50&cursor=<cursor> | List flags (paginated) |
GET | /apps/{app_id}/flags/{flag_key} | Get flag |
POST | /apps/{app_id}/flags | Create flag |
PUT | /apps/{app_id}/flags/{flag_key} | Update flag (full replace) |
DELETE | /apps/{app_id}/flags/{flag_key} | Delete flag |
GET | /apps/{app_id}/flags/{flag_key}/changelog?limit=20&cursor=<cursor> | Flag changelog |
Evaluate Endpoint
GET /apps/{app_id}/evaluate?flagKey=<key>&<context-attrs>Requires an API token with flagship:evaluate permission. Context attributes passed as query params. Returns:
{
"flagKey": "my-flag",
"value": true,
"variant": "on",
"reason": "TARGETING_MATCH"
}FlagDefinition Schema
{
"key": "my-flag",
"type": "boolean",
"default_variation": "off",
"variations": {
"on": true,
"off": false
},
"rules": [
{
"priority": 1,
"conditions": [
{
"attribute": "email",
"operator": "ends_with",
"value": "@cloudflare.com"
}
],
"serve_variation": "on",
"rollout": { "percentage": 100 }
}
],
"description": "Enables the new feature",
"enabled": true
}Field Constraints
| Field | Type | Constraints |
|---|---|---|
key | string | 1-64 chars, /^[a-zA-Z0-9_-]+$/ |
type | enum | Optional. boolean, string, number, json (auto-inferred from variations) |
default_variation | string | Must be a key in variations |
variations | Record<string, T> | At least one. All values same type. Keys: alphanumeric/hyphens/underscores, max 64 chars. Values max 10KB. |
rules | Rule[] | Can be empty. No duplicate priorities. |
description | string? | Max 512 chars, nullable |
enabled | boolean | Required. false = always returns default variation. |
Rule Schema
{
"priority": 1,
"conditions": [ /* Condition[] */ ],
"serve_variation": "on",
"rollout": { "percentage": 50, "attribute": "targetingKey" }
}priority: integer >= 1, unique across rules in the flag (lower = evaluated first)conditions: array of base or logical conditionsserve_variation: must be a key invariationsrollout: optional.percentage0-100.attributedefaults totargetingKey.
Condition Schema
Base condition:
{ "attribute": "email", "operator": "ends_with", "value": "@cloudflare.com" }Logical condition (AND/OR):
{
"logical_operator": "AND",
"clauses": [
{ "attribute": "country", "operator": "equals", "value": "US" },
{ "attribute": "plan", "operator": "in", "value": ["enterprise", "business"] }
]
}Nesting supported up to 6 levels deep.
Operators
| Operator | Description | Value Type |
|---|---|---|
equals | Exact match (case-sensitive) | String |
not_equals | Not exact match | String |
greater_than | Numeric / datetime > | Number, ISO 8601 |
less_than | Numeric / datetime < | Number, ISO 8601 |
greater_than_or_equals | >= | Number, ISO 8601 |
less_than_or_equals | <= | Number, ISO 8601 |
contains | Substring match (case-sensitive) | String |
starts_with | Prefix match | String |
ends_with | Suffix match | String |
in | Value in array | Array |
not_in | Value not in array | Array |
Rate Limits
| Operation | Limit |
|---|---|
| Mutations (POST/PUT/DELETE) | 60 per 60s per account:app |
| Reads (GET) | 600 per 60s per account:app |
Error Codes
| HTTP Status | Meaning |
|---|---|
| 200 | Success (read/update/delete) |
| 201 | Created (create) |
| 400 | Validation error (check error field) |
| 401 | Invalid or missing token |
| 404 | Flag or app not found |
| 409 | Flag key already exists (create) |
| 429 | Rate limited |