12 KiB
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)
Source of truth: Cloudflare Flagship API reference. Use it to verify REST paths, envelopes, response fields, and permission wording before relying on examples here.
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>
Management endpoints use the Cloudflare v4 envelope. On success, the payload is under result; errors are an array under errors.
// Success
{ "success": true, "result": <T>, "errors": [], "messages": [] }
// Paginated success
{
"success": true,
"result": [<T>],
"result_info": { "count": 50, "cursor": "next-cursor-or-null" },
"errors": [],
"messages": []
}
// Error
{ "success": false, "result": null, "errors": [{ "message": "message" }], "messages": [] }
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 the com.cloudflare.account.flagship.evaluate permission. Context attributes passed as query params. This endpoint is not wrapped in the management envelope; the SDK contract returns OpenFeature-style camelCase:
{
"flagKey": "my-flag",
"value": true,
"variant": "on",
"reason": "SPLIT"
}
Reasons: TARGETING_MATCH, SPLIT, DEFAULT, DISABLED.
Management Response Payloads
Management endpoints are wrapped in the Cloudflare v4 envelope shown above. Common .result payloads:
App result
{
"id": "app-uuid",
"name": "my-app",
"created_at": "2026-06-09T12:00:00.000Z",
"updated_at": "2026-06-09T12:00:00.000Z",
"updated_by": "user@example.com"
}
Flag result
{
"key": "my-flag",
"type": "boolean",
"default_variation": "off",
"variations": { "on": true, "off": false },
"rules": [],
"description": "Enables the new feature",
"enabled": true,
"updated_at": "2026-06-09T12:00:00.000Z",
"updated_by": "user@example.com"
}
Changelog entry
{
"flag_key": "my-flag",
"event": "update",
"after": { "key": "my-flag", "default_variation": "off", "variations": { "on": true, "off": false }, "rules": [], "enabled": true },
"diff": { "enabled": { "from": false, "to": true } }
}
Changelog entries include the full flag state after the change. update entries also include diff.
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 errors[].message) |
| 401 | Invalid or missing token |
| 404 | Flag or app not found |
| 409 | Flag key already exists (create) |
| 429 | Rate limited |