Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/flagship/api.md
1# Flagship API Reference23## Binding API (Workers)45The binding is available as `env.FLAGS` (type `Flagship` from `@cloudflare/workers-types`).67### Evaluation Methods89All methods are async, never throw, and return the `defaultValue` on errors.1011| Method | Signature | Returns |12|--------|-----------|---------|13| `get` | `get(flagKey, defaultValue?, context?)` | `Promise<unknown>` |14| `getBooleanValue` | `getBooleanValue(flagKey, defaultValue, context?)` | `Promise<boolean>` |15| `getStringValue` | `getStringValue(flagKey, defaultValue, context?)` | `Promise<string>` |16| `getNumberValue` | `getNumberValue(flagKey, defaultValue, context?)` | `Promise<number>` |17| `getObjectValue` | `getObjectValue<T>(flagKey, defaultValue, context?)` | `Promise<T>` |18| `getBooleanDetails` | `getBooleanDetails(flagKey, defaultValue, context?)` | `Promise<FlagshipEvaluationDetails<boolean>>` |19| `getStringDetails` | `getStringDetails(flagKey, defaultValue, context?)` | `Promise<FlagshipEvaluationDetails<string>>` |20| `getNumberDetails` | `getNumberDetails(flagKey, defaultValue, context?)` | `Promise<FlagshipEvaluationDetails<number>>` |21| `getObjectDetails` | `getObjectDetails<T>(flagKey, defaultValue, context?)` | `Promise<FlagshipEvaluationDetails<T>>` |2223### Parameters (shared across all methods)2425| Parameter | Type | Required | Description |26|-----------|------|----------|-------------|27| `flagKey` | `string` | Yes | Flag key to evaluate |28| `defaultValue` | varies | Yes (except `get`) | Fallback if evaluation fails or flag not found |29| `context` | `FlagshipEvaluationContext` | No | Attributes for targeting rules (`{ userId: "user-42", country: "US" }`) |3031### Types3233```typescript34type FlagshipEvaluationContext = Record<string, string | number | boolean>;3536interface FlagshipEvaluationDetails<T> {37flagKey: string;38value: T;39variant?: string; // name of the matched variation40reason?: string; // "TARGETING_MATCH" | "DEFAULT" | "DISABLED" | "SPLIT"41errorCode?: string; // "TYPE_MISMATCH" | "GENERAL"42errorMessage?: string;43}44```4546### Example4748```typescript49export default {50async fetch(request: Request, env: Env): Promise<Response> {51const enabled = await env.FLAGS.getBooleanValue("new-feature", false, {52userId: "user-42",53});54return new Response(enabled ? "Feature on" : "Feature off");55},56};57```5859---6061## OpenFeature SDK6263Package: `@cloudflare/flagship`6465### Server Provider (`FlagshipServerProvider`)6667For Workers, Node.js, and server-side JavaScript.6869**With binding (recommended inside Workers):**7071```typescript72import { OpenFeature } from "@openfeature/server-sdk";73import { FlagshipServerProvider } from "@cloudflare/flagship";7475await OpenFeature.setProviderAndWait(76new FlagshipServerProvider({ binding: env.FLAGS }),77);78const client = OpenFeature.getClient();79const enabled = await client.getBooleanValue("new-checkout", false, {80targetingKey: "user-42",81});82```8384**With app ID (Node.js / non-Worker runtimes):**8586```typescript87import { OpenFeature } from "@openfeature/server-sdk";88import { FlagshipServerProvider } from "@cloudflare/flagship";8990await OpenFeature.setProviderAndWait(91new FlagshipServerProvider({92appId: "<APP_ID>",93accountId: "<ACCOUNT_ID>",94authToken: "<API_TOKEN>",95}),96);97const client = OpenFeature.getClient();98const enabled = await client.getBooleanValue("new-checkout", false, {99targetingKey: "user-42",100});101```102103### Client Provider (`FlagshipClientProvider`)104105For browser applications. Pre-fetches flags on init, evaluates synchronously.106107```typescript108import { OpenFeature } from "@openfeature/web-sdk";109import { FlagshipClientProvider } from "@cloudflare/flagship";110111await OpenFeature.setProviderAndWait(112new FlagshipClientProvider({113appId: "<APP_ID>",114accountId: "<ACCOUNT_ID>",115authToken: "<API_TOKEN>",116prefetchFlags: ["promo-banner", "dark-mode"],117}),118);119await OpenFeature.setContext({ targetingKey: "user-42", plan: "enterprise" });120const client = OpenFeature.getClient();121122// Synchronous — no await needed123const showBanner = client.getBooleanValue("promo-banner", false);124```125126**Important:** Only flags listed in `prefetchFlags` are available. Unlisted flags return `FLAG_NOT_FOUND`.127128### SDK Hooks129130```typescript131import { LoggingHook, TelemetryHook } from "@cloudflare/flagship";132OpenFeature.addHooks(new LoggingHook(), new TelemetryHook());133```134135---136137## REST API (Flag Management)138139### FIRST: Check Prerequisites140141Before making any REST API calls (create, read, update, delete, toggle flags), verify these environment variables are set:142143| Variable | Purpose | How to get |144|----------|---------|------------|145| `CLOUDFLARE_ACCOUNT_ID` | Account identifier | Dashboard URL or `wrangler whoami` |146| `CLOUDFLARE_API_TOKEN` | Bearer token for API auth | [Create API token](https://dash.cloudflare.com/profile/api-tokens) with Flagship permissions |147| `FLAGSHIP_APP_ID` | Target app UUID | Dashboard under **Compute > Flagship**, or `GET /apps` endpoint |148149Check with:150151```bash152echo "CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID:-(not set)}"153echo "CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN:-(not set)}"154echo "FLAGSHIP_APP_ID=${FLAGSHIP_APP_ID:-(not set)}"155```156157**If any are missing, ask the user to provide them before proceeding.**158159### Base URL and Auth160161Base URL: `https://api.cloudflare.com/client/v4/accounts/{account_id}/flagship`162163Authentication: `Authorization: Bearer <API_TOKEN>`164165Response envelope:166167```json168// Success169{ "success": true, "data": <T> }170171// Error172{ "success": false, "error": "message" }173```174175### App Endpoints176177| Method | Path | Description |178|--------|------|-------------|179| `GET` | `/apps` | List all apps |180| `GET` | `/apps/{app_id}` | Get app |181| `POST` | `/apps` | Create app (`{ "name": "my-app" }`) |182| `PUT` | `/apps/{app_id}` | Update app (`{ "name": "new-name" }`) |183| `DELETE` | `/apps/{app_id}` | Delete app |184185App name constraints: alphanumeric + hyphens + underscores, 1-64 chars.186187### Flag Endpoints188189| Method | Path | Description |190|--------|------|-------------|191| `GET` | `/apps/{app_id}/flags?limit=50&cursor=<cursor>` | List flags (paginated) |192| `GET` | `/apps/{app_id}/flags/{flag_key}` | Get flag |193| `POST` | `/apps/{app_id}/flags` | Create flag |194| `PUT` | `/apps/{app_id}/flags/{flag_key}` | Update flag (full replace) |195| `DELETE` | `/apps/{app_id}/flags/{flag_key}` | Delete flag |196| `GET` | `/apps/{app_id}/flags/{flag_key}/changelog?limit=20&cursor=<cursor>` | Flag changelog |197198### Evaluate Endpoint199200```201GET /apps/{app_id}/evaluate?flagKey=<key>&<context-attrs>202```203204Requires an API token with `flagship:evaluate` permission. Context attributes passed as query params. Returns:205206```json207{208"flagKey": "my-flag",209"value": true,210"variant": "on",211"reason": "TARGETING_MATCH"212}213```214215---216217## FlagDefinition Schema218219```json220{221"key": "my-flag",222"type": "boolean",223"default_variation": "off",224"variations": {225"on": true,226"off": false227},228"rules": [229{230"priority": 1,231"conditions": [232{233"attribute": "email",234"operator": "ends_with",235"value": "@cloudflare.com"236}237],238"serve_variation": "on",239"rollout": { "percentage": 100 }240}241],242"description": "Enables the new feature",243"enabled": true244}245```246247### Field Constraints248249| Field | Type | Constraints |250|-------|------|-------------|251| `key` | string | 1-64 chars, `/^[a-zA-Z0-9_-]+$/` |252| `type` | enum | Optional. `boolean`, `string`, `number`, `json` (auto-inferred from variations) |253| `default_variation` | string | Must be a key in `variations` |254| `variations` | `Record<string, T>` | At least one. All values same type. Keys: alphanumeric/hyphens/underscores, max 64 chars. Values max 10KB. |255| `rules` | `Rule[]` | Can be empty. No duplicate priorities. |256| `description` | string? | Max 512 chars, nullable |257| `enabled` | boolean | Required. `false` = always returns default variation. |258259### Rule Schema260261```json262{263"priority": 1,264"conditions": [ /* Condition[] */ ],265"serve_variation": "on",266"rollout": { "percentage": 50, "attribute": "targetingKey" }267}268```269270- `priority`: integer >= 1, unique across rules in the flag (lower = evaluated first)271- `conditions`: array of base or logical conditions272- `serve_variation`: must be a key in `variations`273- `rollout`: optional. `percentage` 0-100. `attribute` defaults to `targetingKey`.274275### Condition Schema276277**Base condition:**278279```json280{ "attribute": "email", "operator": "ends_with", "value": "@cloudflare.com" }281```282283**Logical condition (AND/OR):**284285```json286{287"logical_operator": "AND",288"clauses": [289{ "attribute": "country", "operator": "equals", "value": "US" },290{ "attribute": "plan", "operator": "in", "value": ["enterprise", "business"] }291]292}293```294295Nesting supported up to 6 levels deep.296297### Operators298299| Operator | Description | Value Type |300|----------|-------------|------------|301| `equals` | Exact match (case-sensitive) | String |302| `not_equals` | Not exact match | String |303| `greater_than` | Numeric / datetime > | Number, ISO 8601 |304| `less_than` | Numeric / datetime < | Number, ISO 8601 |305| `greater_than_or_equals` | >= | Number, ISO 8601 |306| `less_than_or_equals` | <= | Number, ISO 8601 |307| `contains` | Substring match (case-sensitive) | String |308| `starts_with` | Prefix match | String |309| `ends_with` | Suffix match | String |310| `in` | Value in array | Array |311| `not_in` | Value not in array | Array |312313---314315## Rate Limits316317| Operation | Limit |318|-----------|-------|319| Mutations (POST/PUT/DELETE) | 60 per 60s per account:app |320| Reads (GET) | 600 per 60s per account:app |321322## Error Codes323324| HTTP Status | Meaning |325|-------------|---------|326| 200 | Success (read/update/delete) |327| 201 | Created (create) |328| 400 | Validation error (check `error` field) |329| 401 | Invalid or missing token |330| 404 | Flag or app not found |331| 409 | Flag key already exists (create) |332| 429 | Rate limited |333