---
title: Cloudflare Flagship
description: Ship features safely with Flagship, Cloudflare's feature flag service for controlling feature visibility without redeploying code.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Cloudflare Flagship

Ship features safely with feature flags.

Flagship is Cloudflare's feature flag service. It lets you control feature visibility in your applications without redeploying code. Define flags with targeting rules and percentage-based rollouts, then evaluate them directly inside your Workers through a [native binding](https://developers.cloudflare.com/flagship/binding/) or from server and browser applications with [OpenFeature SDKs](https://developers.cloudflare.com/flagship/sdk/).

[OpenFeature ↗](https://openfeature.dev/) is the CNCF open standard for feature flag management. Flagship ships official SDKs for TypeScript (Workers, Node.js, and browsers), Python, and Go. You can swap providers without changing evaluation code.

Check out the [Get started guide](https://developers.cloudflare.com/flagship/get-started/) to create your first feature flag.

## Features

###  Worker binding 

Evaluate flags with a native Workers binding. Type-safe methods with automatic fallback to defaults.

[ Binding reference ](https://developers.cloudflare.com/flagship/binding/) 

###  OpenFeature SDK 

Use the official OpenFeature SDKs to evaluate flags from Workers, Node.js, browsers, Python, and Go server applications. Switch from another flag provider by changing one line of configuration.

[ View SDK docs ](https://developers.cloudflare.com/flagship/sdk/) 

###  Targeting rules 

Serve different flag values based on user attributes. Rules support 11 comparison operators, logical AND/OR grouping, and sequential evaluation.

[ Learn about targeting ](https://developers.cloudflare.com/flagship/targeting/) 

###  Percentage rollouts 

Gradually release features to a percentage of users. Consistent hashing ensures the same user always receives the same flag value.

[ Learn about rollouts ](https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/) 

###  Multi-type variants 

Flag variants can be booleans, strings, numbers, or structured JSON values. Use JSON variants to deliver entire configuration blocks as a single flag.

[ Use Multi-type variants ](https://developers.cloudflare.com/flagship/concepts/) 

###  Flag management 

Create, update, and delete flags through the Cloudflare dashboard. Organize flags into apps that map to your projects or services.

[ Use Flag management ](https://developers.cloudflare.com/flagship/get-started/) 

---

## Related products

**[Workers](https://developers.cloudflare.com/workers/)** 

Build serverless applications on Cloudflare's global network. Flagship integrates natively with Workers through a binding.

**[KV](https://developers.cloudflare.com/kv/)** 

Store key-value data across Cloudflare's global network. Flagship uses this infrastructure to deliver flag configurations.

## More resources

[Developer Discord](https://discord.cloudflare.com) 

Connect with the Workers community on Discord to ask questions, show what you are building, and discuss the platform with other developers.

[@CloudflareDev](https://x.com/cloudflaredev) 

Follow @CloudflareDev on Twitter to learn about product announcements and what is new in Cloudflare Workers.

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/flagship/#page","headline":"Overview · Cloudflare Flagship docs","description":"Ship features safely with Flagship, Cloudflare's feature flag service for controlling feature visibility without redeploying code.","url":"https://developers.cloudflare.com/flagship/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-30","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}}]}
```

---

---
title: Get started
description: Create your first Flagship feature flag and evaluate it inside a Cloudflare Worker using the binding API.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Get started

In this guide, you will create a feature flag in Flagship and evaluate it inside a Cloudflare Worker.

## Create an app and a flag

In this example, you will create a boolean flag called `new-checkout` that controls whether users see a new checkout experience.

1. Log in to the [Cloudflare dashboard ↗](https://dash.cloudflare.com/) and select your account.
2. Go to **Compute** \> **Flagship**.
3. Select **Create app**. Give the app a name that matches your project or service (for example, `checkout-service`).
4. Inside the app, select **Create flag**.
5. Create a boolean flag with the key `new-checkout`. Optionally, add [targeting rules](https://developers.cloudflare.com/flagship/targeting/) to control who sees the flag.
6. Turn on the flag and select **Save**.

## Add the Flagship binding to your Worker

Add the Flagship binding in your Wrangler configuration file so your Worker can evaluate flags through a binding.

* [  wrangler.jsonc ](#tab-panel-8890)
* [  wrangler.toml ](#tab-panel-8891)

JSONC

```
{  "flagship": [    {      "binding": "FLAGS",      "app_id": "<APP_ID>",    },  ],}
```

TOML

```
[[flagship]]binding = "FLAGS"app_id = "<APP_ID>"
```

Replace `<APP_ID>` with the app ID shown in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/flagship). The `binding` field sets the name you use to access Flagship in your Worker code. In this example, the binding is available as `env.FLAGS`.

After updating the Wrangler configuration, run `npx wrangler types` to generate TypeScript types for the binding.

## Evaluate the flag in your Worker

Use the `env.FLAGS` binding to evaluate the flag. The binding provides type-safe methods that return the flag value and fall back to the default you provide if evaluation fails.

* [  JavaScript ](#tab-panel-8892)
* [  TypeScript ](#tab-panel-8893)

JavaScript

```
export default {  async fetch(request, env) {    const url = new URL(request.url);    const userId = url.searchParams.get("userId") ?? "anonymous";
    const showNewCheckout = await env.FLAGS.getBooleanValue(      "new-checkout",      false,      { userId },    );
    if (showNewCheckout) {      return new Response("Welcome to the new checkout experience!");    }
    return new Response("Standard checkout.");  },};
```

TypeScript

```
export default {  async fetch(request: Request, env: Env): Promise<Response> {    const url = new URL(request.url);    const userId = url.searchParams.get("userId") ?? "anonymous";
    const showNewCheckout = await env.FLAGS.getBooleanValue(      "new-checkout",      false,      { userId },    );
    if (showNewCheckout) {      return new Response("Welcome to the new checkout experience!");    }
    return new Response("Standard checkout.");  },};
```

The third argument to `getBooleanValue` is the [evaluation context](https://developers.cloudflare.com/flagship/concepts/#evaluation-context). Flagship uses the context attributes to match targeting rules. In this example, the `userId` attribute is passed so that percentage rollouts and user-specific targeting work correctly.

## Deploy and test

Deploy your Worker:

Terminal window

```
npx wrangler deploy
```

Test flag evaluation by sending a request:

Terminal window

```
curl "https://<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev/?userId=user-42"
```

Change the flag value or targeting rules in the dashboard and observe the updated response. Flag changes propagate globally within seconds.

## (Optional) Use the OpenFeature SDK

If you prefer the [OpenFeature ↗](https://openfeature.dev/) standard interface, or if you are running outside of a Cloudflare Worker, you can use the [@cloudflare/flagship ↗](https://www.npmjs.com/package/@cloudflare/flagship) SDK instead of the binding.

Install the SDK:

 npm  yarn  pnpm  bun 

```
npm i @cloudflare/flagship @openfeature/server-sdk
```

```
yarn add @cloudflare/flagship @openfeature/server-sdk
```

```
pnpm add @cloudflare/flagship @openfeature/server-sdk
```

```
bun add @cloudflare/flagship @openfeature/server-sdk
```

Evaluate flags using the OpenFeature client:

* [ With binding ](#tab-panel-8898)
* [ With app ID ](#tab-panel-8899)

Pass the Flagship binding directly to the provider. This avoids additional HTTP overhead and is the recommended approach inside a Worker. The binding handles authentication automatically.

* [  JavaScript ](#tab-panel-8896)
* [  TypeScript ](#tab-panel-8897)

JavaScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
export default {  async fetch(request, env) {    await OpenFeature.setProviderAndWait(      new FlagshipServerProvider({ binding: env.FLAGS }),    );
    const client = OpenFeature.getClient();
    const showNewCheckout = await client.getBooleanValue(      "new-checkout",      false,      { targetingKey: "user-42" },    );
    return new Response(      showNewCheckout ? "New checkout!" : "Standard checkout.",    );  },};
```

TypeScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
export default {  async fetch(request: Request, env: Env): Promise<Response> {    await OpenFeature.setProviderAndWait(      new FlagshipServerProvider({ binding: env.FLAGS }),    );
    const client = OpenFeature.getClient();
    const showNewCheckout = await client.getBooleanValue(      "new-checkout",      false,      { targetingKey: "user-42" },    );
    return new Response(      showNewCheckout ? "New checkout!" : "Standard checkout.",    );  },};
```

Use an app ID, account ID, and an API token when running outside of a Worker (for example, in Node.js). Generate an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) from your Cloudflare account with Flagship Evaluate permission.

* [  JavaScript ](#tab-panel-8894)
* [  TypeScript ](#tab-panel-8895)

JavaScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
await OpenFeature.setProviderAndWait(  new FlagshipServerProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",  }),);
const client = OpenFeature.getClient();
const showNewCheckout = await client.getBooleanValue("new-checkout", false, {  targetingKey: "user-42",});
```

TypeScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
await OpenFeature.setProviderAndWait(  new FlagshipServerProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",  }),);
const client = OpenFeature.getClient();
const showNewCheckout = await client.getBooleanValue("new-checkout", false, {  targetingKey: "user-42",});
```

Refer to the [SDK documentation](https://developers.cloudflare.com/flagship/sdk/) for detailed setup instructions.

## Next steps

* Learn about [targeting rules](https://developers.cloudflare.com/flagship/targeting/) to serve different values based on user attributes.
* Explore the full [binding API reference](https://developers.cloudflare.com/flagship/binding/) for all evaluation methods.
* Read about [percentage rollouts](https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/) for gradual feature releases.
* Refer to the [Flagship API reference](https://developers.cloudflare.com/flagship/reference/api-reference/) to manage Flagship programmatically.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/get-started/#page","headline":"Get started · Cloudflare Flagship docs","description":"Create your first Flagship feature flag and evaluate it inside a Cloudflare Worker using the binding API.","url":"https://developers.cloudflare.com/flagship/get-started/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/get-started/","name":"Get started"}}]}
```

---

---
title: Concepts
description: Understand Flagship core concepts including apps, flags, variants, targeting rules, evaluation context, and flag propagation.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Concepts

Flagship organizes feature flags into apps. You define flags with variants and targeting rules, then evaluate them within Cloudflare's global network.

## Overview

Flagship feature flags go through three stages from creation to evaluation:

1. **Configure** — Create flags and targeting rules in the [Cloudflare dashboard ↗](https://dash.cloudflare.com/) or through the [API](https://developers.cloudflare.com/api/resources/flagship).
2. **Propagate** — Flagship automatically distributes your flag configuration across Cloudflare's global network within seconds.
3. **Evaluate** — Your Worker (or SDK) evaluates flags locally using the propagated configuration. There is no round-trip to a central server.

Flag changes take effect globally within seconds of saving. You do not need to redeploy your Worker or restart your application. If the dashboard is temporarily unavailable, flag evaluation continues to work using the last propagated configuration.

## Apps

An app is the top-level organizational unit in Flagship. It groups related flags together.

An app typically maps to a single project, service, or product surface. Each Cloudflare account can have multiple apps. For example, you might create one app for your marketing site and another for your API backend.

## Flags

A flag is a named feature toggle. Each flag has a key, a set of [variants](#variants), [targeting rules](#targeting-rules), and an enabled/disabled state.

Flag keys must be unique within an app. Keys can contain letters, numbers, hyphens, and underscores.

When a flag is disabled, it always returns the default variant regardless of any targeting rules. Choose a default variant that is safe for your application if Flagship cannot evaluate the flag.

## Variants

Variants are the possible values a flag can return. Each flag must have at least one variant, and one variant is designated as the default.

Flagship supports four variant types:

| Type    | Example                                                               |
| ------- | --------------------------------------------------------------------- |
| Boolean | on: true, off: false                                                  |
| String  | v1: "old-checkout", v2: "new-checkout"                                |
| Number  | low: 100, high: 1000                                                  |
| JSON    | premium: { "tier": "premium", "features": \["analytics", "export"\] } |

Use boolean flags for simple on/off toggles. Use string, number, or JSON flags when you need to deliver configuration values or structured data. JSON variants can contain objects or arrays.

## Targeting rules

Targeting rules control which variant a flag returns for a given request. Rules are evaluated in sequential order, and the first matching rule wins. If no rule matches, the default variant is returned.

Each rule contains:

* **Conditions** that compare an attribute from the [evaluation context](#evaluation-context) against a value using an operator.
* An optional **percentage rollout** that splits traffic across variants.
* A **variant** to serve when the rule matches.

Conditions within a rule can be grouped with `AND`/`OR` operators.

Refer to [Targeting rules](https://developers.cloudflare.com/flagship/targeting/) and [Operators](https://developers.cloudflare.com/flagship/targeting/operators/) for the full list of operators and configuration options.

## Evaluation context

The evaluation context is a set of key-value attributes that describe the current user or request (for example, `userId`, `country`, `plan`).

You pass the context as the third argument to evaluation methods on the binding:

TypeScript

```
const value = await env.FLAGS.getBooleanValue("new-checkout", false, {  userId: "user-42",  country: "US",});
```

When using the [OpenFeature SDK](https://developers.cloudflare.com/flagship/sdk/), you pass context through the OpenFeature evaluation context object.

Flagship uses context attributes to match targeting rules and to determine percentage rollout bucketing. A consistent context (for example, the same `userId`) produces the same rollout result on every evaluation.

Avoid sending sensitive data in evaluation context. Only include attributes needed by targeting rules or rollout bucketing.

## Flag propagation

After you change a flag, it can take up to 30 seconds for the updated value to reflect globally. During this propagation window, some evaluations may still return the previous flag value.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/concepts/#page","headline":"Concepts · Cloudflare Flagship docs","description":"Understand Flagship core concepts including apps, flags, variants, targeting rules, evaluation context, and flag propagation.","url":"https://developers.cloudflare.com/flagship/concepts/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/concepts/","name":"Concepts"}}]}
```

---

---
title: Configuration
description: Add and configure a Flagship binding in your Wrangler configuration file to evaluate feature flags in a Worker.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Configuration

To use Flagship in a Cloudflare Worker, add a Flagship binding to your Wrangler configuration file. The binding gives your Worker access to `env.FLAGS`, which provides methods to evaluate feature flags.

## Add the binding

Add the `flagship` block to your Wrangler configuration file with a binding name and your app ID.

* [  wrangler.jsonc ](#tab-panel-8884)
* [  wrangler.toml ](#tab-panel-8885)

JSONC

```
{  "flagship": [    {      "binding": "FLAGS",      "app_id": "<APP_ID>",    },  ],}
```

TOML

```
[[flagship]]binding = "FLAGS"app_id = "<APP_ID>"
```

Replace `<APP_ID>` with the app ID from your Flagship app. If you have not created an app yet, refer to the [Get started guide](https://developers.cloudflare.com/flagship/get-started/#create-an-app-and-a-flag). The `binding` field sets the name you use to access Flagship in your Worker code (for example, `env.FLAGS`).

## Bind to multiple apps

A single Worker can bind to multiple Flagship apps. Use the array form to define more than one binding:

* [  wrangler.jsonc ](#tab-panel-8886)
* [  wrangler.toml ](#tab-panel-8887)

JSONC

```
{  "flagship": [    {      "binding": "FLAGS",      "app_id": "<APP_ID_1>",    },    {      "binding": "EXPERIMENT_FLAGS",      "app_id": "<APP_ID_2>",    },  ],}
```

TOML

```
[[flagship]]binding = "FLAGS"app_id = "<APP_ID_1>"
[[flagship]]binding = "EXPERIMENT_FLAGS"app_id = "<APP_ID_2>"
```

Each binding is available as a separate property on the `env` object (for example, `env.FLAGS` and `env.EXPERIMENT_FLAGS`).

## Generate types

After adding the binding, run `npx wrangler types` to generate TypeScript types. This creates the `Env` interface with each binding typed as `Flagship`.

TypeScript

```
interface Env {  FLAGS: Flagship;  EXPERIMENT_FLAGS: Flagship;}
```

## Use the binding

Call evaluation methods on `env.FLAGS` to resolve flag values at runtime. Each method accepts a flag key, a default value, and an optional evaluation context.

* [  JavaScript ](#tab-panel-8888)
* [  TypeScript ](#tab-panel-8889)

JavaScript

```
export default {  async fetch(request, env) {    const isEnabled = await env.FLAGS.getBooleanValue("my-feature", false, {      userId: "user-42",    });
    return new Response(isEnabled ? "Feature is on" : "Feature is off");  },};
```

TypeScript

```
export default {  async fetch(request: Request, env: Env): Promise<Response> {    const isEnabled = await env.FLAGS.getBooleanValue("my-feature", false, {      userId: "user-42",    });
    return new Response(isEnabled ? "Feature is on" : "Feature is off");  },};
```

Refer to the [binding API reference](https://developers.cloudflare.com/flagship/binding/) for the full list of methods.

## Local development

Flagship bindings work with `wrangler dev`. Local Workers use the live Flagship app configured by `app_id`. There is no local flag store. Make sure your local Wrangler configuration points to a valid Flagship app before testing evaluations.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/configuration/#page","headline":"Configuration · Cloudflare Flagship docs","description":"Add and configure a Flagship binding in your Wrangler configuration file to evaluate feature flags in a Worker.","url":"https://developers.cloudflare.com/flagship/configuration/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/configuration/","name":"Configuration"}}]}
```

---

---
title: Best practices
description: Best practices for using Flagship in applications, including evaluation paths, rollout workflows, and safe flag cleanup.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Best practices

Use these patterns to keep Flagship evaluations predictable, fast, and easy to maintain.

## Choose the right evaluation path

Use the [Workers binding](https://developers.cloudflare.com/flagship/binding/) inside Cloudflare Workers. The binding handles authentication automatically and avoids application-managed API tokens.

Use the [OpenFeature SDK](https://developers.cloudflare.com/flagship/sdk/) when you run outside Workers or need a vendor-neutral OpenFeature interface. In Workers, you can still pass the binding to the OpenFeature server provider to keep binding performance while using OpenFeature APIs.

## Evaluate once per request

Avoid evaluating the same flag repeatedly in a loop. Evaluate the flag once, store the result in a local variable, and reuse it for the rest of the request.

TypeScript

```
const enabled = await env.FLAGS.getBooleanValue("show-related-items", false, {  userId,});
for (const item of items) {  if (enabled) {    item.related = await loadRelatedItems(item.id);  }}
```

## Pass context consistently

Targeting and percentage rollouts depend on the evaluation context you pass from your application. Use stable identifiers and the same attribute names everywhere.

TypeScript

```
const context = {  userId: session.user.id,  plan: session.user.plan,  country: request.cf?.country ?? "unknown",};
const enabled = await env.FLAGS.getBooleanValue("new-checkout", false, context);
```

For OpenFeature SDKs, use `targetingKey` as the stable identifier. For the Workers binding, use the attribute configured for your rollout, such as `userId`.

## Choose safe defaults

Every evaluation method requires a default value. Choose a default that keeps your application safe if the flag does not exist, cannot be evaluated, or has a type mismatch.

For release flags, this is usually the existing experience. For configuration flags, choose conservative limits or behavior that your application can handle without extra dependencies.

## Use details for debugging and observability

Use `*Details` methods when you need to understand why a value was returned. Details include the resolved value, variant, reason, and error metadata.

TypeScript

```
const details = await env.FLAGS.getBooleanDetails("new-checkout", false, {  userId: "user-42",});
console.log(details.value);console.log(details.variant);console.log(details.reason);console.log(details.errorCode);
```

## Roll out progressively

Start with a small percentage rollout, monitor application metrics, then increase the percentage over time.

1. Create the flag with a small rollout, such as 5%.
2. Monitor errors, latency, business metrics, and user feedback.
3. Increase to 25%, then 50%, then 100% as confidence grows.
4. After the rollout reaches 100%, make the winning variant the default and remove temporary targeting rules.
5. After the feature is fully shipped, remove the old code path and delete the flag.

## Clean up stale flags

Flags that are disabled or fully rolled out still add maintenance cost. Before deleting a flag, disable it first, monitor for unexpected behavior, remove the evaluation code, deploy the code change, then delete the flag from Flagship.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/best-practices/#page","headline":"Best practices · Cloudflare Flagship docs","description":"Best practices for using Flagship in applications, including evaluation paths, rollout workflows, and safe flag cleanup.","url":"https://developers.cloudflare.com/flagship/best-practices/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/best-practices/","name":"Best practices"}}]}
```

---

---
title: Binding API
description: Evaluate Flagship feature flags directly in Cloudflare Workers using the native binding with type-safe methods and automatic fallback.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Binding API

Workers access Flagship through a binding that you add to your Wrangler configuration file. The `binding` field sets the variable name you use in your Worker code.

* [  wrangler.jsonc ](#tab-panel-8880)
* [  wrangler.toml ](#tab-panel-8881)

JSONC

```
{  "flagship": [    {      "binding": "FLAGS",      "app_id": "<APP_ID>",    },  ],}
```

TOML

```
[[flagship]]binding = "FLAGS"app_id = "<APP_ID>"
```

Replace `<APP_ID>` with the app ID from your Flagship app. If you have not created an app yet, refer to the [Get started guide](https://developers.cloudflare.com/flagship/get-started/#create-an-app-and-a-flag). With this configuration, the binding is available as `env.FLAGS`. Refer to [Configuration](https://developers.cloudflare.com/flagship/configuration/) for additional options such as binding to multiple apps.

The binding provides type-safe methods for evaluating feature flags. If an evaluation fails or a flag is not found, the method returns the default value you provide.

* [  JavaScript ](#tab-panel-8882)
* [  TypeScript ](#tab-panel-8883)

JavaScript

```
export default {  async fetch(request, env) {    const enabled = await env.FLAGS.getBooleanValue("new-feature", false, {      userId: "user-42",    });    return new Response(enabled ? "Feature on" : "Feature off");  },};
```

TypeScript

```
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");  },};
```

The binding has the type `Flagship` from the `@cloudflare/workers-types` package.

* [ Types ](https://developers.cloudflare.com/flagship/binding/types/)
* [ Methods ](https://developers.cloudflare.com/flagship/binding/methods/)

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/flagship/binding/#page","headline":"Binding API · Cloudflare Flagship docs","description":"Evaluate Flagship feature flags directly in Cloudflare Workers using the native binding with type-safe methods and automatic fallback.","url":"https://developers.cloudflare.com/flagship/binding/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-04-30","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/binding/","name":"Binding API"}}]}
```

---

---
title: Methods
description: Reference for all Flagship binding evaluation methods, including typed value and details methods for booleans, strings, numbers, and objects.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Methods

The Flagship binding provides the following methods for evaluating feature flags. All methods are asynchronous and return a `Promise`. For known evaluation failures, typed methods return the `defaultValue` you provide.

Refer to the [types reference](https://developers.cloudflare.com/flagship/binding/types/) for the definitions of `FlagshipEvaluationContext` and `FlagshipEvaluationDetails`.

## `get()`

Returns the raw flag value without type checking. Use this method when the flag type is not known at compile time.

If you provide `defaultValue`, `get()` returns that value for known evaluation failures, such as a missing flag. If you omit `defaultValue`, known evaluation failures are thrown.

TypeScript

```
get(flagKey: string, defaultValue?: unknown, context?: FlagshipEvaluationContext): Promise<unknown>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | unknown                   | No       | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const value = await env.FLAGS.get("checkout-flow", "v1", {  userId: "user-42",});
```

## `getBooleanValue()`

Returns the flag value as a `boolean`.

TypeScript

```
getBooleanValue(flagKey: string, defaultValue: boolean, context?: FlagshipEvaluationContext): Promise<boolean>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | boolean                   | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const enabled = await env.FLAGS.getBooleanValue("dark-mode", false, {  userId: "user-42",});
```

## `getStringValue()`

Returns the flag value as a `string`.

TypeScript

```
getStringValue(flagKey: string, defaultValue: string, context?: FlagshipEvaluationContext): Promise<string>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | string                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const variant = await env.FLAGS.getStringValue("checkout-flow", "v1", {  userId: "user-42",  country: "US",});
```

## `getNumberValue()`

Returns the flag value as a `number`.

TypeScript

```
getNumberValue(flagKey: string, defaultValue: number, context?: FlagshipEvaluationContext): Promise<number>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | number                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const maxRetries = await env.FLAGS.getNumberValue("max-retries", 3, {  plan: "enterprise",});
```

## `getObjectValue()`

Returns the flag value as a typed object. Use the generic parameter `T` to specify the expected shape.

TypeScript

```
getObjectValue<T extends object>(flagKey: string, defaultValue: T, context?: FlagshipEvaluationContext): Promise<T>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | T                         | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
interface ThemeConfig {  primaryColor: string;  fontSize: number;}
const theme = await env.FLAGS.getObjectValue<ThemeConfig>(  "theme-config",  { primaryColor: "#000", fontSize: 14 },  { userId: "user-42" },);
```

## `getBooleanDetails()`

Returns the flag value as a `boolean` with evaluation metadata.

TypeScript

```
getBooleanDetails(flagKey: string, defaultValue: boolean, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<boolean>>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | boolean                   | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const details = await env.FLAGS.getBooleanDetails("dark-mode", false, {  userId: "user-42",});console.log(details.value); // trueconsole.log(details.reason); // "TARGETING_MATCH"
```

## `getStringDetails()`

Returns the flag value as a `string` with evaluation metadata.

TypeScript

```
getStringDetails(flagKey: string, defaultValue: string, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<string>>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | string                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const details = await env.FLAGS.getStringDetails("checkout-flow", "v1", {  userId: "user-42",});console.log(details.value); // "v2"console.log(details.variant); // "new"console.log(details.reason); // "TARGETING_MATCH"
```

## `getNumberDetails()`

Returns the flag value as a `number` with evaluation metadata.

TypeScript

```
getNumberDetails(flagKey: string, defaultValue: number, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<number>>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | number                    | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
const details = await env.FLAGS.getNumberDetails("max-retries", 3, {  plan: "enterprise",});console.log(details.value); // 5console.log(details.reason); // "TARGETING_MATCH"
```

## `getObjectDetails()`

Returns the flag value as a typed object with evaluation metadata. Use the generic parameter `T` to specify the expected shape.

TypeScript

```
getObjectDetails<T extends object>(flagKey: string, defaultValue: T, context?: FlagshipEvaluationContext): Promise<FlagshipEvaluationDetails<T>>
```

| Parameter    | Type                      | Required | Description                                                               |
| ------------ | ------------------------- | -------- | ------------------------------------------------------------------------- |
| flagKey      | string                    | Yes      | The key of the flag to evaluate.                                          |
| defaultValue | T                         | Yes      | The fallback value returned if evaluation fails or the flag is not found. |
| context      | FlagshipEvaluationContext | No       | Key-value attributes for targeting rules.                                 |

TypeScript

```
interface ThemeConfig {  primaryColor: string;  fontSize: number;}
const details = await env.FLAGS.getObjectDetails<ThemeConfig>(  "theme-config",  { primaryColor: "#000", fontSize: 14 },  { userId: "user-42" },);console.log(details.value); // { primaryColor: "#0051FF", fontSize: 16 }console.log(details.variant); // "brand-refresh"
```

## Error handling

Typed evaluation methods return the `defaultValue` you provided for known evaluation failures, such as a missing flag or type mismatch. Unexpected runtime failures can still throw. Use the `*Details` methods to inspect known evaluation failures.

### Type mismatch

If you call a typed method on a flag with a different type (for example, `getBooleanValue` on a string flag), the method returns the default value. The `*Details` methods set `errorCode` to `"TYPE_MISMATCH"`.

TypeScript

```
// Flag "checkout-flow" is a string flag, but you call getBooleanDetails.const details = await env.FLAGS.getBooleanDetails("checkout-flow", false);console.log(details.value); // false (the default value)console.log(details.errorCode); // "TYPE_MISMATCH"
```

### Evaluation failure

If evaluation fails for another reason, the method returns the default value. The `*Details` methods include an `errorCode` such as `"FLAG_NOT_FOUND"`, `"INVALID_CONTEXT"`, `"PARSE_ERROR"`, or `"GENERAL"`.

TypeScript

```
const details = await env.FLAGS.getStringDetails(  "nonexistent-flag",  "fallback",);console.log(details.value); // "fallback"console.log(details.errorCode); // "FLAG_NOT_FOUND"
```

## Parameters reference

The following table summarizes the parameters shared across all evaluation methods.

| Parameter    | Type                      | Required         | Description                                                                                   |
| ------------ | ------------------------- | ---------------- | --------------------------------------------------------------------------------------------- |
| flagKey      | string                    | Yes              | The key of the flag to evaluate.                                                              |
| defaultValue | varies                    | Yes (except get) | The fallback value returned if evaluation fails or the flag is not found.                     |
| context      | FlagshipEvaluationContext | No               | Key-value attributes for targeting rules (for example, { userId: "user-42", country: "US" }). |

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/binding/methods/#page","headline":"Methods · Cloudflare Flagship docs","description":"Reference for all Flagship binding evaluation methods, including typed value and details methods for booleans, strings, numbers, and objects.","url":"https://developers.cloudflare.com/flagship/binding/methods/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/binding/","name":"Binding API"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/binding/methods/","name":"Methods"}}]}
```

---

---
title: Types
description: TypeScript type definitions for the Flagship binding, including Flagship, FlagshipEvaluationContext, and FlagshipEvaluationDetails.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Types

The Flagship binding uses the following TypeScript types. These are available from the `@cloudflare/workers-types` package after running `npx wrangler types`.

## `Flagship`

The binding type. Each Flagship binding in your Wrangler configuration is typed as `Flagship` on the `Env` interface.

TypeScript

```
interface Env {  FLAGS: Flagship;}
```

Refer to the [methods reference](https://developers.cloudflare.com/flagship/binding/methods/) for the full list of evaluation methods available on the binding.

## `FlagshipEvaluationContext`

A record of attribute names to values passed for [targeting rules](https://developers.cloudflare.com/flagship/targeting/). Use this to provide user attributes such as user ID, country, or plan type.

TypeScript

```
type FlagshipEvaluationContext = Record<string, string | number | boolean>;
```

## `FlagshipEvaluationDetails`

Returned by the `*Details` methods. Contains the evaluated value and metadata about how Flagship resolved the flag.

TypeScript

```
interface FlagshipEvaluationDetails<T> {  flagKey: string;  value: T;  variant?: string;  reason?: string;  errorCode?: string;}
```

| Property  | Type   | Description                                                                         |
| --------- | ------ | ----------------------------------------------------------------------------------- |
| flagKey   | string | The key of the evaluated flag.                                                      |
| value     | T      | The resolved flag value.                                                            |
| variant   | string | The name of the matched variant, if any.                                            |
| reason    | string | Why the flag resolved to this value (for example, "TARGETING\_MATCH" or "DEFAULT"). |
| errorCode | string | An error code if evaluation failed (for example, "TYPE\_MISMATCH" or "GENERAL").    |

Refer to [evaluation reasons and error codes](https://developers.cloudflare.com/flagship/reference/evaluation-reasons/) for the full list of possible values.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/binding/types/#page","headline":"Types · Cloudflare Flagship docs","description":"TypeScript type definitions for the Flagship binding, including Flagship, FlagshipEvaluationContext, and FlagshipEvaluationDetails.","url":"https://developers.cloudflare.com/flagship/binding/types/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/binding/","name":"Binding API"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/binding/types/","name":"Types"}}]}
```

---

---
title: OpenFeature SDK
description: Use the official Flagship OpenFeature SDKs to evaluate feature flags from Workers, Node.js, browsers, Python, and Go applications.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# OpenFeature SDK

Evaluate Flagship feature flags using OpenFeature.

[OpenFeature ↗](https://openfeature.dev/) is the CNCF standard for feature flag interfaces. It provides a vendor-neutral API so you can switch between flag providers without changing evaluation code.

Flagship provides official OpenFeature-compatible SDKs for TypeScript, Python, and Go. The source code is available on [GitHub ↗](https://github.com/cloudflare/flagship).

| SDK        | Package                                                                                               | Runtime                    | Evaluation modes                              |
| ---------- | ----------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------------------------- |
| TypeScript | [@cloudflare/flagship ↗](https://www.npmjs.com/package/@cloudflare/flagship)                          | Workers, Node.js, browsers | Workers binding, HTTP, browser prefetch cache |
| Python     | [cloudflare-flagship ↗](https://pypi.org/project/cloudflare-flagship/)                                | Python server applications | HTTP                                          |
| Go         | [github.com/cloudflare/flagship/sdks/go ↗](https://pkg.go.dev/github.com/cloudflare/flagship/sdks/go) | Go server applications     | HTTP                                          |

## SDKs

Flagship SDKs are organized by language. The TypeScript SDK has separate setup guides for server-side and browser usage because they use different OpenFeature packages and runtime behavior.

* [TypeScript Server SDK](https://developers.cloudflare.com/flagship/sdk/server-provider/) — For Workers, Node.js, and other server-side JavaScript runtimes.
* [TypeScript Client SDK](https://developers.cloudflare.com/flagship/sdk/client-provider/) — For browser applications that need synchronous OpenFeature web SDK evaluation.
* [Python SDK](https://developers.cloudflare.com/flagship/sdk/python/) — For Python server applications.
* [Go SDK](https://developers.cloudflare.com/flagship/sdk/go/) — For Go server applications.

Note

If you are running inside a Cloudflare Worker, the [binding](https://developers.cloudflare.com/flagship/binding/) is the recommended approach because it avoids HTTP overhead. You can also [pass the binding to the OpenFeature SDK](https://developers.cloudflare.com/flagship/sdk/server-provider/) to get the best of both. Use the SDK without a binding when running in non-Worker runtimes like Node.js or the browser.

## Installation

For TypeScript server-side usage:

 npm  yarn  pnpm  bun 

```
npm i @cloudflare/flagship @openfeature/server-sdk
```

```
yarn add @cloudflare/flagship @openfeature/server-sdk
```

```
pnpm add @cloudflare/flagship @openfeature/server-sdk
```

```
bun add @cloudflare/flagship @openfeature/server-sdk
```

For TypeScript browser usage:

 npm  yarn  pnpm  bun 

```
npm i @cloudflare/flagship @openfeature/web-sdk
```

```
yarn add @cloudflare/flagship @openfeature/web-sdk
```

```
pnpm add @cloudflare/flagship @openfeature/web-sdk
```

```
bun add @cloudflare/flagship @openfeature/web-sdk
```

For Python:

Terminal window

```
uv add cloudflare-flagship
```

For Go:

Terminal window

```
go get github.com/cloudflare/flagship/sdks/go
```

## Next steps

* Set up the [server provider](https://developers.cloudflare.com/flagship/sdk/server-provider/) for Workers, Node.js, or other server-side runtimes.
* Set up the [client provider](https://developers.cloudflare.com/flagship/sdk/client-provider/) for browser applications.
* Set up the [Python SDK](https://developers.cloudflare.com/flagship/sdk/python/) for Python server applications.
* Set up the [Go SDK](https://developers.cloudflare.com/flagship/sdk/go/) for Go server applications.

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/flagship/sdk/#page","headline":"OpenFeature SDK · Cloudflare Flagship docs","description":"Use the official Flagship OpenFeature SDKs to evaluate feature flags from Workers, Node.js, browsers, Python, and Go applications.","url":"https://developers.cloudflare.com/flagship/sdk/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-30","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}}]}
```

---

---
title: TypeScript Client SDK
description: Set up the FlagshipClientProvider to evaluate feature flags synchronously in browser applications using the OpenFeature web SDK.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# TypeScript Client SDK

The `FlagshipClientProvider` implements the OpenFeature web provider interface for browser applications. It pre-fetches a declared set of flag values on initialization and resolves evaluations synchronously from an in-memory cache.

This makes the provider suitable for client-side rendering where synchronous access to flag values is required.

Warning

We do not recommend using the client provider in public-facing apps right now. It requires a Cloudflare API token, which would be exposed in client-side code and visible to anyone who inspects your application. We are working on a safer solution for client-side flag evaluation — in the meantime, use the [Worker binding](https://developers.cloudflare.com/flagship/binding/) or the [TypeScript server SDK](https://developers.cloudflare.com/flagship/sdk/server-provider/).

## prefetchFlags

`prefetchFlags` is a required array of flag keys that the provider fetches during initialization and on every context change. Only flags listed in this array are available for synchronous evaluation — any flag key not included returns a `FLAG_NOT_FOUND` error at resolution time.

**Fetch behavior:**

* **On initialization** — all flags in `prefetchFlags` are fetched in parallel and stored in an in-memory cache. The provider transitions to `READY` once all fetches complete (individual failures are non-fatal).
* **On context change** — the cache is invalidated and all flags are re-fetched for the new context. This is required by the [static context paradigm ↗](https://openfeature.dev/specification/glossary/#static-context-paradigm) used by the OpenFeature web SDK, where context is set globally and providers are expected to re-evaluate when it changes.
* **At resolution time** — evaluations are served synchronously from the cache. No network request is made during `getBooleanValue`, `getStringValue`, etc.

## Setup

The following example initializes the provider with a set of pre-fetched flags and evaluates them in a browser application.

* [  JavaScript ](#tab-panel-8902)
* [  TypeScript ](#tab-panel-8903)

JavaScript

```
import { OpenFeature } from "@openfeature/web-sdk";import { FlagshipClientProvider } from "@cloudflare/flagship/web";
await OpenFeature.setProviderAndWait(  new FlagshipClientProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",    prefetchFlags: ["promo-banner", "dark-mode", "max-uploads"],  }),);
// Set evaluation context globally. The provider re-fetches all prefetchFlags// whenever the context changes.await OpenFeature.setContext({ targetingKey: "user-42", plan: "enterprise" });
const client = OpenFeature.getClient();
// Synchronous — served from the in-memory cache.const showBanner = client.getBooleanValue("promo-banner", false);
if (showBanner) {  document.getElementById("banner").style.display = "block";}
```

TypeScript

```
import { OpenFeature } from "@openfeature/web-sdk";import { FlagshipClientProvider } from "@cloudflare/flagship/web";
await OpenFeature.setProviderAndWait(  new FlagshipClientProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",    prefetchFlags: ["promo-banner", "dark-mode", "max-uploads"],  }),);
// Set evaluation context globally. The provider re-fetches all prefetchFlags// whenever the context changes.await OpenFeature.setContext({ targetingKey: "user-42", plan: "enterprise" });
const client = OpenFeature.getClient();
// Synchronous — served from the in-memory cache.const showBanner = client.getBooleanValue("promo-banner", false);
if (showBanner) {  document.getElementById("banner").style.display = "block";}
```

Note

`getBooleanValue` on the client provider is synchronous and does not require `await`, unlike the [TypeScript server SDK](https://developers.cloudflare.com/flagship/sdk/server-provider/).

## Configuration options

| Option        | Type        | Required | Description                                                                                                                            |
| ------------- | ----------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| appId         | string      | Yes      | The Flagship app ID from the Cloudflare dashboard.                                                                                     |
| accountId     | string      | Yes      | Your Cloudflare account ID.                                                                                                            |
| authToken     | string      | Yes      | A Cloudflare [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with Flagship read permissions. |
| fetchOptions  | RequestInit | No       | Custom fetch options applied to HTTP requests.                                                                                         |
| timeout       | number      | No       | Request timeout in milliseconds. Defaults to 5000.                                                                                     |
| retries       | number      | No       | Retry attempts on transient errors. Defaults to 1 and is capped at 10.                                                                 |
| retryDelay    | number      | No       | Delay between retries in milliseconds. Defaults to 1000 and is capped at 30000.                                                        |
| prefetchFlags | string\[\]  | Yes      | Flag keys to fetch on initialization and on every context change. Flags not in this list return FLAG\_NOT\_FOUND at evaluation time.   |

## When to use the client provider

Use the client provider in browser applications, single-page apps, or any client-side JavaScript environment.

Evaluations are synchronous, so they do not block rendering. Flag values are fetched once during initialization and re-fetched whenever the evaluation context changes. To force a refresh, update the context via `OpenFeature.setContext(...)`.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/sdk/client-provider/#page","headline":"TypeScript Client SDK · Cloudflare Flagship docs","description":"Set up the FlagshipClientProvider to evaluate feature flags synchronously in browser applications using the OpenFeature web SDK.","url":"https://developers.cloudflare.com/flagship/sdk/client-provider/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/sdk/client-provider/","name":"TypeScript Client SDK"}}]}
```

---

---
title: Go SDK
description: Set up the Flagship OpenFeature provider to evaluate Flagship feature flags from Go server applications.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Go SDK

The Go SDK provides an OpenFeature-compatible server provider for Go applications. It evaluates flags over HTTP and does not support the Cloudflare Workers binding.

## Installation

Install with `go get`:

Terminal window

```
go get github.com/cloudflare/flagship/sdks/go
```

## Setup

Configure the provider with your Flagship app ID, Cloudflare account ID, and an API token with Flagship Evaluate permission.

```
package main
import (  "context"  "log"
  flagship "github.com/cloudflare/flagship/sdks/go"  "github.com/open-feature/go-sdk/openfeature")
func main() {  ctx := context.Background()
  provider, err := flagship.NewProvider(flagship.Options{    AppID:     "<APP_ID>",    AccountID: "<ACCOUNT_ID>",    AuthToken: "<API_TOKEN>",  })  if err != nil {    log.Fatal(err)  }
  if err := openfeature.SetProviderAndWait(provider); err != nil {    log.Fatal(err)  }  defer openfeature.Shutdown()
  client := openfeature.NewDefaultClient()  evalCtx := openfeature.NewEvaluationContext("user-42", map[string]any{    "plan": "enterprise",  })
  enabled, err := client.BooleanValue(ctx, "new-checkout", false, evalCtx)  if err != nil {    log.Fatal(err)  }
  log.Println("new-checkout:", enabled)}
```

## Flag types

The Go SDK supports all OpenFeature server-side flag types.

```
enabled, _ := client.BooleanValue(ctx, "new-checkout", false, evalCtx)variant, _ := client.StringValue(ctx, "homepage-hero", "control", evalCtx)rate, _ := client.FloatValue(ctx, "sample-rate", 0.1, evalCtx)limit, _ := client.IntValue(ctx, "upload-limit", 10, evalCtx)config, _ := client.ObjectValue(ctx, "ui-config", map[string]any{"theme": "light"}, evalCtx)
```

Use the `*ValueDetails` methods when you need reason, variant, metadata, or error codes.

## Response caching

The provider can cache evaluations to avoid a network round-trip for repeated flag/context pairs. Caching is off by default and enabled by setting `CacheTTL`:

```
provider, err := flagship.NewProvider(flagship.Options{  AppID:        "<APP_ID>",  AccountID:    "<ACCOUNT_ID>",  AuthToken:    "<API_TOKEN>",  CacheTTL:     30 * time.Second, // values may be up to this stale  CacheMaxSize: 1000,             // LRU-evicted beyond this many entries})
```

Each cache entry is keyed by flag key, flag type, and the full evaluation context, so distinct contexts never share a cached value. Cache hits resolve with `reason == openfeature.CachedReason`.

Disabled flags, errors, and type mismatches are never cached. Because freshness is TTL-based, a flag change in Flagship takes effect after the entry expires.

The cache is per-provider instance, guarded by a mutex for concurrent use, and cleared on `Shutdown`.

## Configuration options

| Option         | Description                                                                                              |
| -------------- | -------------------------------------------------------------------------------------------------------- |
| AppID          | Flagship app ID.                                                                                         |
| AccountID      | Required with AppID.                                                                                     |
| BaseURL        | Base URL override. Defaults to https://api.cloudflare.com.                                               |
| AuthToken      | Adds Authorization: Bearer <token> to each request.                                                      |
| Headers        | Static headers. Explicit Authorization overrides AuthToken.                                              |
| HeadersFactory | Dynamic per-request headers. Values override Headers and AuthToken.                                      |
| HTTPClient     | Custom HTTP client.                                                                                      |
| Timeout        | Per-attempt timeout. Defaults to 5 seconds.                                                              |
| Retries        | Retry attempts on transient errors. Defaults to 1 and is capped at 10.                                   |
| DisableRetries | Disables retries when set to true.                                                                       |
| RetryDelay     | Delay between retries. Defaults to 1 second and is capped at 30 seconds.                                 |
| CacheTTL       | Enables in-memory response caching when greater than 0\. Cached values may be up to this duration stale. |
| CacheMaxSize   | Maximum number of cached entries. LRU-evicted beyond this limit. Defaults to 1000 when CacheTTL is set.  |
| Logging        | Enables debug and error logging. Off by default.                                                         |
| Logger         | Optional slog\-compatible logger. Uses the default slog logger when unset.                               |
| Hooks          | Provider-level OpenFeature hooks.                                                                        |

## Evaluation context

Context attributes are sent as URL query parameters. Supported values are strings, numeric types, booleans, and `time.Time`. `nil` values are skipped. Maps, slices, structs, and other complex values return `INVALID_CONTEXT` through OpenFeature and do not trigger an HTTP request.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/sdk/go/#page","headline":"Go SDK · Cloudflare Flagship docs","description":"Set up the Flagship OpenFeature provider to evaluate Flagship feature flags from Go server applications.","url":"https://developers.cloudflare.com/flagship/sdk/go/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-30","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/sdk/go/","name":"Go SDK"}}]}
```

---

---
title: Python SDK
description: Set up the FlagshipServerProvider to evaluate Flagship feature flags from Python server applications using OpenFeature.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Python SDK

The Python SDK provides an OpenFeature-compatible `FlagshipServerProvider` for server-side Python applications. It evaluates flags over HTTP and does not support the Cloudflare Workers binding.

## Installation

Install with `uv` or `pip`:

Terminal window

```
uv add cloudflare-flagship
```

Terminal window

```
pip install cloudflare-flagship
```

## Setup

Configure the provider with your Flagship app ID, Cloudflare account ID, and an API token with Flagship Evaluate permission.

Python

```
from openfeature import apifrom openfeature.evaluation_context import EvaluationContextfrom flagship import FlagshipServerProvider
api.set_provider(    FlagshipServerProvider(        app_id="<APP_ID>",        account_id="<ACCOUNT_ID>",        auth_token="<API_TOKEN>",    ))
client = api.get_client()enabled = client.get_boolean_value(    "new-checkout",    False,    EvaluationContext(targeting_key="user-42", attributes={"plan": "enterprise"}),)
```

## Flag types

The Python SDK supports all OpenFeature flag types. Python's OpenFeature SDK separates numeric values into integer and float methods.

Python

```
enabled = client.get_boolean_value("new-checkout", False, context)variant = client.get_string_value("homepage-hero", "control", context)limit = client.get_integer_value("upload-limit", 10, context)rate = client.get_float_value("sample-rate", 0.1, context)config = client.get_object_value("ui-config", {"theme": "light"}, context)
```

Use the `*_details` methods when you need the resolved value, reason, variant, or error code.

## Configuration options

| Option           | Type                               | Default | Description                                                 |
| ---------------- | ---------------------------------- | ------- | ----------------------------------------------------------- |
| app\_id          | str                                | None    | Flagship app ID.                                            |
| account\_id      | str                                | None    | Required with app\_id.                                      |
| auth\_token      | str                                | None    | Bearer token added to every request.                        |
| headers\_factory | Callable\[\[\], dict\[str, str\]\] | None    | Dynamic per-request headers.                                |
| timeout          | float                              | 5.0     | Request timeout in seconds.                                 |
| retries          | int                                | 1       | Retry attempts on transient errors, capped at 10.           |
| retry\_delay     | float                              | 1.0     | Delay between retries in seconds, capped at 30.0.           |
| logging          | bool                               | False   | Enable SDK-level debug output through the SDK logger.       |
| cache\_ttl       | float                              | None    | Cache TTL in seconds. Enables caching when set.             |
| cache\_max\_size | int                                | 1000    | Maximum cached entries before least-recently-used eviction. |

## Response caching

Server-side response caching is off by default. Enable it with `cache_ttl` when you want repeated evaluations for the same flag, type, and evaluation context to reuse a recent result.

Python

```
FlagshipServerProvider(    app_id="<APP_ID>",    account_id="<ACCOUNT_ID>",    auth_token="<API_TOKEN>",    cache_ttl=30.0,    cache_max_size=1000,)
```

Cached values may be stale until the TTL expires. Keep the TTL short for flags that you expect to change during active rollouts. The provider does not cache disabled flags or errors.

## Evaluation context

Context attributes are sent as URL query parameters. Supported values are strings, integers, floats, booleans, and `datetime` values. Dictionaries, lists, tuples, and other complex values raise `InvalidContextError`.

## Async evaluation

The async API mirrors the sync API:

Python

```
enabled = await client.get_boolean_value_async("new-checkout", False, context)details = await client.get_boolean_details_async("new-checkout", False, context)
```

When shutting down in an async context, use `shutdown_async()`:

Python

```
await api.shutdown_async()
```

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/sdk/python/#page","headline":"Python SDK · Cloudflare Flagship docs","description":"Set up the FlagshipServerProvider to evaluate Flagship feature flags from Python server applications using OpenFeature.","url":"https://developers.cloudflare.com/flagship/sdk/python/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/sdk/python/","name":"Python SDK"}}]}
```

---

---
title: TypeScript Server SDK
description: Set up the FlagshipServerProvider to evaluate feature flags from Workers, Node.js, or other server-side JavaScript runtimes using OpenFeature.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# TypeScript Server SDK

The `FlagshipServerProvider` implements the OpenFeature server provider interface. The provider works in [Cloudflare Workers](https://developers.cloudflare.com/workers/), Node.js, and any server-side JavaScript runtime that supports the Fetch API.

Inside a Cloudflare Worker, you can pass the Flagship [binding](https://developers.cloudflare.com/flagship/binding/) directly to the provider. This avoids HTTP overhead and is the recommended approach. Outside of Workers, initialize the provider with an app ID and account ID.

## Setup

* [ With binding ](#tab-panel-8914)
* [ With app ID ](#tab-panel-8915)

Pass the Flagship binding directly to the provider. This is the recommended approach inside a Worker.

* [  JavaScript ](#tab-panel-8912)
* [  TypeScript ](#tab-panel-8913)

JavaScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
export default {  async fetch(request, env) {    await OpenFeature.setProviderAndWait(      new FlagshipServerProvider({ binding: env.FLAGS }),    );
    const client = OpenFeature.getClient();
    const showNewCheckout = await client.getBooleanValue(      "new-checkout",      false,      { targetingKey: "user-42", plan: "enterprise" },    );
    if (showNewCheckout) {      return new Response("New checkout enabled!");    }
    return new Response("Standard checkout.");  },};
```

TypeScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
export default {  async fetch(request: Request, env: Env): Promise<Response> {    await OpenFeature.setProviderAndWait(      new FlagshipServerProvider({ binding: env.FLAGS }),    );
    const client = OpenFeature.getClient();
    const showNewCheckout = await client.getBooleanValue(      "new-checkout",      false,      { targetingKey: "user-42", plan: "enterprise" },    );
    if (showNewCheckout) {      return new Response("New checkout enabled!");    }
    return new Response("Standard checkout.");  },};
```

Use an app ID, account ID, and an API token when running outside of a Worker (for example, in Node.js). Generate an [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) from your Cloudflare account with Flagship read permissions.

* [  JavaScript ](#tab-panel-8908)
* [  TypeScript ](#tab-panel-8909)

JavaScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
await OpenFeature.setProviderAndWait(  new FlagshipServerProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",  }),);
const client = OpenFeature.getClient();
const showNewCheckout = await client.getBooleanValue("new-checkout", false, {  targetingKey: "user-42",  plan: "enterprise",});
```

TypeScript

```
import { OpenFeature } from "@openfeature/server-sdk";import { FlagshipServerProvider } from "@cloudflare/flagship/server";
await OpenFeature.setProviderAndWait(  new FlagshipServerProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",  }),);
const client = OpenFeature.getClient();
const showNewCheckout = await client.getBooleanValue("new-checkout", false, {  targetingKey: "user-42",  plan: "enterprise",});
```

## Configuration options

| Option       | Type        | Required | Description                                                                                                                                                               |
| ------------ | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| binding      | Flagship    | No       | The Flagship binding from env.FLAGS. Use this inside a Worker for best performance. The binding handles authentication automatically.                                     |
| appId        | string      | No       | The Flagship app ID from the Cloudflare dashboard. Required when not using a binding.                                                                                     |
| accountId    | string      | No       | Your Cloudflare account ID. Required when using appId.                                                                                                                    |
| authToken    | string      | No       | A Cloudflare [API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) with Flagship read permissions. Required when not using a binding. |
| fetchOptions | RequestInit | No       | Custom fetch options applied to HTTP requests.                                                                                                                            |
| timeout      | number      | No       | Request timeout in milliseconds. Defaults to 5000.                                                                                                                        |
| retries      | number      | No       | Retry attempts on transient errors. Defaults to 1 and is capped at 10.                                                                                                    |
| retryDelay   | number      | No       | Delay between retries in milliseconds. Defaults to 1000 and is capped at 30000.                                                                                           |
| cacheTtl     | number      | No       | Cache TTL in milliseconds. Enables response caching when greater than 0.                                                                                                  |
| cacheMaxSize | number      | No       | Maximum cached entries. Defaults to 1000 when cacheTtl is set.                                                                                                            |

Provide either `binding` or `appId`, `accountId`, and `authToken`.

## Response caching

Server-side response caching is off by default. Enable it with `cacheTtl` when you want repeated evaluations for the same flag, type, and evaluation context to reuse a recent result.

TypeScript

```
new FlagshipServerProvider({  appId: "<APP_ID>",  accountId: "<ACCOUNT_ID>",  authToken: "<API_TOKEN>",  cacheTtl: 30_000,  cacheMaxSize: 1000,});
```

Use caching for high-traffic server applications that repeatedly evaluate the same flags for the same contexts. Cached values may be stale until the TTL expires, so keep the TTL short for flags that you expect to change during active rollouts. The provider does not cache disabled flags or errors.

## Evaluation context

OpenFeature uses an evaluation context to pass user attributes to the flag provider. The `targetingKey` field is the primary user identifier.

Pass additional attributes alongside `targetingKey` to match [targeting rules](https://developers.cloudflare.com/flagship/targeting/). For example, you can include `plan`, `country`, or any custom attribute your rules reference.

Use primitive context values such as strings, numbers, booleans, and `Date` objects. The provider rejects objects and arrays as invalid context.

* [  JavaScript ](#tab-panel-8904)
* [  TypeScript ](#tab-panel-8905)

JavaScript

```
const value = await client.getBooleanValue("new-checkout", false, {  targetingKey: "user-42",  plan: "enterprise",  country: "US",});
```

TypeScript

```
const value = await client.getBooleanValue("new-checkout", false, {  targetingKey: "user-42",  plan: "enterprise",  country: "US",});
```

## Available hooks

The SDK ships with two hooks that you can attach to the OpenFeature client.

* **LoggingHook** — Logs structured information for every evaluation.
* **TelemetryHook** — Captures timing and event data for observability.

* [  JavaScript ](#tab-panel-8906)
* [  TypeScript ](#tab-panel-8907)

JavaScript

```
import { LoggingHook, TelemetryHook } from "@cloudflare/flagship/server";
OpenFeature.addHooks(new LoggingHook(), new TelemetryHook());
```

TypeScript

```
import { LoggingHook, TelemetryHook } from "@cloudflare/flagship/server";
OpenFeature.addHooks(new LoggingHook(), new TelemetryHook());
```

## Migrate from another provider

If you use another OpenFeature-compatible provider (for example, LaunchDarkly or Flagsmith), switch to Flagship by replacing the provider initialization. No changes are needed at evaluation call sites.

* [  JavaScript ](#tab-panel-8910)
* [  TypeScript ](#tab-panel-8911)

JavaScript

```
// Beforeawait OpenFeature.setProviderAndWait(  new LaunchDarklyProvider({ sdkKey: "..." }),);
// Afterawait OpenFeature.setProviderAndWait(  new FlagshipServerProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",  }),);
```

TypeScript

```
// Beforeawait OpenFeature.setProviderAndWait(  new LaunchDarklyProvider({ sdkKey: "..." }),);
// Afterawait OpenFeature.setProviderAndWait(  new FlagshipServerProvider({    appId: "<APP_ID>",    accountId: "<ACCOUNT_ID>",    authToken: "<API_TOKEN>",  }),);
```

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/sdk/server-provider/#page","headline":"TypeScript Server SDK · Cloudflare Flagship docs","description":"Set up the FlagshipServerProvider to evaluate feature flags from Workers, Node.js, or other server-side JavaScript runtimes using OpenFeature.","url":"https://developers.cloudflare.com/flagship/sdk/server-provider/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/sdk/","name":"OpenFeature SDK"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/sdk/server-provider/","name":"TypeScript Server SDK"}}]}
```

---

---
title: Targeting rules
description: Serve different Flagship flag values to different users based on attributes, conditions, and logical grouping.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Targeting rules

Targeting rules let you serve different flag values to different users based on their attributes. Each flag can have zero or more rules.

Rules are evaluated in sequential order, from top to bottom. The first rule whose conditions match is used, and its configured variant is returned. If no rule matches, Flagship returns the flag's default variant.

When a flag is disabled, the default variant is always returned regardless of rules.

Place more specific rules before broader rules. A broad catch-all rule can prevent later rules from running.

## How rules work

A rule consists of:

* **Conditions** — One or more attribute comparisons that must be satisfied. For example, `country equals "US"` or `plan in ["enterprise", "business"]`.
* **Serve variant** — The variant to return when the rule matches.
* **Rollout** (optional) — A percentage-based gradual release. Only the specified percentage of matching users receive the rule's variant. The rest continue to the next rule.

## Condition structure

Each condition compares an attribute from the evaluation context against a value using an operator:

* **Attribute** — The context key to evaluate (for example, `userId`, `country`, `plan`).
* **Operator** — The comparison to perform. Flagship supports [11 operators](https://developers.cloudflare.com/flagship/targeting/operators/).
* **Value** — The value to compare against. Can be a string, number, or array depending on the operator.

If the evaluation context does not include the attribute referenced by a condition, that condition does not match.

## Logical grouping

Conditions within a rule can be grouped with `AND`/`OR` operators and nested up to five levels deep.

For example, to target enterprise users in the US or Canada:

* `AND`:  
  * `plan equals "enterprise"`
  * `OR`:  
    * `country equals "US"`
    * `country equals "CA"`

Use the smallest set of context attributes necessary to express the rule. This keeps rule behavior easier to reason about and avoids sending unnecessary user data in evaluation context.

## Learn more

* [ Operators ](https://developers.cloudflare.com/flagship/targeting/operators/)
* [ Percentage rollouts ](https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/)

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/flagship/targeting/#page","headline":"Targeting rules · Cloudflare Flagship docs","description":"Serve different Flagship flag values to different users based on attributes, conditions, and logical grouping.","url":"https://developers.cloudflare.com/flagship/targeting/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/targeting/","name":"Targeting rules"}}]}
```

---

---
title: Operators
description: Reference for the 11 comparison operators available in Flagship targeting rule conditions, including equality, comparison, string, and array operators.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Operators

Flagship supports 11 comparison operators for targeting rule conditions. Each operator compares an attribute from the [evaluation context](https://developers.cloudflare.com/flagship/concepts/#evaluation-context) against a specified value.

## Operator reference

| Operator                  | Description                                                                          | Example                                                 | Value type                |
| ------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------- | ------------------------- |
| equals                    | Returns true if the attribute value matches the specified value.                     | country equals "US"                                     | String                    |
| not\_equals               | Returns true if the attribute value does not match the specified value.              | plan not\_equals "free"                                 | String                    |
| greater\_than             | Returns true if the attribute value is greater than the specified value.             | age greater\_than 18                                    | Number, ISO 8601 datetime |
| less\_than                | Returns true if the attribute value is less than the specified value.                | loginCount less\_than 5                                 | Number, ISO 8601 datetime |
| greater\_than\_or\_equals | Returns true if the attribute value is greater than or equal to the specified value. | score greater\_than\_or\_equals 90                      | Number, ISO 8601 datetime |
| less\_than\_or\_equals    | Returns true if the attribute value is less than or equal to the specified value.    | createdAt less\_than\_or\_equals "2025-01-01T00:00:00Z" | Number, ISO 8601 datetime |
| contains                  | Returns true if the attribute value contains the specified substring.                | email contains "@cloudflare.com"                        | String                    |
| starts\_with              | Returns true if the attribute value starts with the specified prefix.                | path starts\_with "/api/v2"                             | String                    |
| ends\_with                | Returns true if the attribute value ends with the specified suffix.                  | domain ends\_with ".dev"                                | String                    |
| in                        | Returns true if the attribute value is in the specified array.                       | country in \["US", "CA", "UK"\]                         | Array                     |
| not\_in                   | Returns true if the attribute value is not in the specified array.                   | userId not\_in \["blocked-1", "blocked-2"\]             | Array                     |

## Operator categories

### Equality operators

`equals`, `not_equals`

Use these operators for exact string matching. The comparison is case-sensitive.

### Comparison operators

`greater_than`, `less_than`, `greater_than_or_equals`, `less_than_or_equals`

These operators work with numeric values and ISO 8601 datetime strings. When comparing datetimes, provide the value in ISO 8601 format (for example, `"2025-01-01T00:00:00Z"`).

### String operators

`contains`, `starts_with`, `ends_with`

These operators perform substring matching against the attribute value. All string comparisons are case-sensitive.

### Array operators

`in`, `not_in`

The value must be an array. Flagship checks whether the attribute value is a member of the specified array.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/targeting/operators/#page","headline":"Operators · Cloudflare Flagship docs","description":"Reference for the 11 comparison operators available in Flagship targeting rule conditions, including equality, comparison, string, and array operators.","url":"https://developers.cloudflare.com/flagship/targeting/operators/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-04-21","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/targeting/","name":"Targeting rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/targeting/operators/","name":"Operators"}}]}
```

---

---
title: Percentage rollouts
description: Gradually release features to a fraction of users with Flagship percentage rollouts and consistent hashing for sticky bucketing.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Percentage rollouts

Percentage rollouts let you gradually release a feature to a fraction of your users. Any [targeting rule](https://developers.cloudflare.com/flagship/targeting/) can include a rollout percentage between 0 and 100.

Use percentage rollouts when you want to limit blast radius, run an experiment, or sample requests without deploying new code.

## How percentage rollouts work

When a rule has a percentage rollout, the rule only serves its variant when both the rule conditions and the rollout bucket match. Contexts that do not match the rule continue to the next rule or receive the default variant if no later rule matches.

For example, a rule can target users on the `enterprise` plan, then serve the new experience to only 10% of those users. Users outside the 10% continue through the rest of the rule list.

```
{  "priority": 1,  "conditions": [    { "attribute": "plan", "operator": "equals", "value": "enterprise" }  ],  "serve_variation": "on",  "rollout": {    "percentage": 10,    "attribute": "userId"  }}
```

The `reason` in evaluation details is `SPLIT` when a percentage rollout serves the variant.

## Sticky bucketing

Flagship uses consistent hashing on a configurable attribute to assign users to a rollout bucket. The same user always receives the same flag value for a given rollout configuration. This ensures a consistent experience across repeated evaluations.

By default, the bucketing attribute is `targetingKey`. You can configure which attribute to use for bucketing when you set up the rollout in the dashboard.

Rollout buckets are independent across accounts and flags. The same identifier may fall into different buckets for different flags, which helps avoid correlated rollouts across unrelated features.

Choose a bucketing attribute based on what should remain stable:

| Use case               | Suggested attribute                     |
| ---------------------- | --------------------------------------- |
| User-facing release    | Stable user ID or targetingKey          |
| Account-level rollout  | Account ID                              |
| Organization rollout   | Organization or workspace ID            |
| Request-level sampling | Request ID or another per-request value |

For most feature releases and experiments, use a stable user or account identifier. Use request-level values only when changing between requests is acceptable, such as for traffic sampling.

Random assignment without targetingKey

If `targetingKey` is not present in the evaluation context and no alternative bucketing attribute is configured, Flagship cannot produce a stable hash. In this case the rollout bucket is assigned randomly on each evaluation, meaning the same user may receive different flag values across requests.

Always provide a stable `targetingKey` (or configure a consistent bucketing attribute) to guarantee sticky bucketing.

## Common rollout patterns

### Progressive rollout

Start with a small rollout, monitor your application, then increase the percentage as confidence grows.

1. Create a flag with a 5% rollout.
2. Monitor errors, latency, product metrics, and user feedback.
3. Increase to 25%, then 50%, then 100%.
4. After the rollout reaches 100%, remove temporary targeting rules and make the winning variant the default.
5. After the feature is fully shipped, remove the old code path and delete the flag.

### Targeted rollout plus percentage rollout

Consider a flag `new-checkout` with the following rules:

1. **Rule 1**: `plan equals "enterprise"` — serve variant `on`.
2. **Rule 2**: 25% rollout on `userId` — serve variant `on`.
3. **Default variant**: `off`.

In this configuration:

* All enterprise users see the new checkout.
* 25% of all other users, determined by their `userId`, also see the new checkout.
* The remaining 75% of non-enterprise users see the standard checkout.

As you gain confidence, increase the rollout percentage until you reach 100%.

### A/B/n testing

For a plain A/B/n test with no audience conditions, configure each variant's traffic share in the Cloudflare dashboard. The dashboard calculates the cumulative thresholds for you.

If you manage a plain A/B/n test directly through the API, create one rule per variant with cumulative rollout percentages. Flagship evaluates rules in priority order. If a context matches a rule but does not fall into that rule's rollout percentage, evaluation continues to the next rule.

For a 30% / 40% / 30% split across variants A, B, and C:

| Variant | Share | Cumulative threshold |
| ------- | ----- | -------------------- |
| A       | 30%   | 30                   |
| B       | 40%   | 70                   |
| C       | 30%   | 100                  |

```
[  {    "priority": 1,    "conditions": [],    "serve_variation": "variant-a",    "rollout": { "percentage": 30, "attribute": "targetingKey" }  },  {    "priority": 2,    "conditions": [],    "serve_variation": "variant-b",    "rollout": { "percentage": 70, "attribute": "targetingKey" }  },  {    "priority": 3,    "conditions": [],    "serve_variation": "variant-c",    "rollout": { "percentage": 100, "attribute": "targetingKey" }  }]
```

In API-managed configurations, the first rule covers buckets 0-30\. The second rule covers buckets 31-70\. The final rule catches the remaining buckets through 100\. Always set the final rule to 100 when every eligible context should receive a variant.

Use the same bucketing attribute on every rule in the experiment. If each rule uses a different attribute, users may not stay in the intended split.

### Targeted A/B/n testing

You can combine audience targeting with a multi-variant rollout. For example, you might want only premium users to enter an experiment, then split those premium users across three variants.

For targeted A/B/n tests, repeat the same audience condition on each variant rule and use cumulative rollout thresholds. When you use this targeted multi-rule pattern, configure the cumulative threshold for each rule explicitly, whether you are using the dashboard or the API.

For a premium-only split where 20% receive variant A, 40% receive variant B, and the remaining 40% receive variant C, use thresholds of 20, 60, and 100:

```
[  {    "priority": 1,    "conditions": [      { "attribute": "plan", "operator": "equals", "value": "premium" }    ],    "serve_variation": "variant-a",    "rollout": { "percentage": 20, "attribute": "targetingKey" }  },  {    "priority": 2,    "conditions": [      { "attribute": "plan", "operator": "equals", "value": "premium" }    ],    "serve_variation": "variant-b",    "rollout": { "percentage": 60, "attribute": "targetingKey" }  },  {    "priority": 3,    "conditions": [      { "attribute": "plan", "operator": "equals", "value": "premium" }    ],    "serve_variation": "variant-c",    "rollout": { "percentage": 100, "attribute": "targetingKey" }  }]
```

Users who do not match `plan equals "premium"` skip all three rules and receive the flag's default variant, unless a later rule matches them.

### Request sampling

You can use percentage rollouts for request-level sampling by choosing a per-request bucketing attribute. For example, a 1% rollout can enable extra logging or diagnostics for a small fraction of requests.

Only use this pattern when it is acceptable for the same user to receive different results on different requests.

## Troubleshooting

### Rollout results change between requests

If the same user receives different values across requests, the evaluation context is probably missing `targetingKey` or the configured bucketing attribute.

Pass the same stable identifier on every evaluation:

TypeScript

```
const enabled = await env.FLAGS.getBooleanValue("gradual-rollout", false, {  userId: session.user.id,});
```

Then configure the rollout to bucket by `userId`.

### Rollout never reaches some users

Check rule order. A catch-all rule with a lower priority number can return a variant before later rollout rules run. Place broad catch-all rules after more specific rules.

### A/B/n split does not match expected percentages

For plain dashboard-managed A/B/n tests, enter each variant's traffic share and let the dashboard calculate thresholds.

For API-managed A/B/n tests, or for targeted A/B/n tests configured as multiple rules, use cumulative thresholds. A 30% / 40% / 30% split should use thresholds of 30, 70, and 100, not 30, 40, and 30.

### Default variant appears during a rollout

This can happen when a context matches the rule conditions but falls outside the rollout percentage, and no later rule matches. Add a later rule or use a 100% final rule if every matching context should receive a non-default variant.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/#page","headline":"Percentage rollouts · Cloudflare Flagship docs","description":"Gradually release features to a fraction of users with Flagship percentage rollouts and consistent hashing for sticky bucketing.","url":"https://developers.cloudflare.com/flagship/targeting/percentage-rollouts/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/targeting/","name":"Targeting rules"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/targeting/percentage-rollouts/","name":"Percentage rollouts"}}]}
```

---

# Flagship

# Apps

## List apps

**get** `/accounts/{account_id}/flagship/apps`

Lists all apps in the account. Returns identity and audit fields only — flag definitions are not included.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: array of object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": [
    {
      "id": "id",
      "created_at": "created_at",
      "name": "name",
      "updated_at": "updated_at",
      "updated_by": "updated_by"
    }
  ],
  "success": true
}
```

## Get app

**get** `/accounts/{account_id}/flagship/apps/{app_id}`

Returns an app's name and audit fields. Flag definitions are not included.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "id": "id",
    "created_at": "created_at",
    "name": "name",
    "updated_at": "updated_at",
    "updated_by": "updated_by"
  },
  "success": true
}
```

## Create app

**post** `/accounts/{account_id}/flagship/apps`

Creates an app. The returned `id` is used in all subsequent flag, changelog, and evaluation requests.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

### Body Parameters

- `name: string`

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -d '{
          "name": "x"
        }'
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "id": "id",
    "created_at": "created_at",
    "name": "name",
    "updated_at": "updated_at",
    "updated_by": "updated_by"
  },
  "success": true
}
```

## Update app

**put** `/accounts/{account_id}/flagship/apps/{app_id}`

Updates an app. Only `name` is mutable.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

### Body Parameters

- `name: optional string`

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID \
    -X PUT \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -d '{}'
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "id": "id",
    "created_at": "created_at",
    "name": "name",
    "updated_at": "updated_at",
    "updated_by": "updated_by"
  },
  "success": true
}
```

## Delete app

**delete** `/accounts/{account_id}/flagship/apps/{app_id}`

Deletes an app and all its flags and changelog history. Returns 409 if any Worker still references this app via a Flagship binding.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { id }`

  - `id: string`

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID \
    -X DELETE \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "id": "id"
  },
  "success": true
}
```

## Domain Types

### App List Response

- `AppListResponse object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

### App Get Response

- `AppGetResponse object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

### App Create Response

- `AppCreateResponse object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

### App Update Response

- `AppUpdateResponse object { id, created_at, name, 2 more }`

  - `id: string`

  - `created_at: string`

  - `name: string`

  - `updated_at: string`

  - `updated_by: string`

    Email of the actor who last modified the app, or `edge-gateway` for gateway-authenticated changes.

### App Delete Response

- `AppDeleteResponse object { id }`

  - `id: string`

# Flags

## List flags

**get** `/accounts/{account_id}/flagship/apps/{app_id}/flags`

Lists an app's flags ordered by key. Pass `cursor` from `result_info` to page forward; a null cursor indicates the last page.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

### Query Parameters

- `cursor: optional string`

  Pagination cursor from a previous response.

- `limit: optional string`

  Max items to return (1–200).

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: array of object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

- `result_info: object { count, cursor }`

  - `count: number`

    Number of items returned in this page.

  - `cursor: string`

    Cursor to pass back to fetch the next page, or null when this is the last page.

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/flags \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": [
    {
      "default_variation": "x",
      "enabled": true,
      "key": "x",
      "rules": [
        {
          "conditions": [
            {
              "attribute": "x",
              "operator": "equals",
              "value": {}
            }
          ],
          "priority": 1,
          "serve_variation": "x",
          "rollout": {
            "percentage": 0,
            "attribute": "x"
          }
        }
      ],
      "variations": {
        "foo": "string"
      },
      "description": "description",
      "type": "boolean",
      "updated_at": "updated_at",
      "updated_by": "updated_by"
    }
  ],
  "result_info": {
    "count": 0,
    "cursor": "cursor"
  },
  "success": true
}
```

## Get flag

**get** `/accounts/{account_id}/flagship/apps/{app_id}/flags/{flag_key}`

Returns the full flag definition including rules, variations, and audit fields.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

- `flag_key: string`

  Flag key (slug).

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/flags/$FLAG_KEY \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "default_variation": "x",
    "enabled": true,
    "key": "x",
    "rules": [
      {
        "conditions": [
          {
            "attribute": "x",
            "operator": "equals",
            "value": {}
          }
        ],
        "priority": 1,
        "serve_variation": "x",
        "rollout": {
          "percentage": 0,
          "attribute": "x"
        }
      }
    ],
    "variations": {
      "foo": "string"
    },
    "description": "description",
    "type": "boolean",
    "updated_at": "updated_at",
    "updated_by": "updated_by"
  },
  "success": true
}
```

## Create flag

**post** `/accounts/{account_id}/flagship/apps/{app_id}/flags`

Creates a flag. Returns 409 if the key already exists. `type` is inferred from variation values and may be omitted.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

### Body Parameters

- `default_variation: string`

  Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

- `enabled: boolean`

  When false, the flag bypasses all rules and always serves `default_variation`.

- `key: string`

  Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

- `rules: array of object { conditions, priority, serve_variation, rollout }`

  Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

  - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

    Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

    - `object { attribute, operator, value }`

      - `attribute: string`

      - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

        - `"equals"`

        - `"not_equals"`

        - `"greater_than"`

        - `"less_than"`

        - `"greater_than_or_equals"`

        - `"less_than_or_equals"`

        - `"contains"`

        - `"starts_with"`

        - `"ends_with"`

        - `"in"`

        - `"not_in"`

      - `value: unknown`

        Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

    - `object { clauses, logical_operator }`

      - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

        - `object { attribute, operator, value }`

          - `attribute: string`

          - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

            - `"equals"`

            - `"not_equals"`

            - `"greater_than"`

            - `"less_than"`

            - `"greater_than_or_equals"`

            - `"less_than_or_equals"`

            - `"contains"`

            - `"starts_with"`

            - `"ends_with"`

            - `"in"`

            - `"not_in"`

          - `value: unknown`

            Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

        - `object { clauses, logical_operator }`

          - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

            - `object { attribute, operator, value }`

              - `attribute: string`

              - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                - `"equals"`

                - `"not_equals"`

                - `"greater_than"`

                - `"less_than"`

                - `"greater_than_or_equals"`

                - `"less_than_or_equals"`

                - `"contains"`

                - `"starts_with"`

                - `"ends_with"`

                - `"in"`

                - `"not_in"`

              - `value: unknown`

                Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

            - `object { clauses, logical_operator }`

              - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                - `object { attribute, operator, value }`

                  - `attribute: string`

                  - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                    - `"equals"`

                    - `"not_equals"`

                    - `"greater_than"`

                    - `"less_than"`

                    - `"greater_than_or_equals"`

                    - `"less_than_or_equals"`

                    - `"contains"`

                    - `"starts_with"`

                    - `"ends_with"`

                    - `"in"`

                    - `"not_in"`

                  - `value: unknown`

                    Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                - `object { clauses, logical_operator }`

                  - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                    - `object { attribute, operator, value }`

                      - `attribute: string`

                      - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                        - `"equals"`

                        - `"not_equals"`

                        - `"greater_than"`

                        - `"less_than"`

                        - `"greater_than_or_equals"`

                        - `"less_than_or_equals"`

                        - `"contains"`

                        - `"starts_with"`

                        - `"ends_with"`

                        - `"in"`

                        - `"not_in"`

                      - `value: unknown`

                        Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                    - `object { clauses, logical_operator }`

                      - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                        - `object { attribute, operator, value }`

                          - `attribute: string`

                          - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                            - `"equals"`

                            - `"not_equals"`

                            - `"greater_than"`

                            - `"less_than"`

                            - `"greater_than_or_equals"`

                            - `"less_than_or_equals"`

                            - `"contains"`

                            - `"starts_with"`

                            - `"ends_with"`

                            - `"in"`

                            - `"not_in"`

                          - `value: unknown`

                            Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                        - `object { clauses, logical_operator }`

                          - `clauses: array of string or number or boolean or 2 more`

                            - `string`

                            - `number`

                            - `boolean`

                            - `map[unknown]`

                            - `array of unknown`

                          - `logical_operator: "AND" or "OR"`

                            - `"AND"`

                            - `"OR"`

                      - `logical_operator: "AND" or "OR"`

                        - `"AND"`

                        - `"OR"`

                  - `logical_operator: "AND" or "OR"`

                    - `"AND"`

                    - `"OR"`

              - `logical_operator: "AND" or "OR"`

                - `"AND"`

                - `"OR"`

          - `logical_operator: "AND" or "OR"`

            - `"AND"`

            - `"OR"`

      - `logical_operator: "AND" or "OR"`

        - `"AND"`

        - `"OR"`

  - `priority: number`

    Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

  - `serve_variation: string`

    Variation served when this rule matches. Must be a key in `variations`.

  - `rollout: optional object { percentage, attribute }`

    - `percentage: number`

      Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

    - `attribute: optional string`

      Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

- `variations: map[string or number or boolean or 2 more]`

  Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

  - `string`

  - `number`

  - `boolean`

  - `map[unknown]`

  - `array of unknown`

- `description: optional string`

- `type: optional "boolean" or "string" or "number" or "json"`

  Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

  - `"boolean"`

  - `"string"`

  - `"number"`

  - `"json"`

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/flags \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -d '{
          "default_variation": "x",
          "enabled": true,
          "key": "x",
          "rules": [
            {
              "conditions": [
                {
                  "attribute": "x",
                  "operator": "equals",
                  "value": {}
                }
              ],
              "priority": 1,
              "serve_variation": "x"
            }
          ],
          "variations": {
            "foo": "string"
          }
        }'
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "default_variation": "x",
    "enabled": true,
    "key": "x",
    "rules": [
      {
        "conditions": [
          {
            "attribute": "x",
            "operator": "equals",
            "value": {}
          }
        ],
        "priority": 1,
        "serve_variation": "x",
        "rollout": {
          "percentage": 0,
          "attribute": "x"
        }
      }
    ],
    "variations": {
      "foo": "string"
    },
    "description": "description",
    "type": "boolean",
    "updated_at": "updated_at",
    "updated_by": "updated_by"
  },
  "success": true
}
```

## Update flag

**put** `/accounts/{account_id}/flagship/apps/{app_id}/flags/{flag_key}`

Replaces the entire flag definition. Omitted fields are dropped, not preserved — read before writing. Each update appends a changelog entry.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

- `flag_key: string`

  Flag key (slug).

### Body Parameters

- `default_variation: string`

  Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

- `enabled: boolean`

  When false, the flag bypasses all rules and always serves `default_variation`.

- `key: string`

  Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

- `rules: array of object { conditions, priority, serve_variation, rollout }`

  Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

  - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

    Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

    - `object { attribute, operator, value }`

      - `attribute: string`

      - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

        - `"equals"`

        - `"not_equals"`

        - `"greater_than"`

        - `"less_than"`

        - `"greater_than_or_equals"`

        - `"less_than_or_equals"`

        - `"contains"`

        - `"starts_with"`

        - `"ends_with"`

        - `"in"`

        - `"not_in"`

      - `value: unknown`

        Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

    - `object { clauses, logical_operator }`

      - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

        - `object { attribute, operator, value }`

          - `attribute: string`

          - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

            - `"equals"`

            - `"not_equals"`

            - `"greater_than"`

            - `"less_than"`

            - `"greater_than_or_equals"`

            - `"less_than_or_equals"`

            - `"contains"`

            - `"starts_with"`

            - `"ends_with"`

            - `"in"`

            - `"not_in"`

          - `value: unknown`

            Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

        - `object { clauses, logical_operator }`

          - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

            - `object { attribute, operator, value }`

              - `attribute: string`

              - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                - `"equals"`

                - `"not_equals"`

                - `"greater_than"`

                - `"less_than"`

                - `"greater_than_or_equals"`

                - `"less_than_or_equals"`

                - `"contains"`

                - `"starts_with"`

                - `"ends_with"`

                - `"in"`

                - `"not_in"`

              - `value: unknown`

                Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

            - `object { clauses, logical_operator }`

              - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                - `object { attribute, operator, value }`

                  - `attribute: string`

                  - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                    - `"equals"`

                    - `"not_equals"`

                    - `"greater_than"`

                    - `"less_than"`

                    - `"greater_than_or_equals"`

                    - `"less_than_or_equals"`

                    - `"contains"`

                    - `"starts_with"`

                    - `"ends_with"`

                    - `"in"`

                    - `"not_in"`

                  - `value: unknown`

                    Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                - `object { clauses, logical_operator }`

                  - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                    - `object { attribute, operator, value }`

                      - `attribute: string`

                      - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                        - `"equals"`

                        - `"not_equals"`

                        - `"greater_than"`

                        - `"less_than"`

                        - `"greater_than_or_equals"`

                        - `"less_than_or_equals"`

                        - `"contains"`

                        - `"starts_with"`

                        - `"ends_with"`

                        - `"in"`

                        - `"not_in"`

                      - `value: unknown`

                        Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                    - `object { clauses, logical_operator }`

                      - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                        - `object { attribute, operator, value }`

                          - `attribute: string`

                          - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                            - `"equals"`

                            - `"not_equals"`

                            - `"greater_than"`

                            - `"less_than"`

                            - `"greater_than_or_equals"`

                            - `"less_than_or_equals"`

                            - `"contains"`

                            - `"starts_with"`

                            - `"ends_with"`

                            - `"in"`

                            - `"not_in"`

                          - `value: unknown`

                            Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                        - `object { clauses, logical_operator }`

                          - `clauses: array of string or number or boolean or 2 more`

                            - `string`

                            - `number`

                            - `boolean`

                            - `map[unknown]`

                            - `array of unknown`

                          - `logical_operator: "AND" or "OR"`

                            - `"AND"`

                            - `"OR"`

                      - `logical_operator: "AND" or "OR"`

                        - `"AND"`

                        - `"OR"`

                  - `logical_operator: "AND" or "OR"`

                    - `"AND"`

                    - `"OR"`

              - `logical_operator: "AND" or "OR"`

                - `"AND"`

                - `"OR"`

          - `logical_operator: "AND" or "OR"`

            - `"AND"`

            - `"OR"`

      - `logical_operator: "AND" or "OR"`

        - `"AND"`

        - `"OR"`

  - `priority: number`

    Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

  - `serve_variation: string`

    Variation served when this rule matches. Must be a key in `variations`.

  - `rollout: optional object { percentage, attribute }`

    - `percentage: number`

      Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

    - `attribute: optional string`

      Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

- `variations: map[string or number or boolean or 2 more]`

  Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

  - `string`

  - `number`

  - `boolean`

  - `map[unknown]`

  - `array of unknown`

- `description: optional string`

- `type: optional "boolean" or "string" or "number" or "json"`

  Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

  - `"boolean"`

  - `"string"`

  - `"number"`

  - `"json"`

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/flags/$FLAG_KEY \
    -X PUT \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -d '{
          "default_variation": "x",
          "enabled": true,
          "key": "x",
          "rules": [
            {
              "conditions": [
                {
                  "attribute": "x",
                  "operator": "equals",
                  "value": {}
                }
              ],
              "priority": 1,
              "serve_variation": "x"
            }
          ],
          "variations": {
            "foo": "string"
          }
        }'
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "default_variation": "x",
    "enabled": true,
    "key": "x",
    "rules": [
      {
        "conditions": [
          {
            "attribute": "x",
            "operator": "equals",
            "value": {}
          }
        ],
        "priority": 1,
        "serve_variation": "x",
        "rollout": {
          "percentage": 0,
          "attribute": "x"
        }
      }
    ],
    "variations": {
      "foo": "string"
    },
    "description": "description",
    "type": "boolean",
    "updated_at": "updated_at",
    "updated_by": "updated_by"
  },
  "success": true
}
```

## Delete flag

**delete** `/accounts/{account_id}/flagship/apps/{app_id}/flags/{flag_key}`

Permanently deletes a flag. Subsequent evaluations fall back to the caller-supplied default. Cannot be undone.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

- `flag_key: string`

  Flag key (slug).

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: object { key }`

  - `key: string`

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/flags/$FLAG_KEY \
    -X DELETE \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": {
    "key": "key"
  },
  "success": true
}
```

## Domain Types

### Flag List Response

- `FlagListResponse object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

### Flag Get Response

- `FlagGetResponse object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

### Flag Create Response

- `FlagCreateResponse object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

### Flag Update Response

- `FlagUpdateResponse object { default_variation, enabled, key, 6 more }`

  - `default_variation: string`

    Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

  - `enabled: boolean`

    When false, the flag bypasses all rules and always serves `default_variation`.

  - `key: string`

    Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

  - `rules: array of object { conditions, priority, serve_variation, rollout }`

    Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

    - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

      Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

      - `object { attribute, operator, value }`

        - `attribute: string`

        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

          - `"equals"`

          - `"not_equals"`

          - `"greater_than"`

          - `"less_than"`

          - `"greater_than_or_equals"`

          - `"less_than_or_equals"`

          - `"contains"`

          - `"starts_with"`

          - `"ends_with"`

          - `"in"`

          - `"not_in"`

        - `value: unknown`

          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

      - `object { clauses, logical_operator }`

        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of string or number or boolean or 2 more`

                              - `string`

                              - `number`

                              - `boolean`

                              - `map[unknown]`

                              - `array of unknown`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `logical_operator: "AND" or "OR"`

          - `"AND"`

          - `"OR"`

    - `priority: number`

      Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

    - `serve_variation: string`

      Variation served when this rule matches. Must be a key in `variations`.

    - `rollout: optional object { percentage, attribute }`

      - `percentage: number`

        Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

      - `attribute: optional string`

        Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

  - `variations: map[string or number or boolean or 2 more]`

    Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

  - `description: optional string`

  - `type: optional "boolean" or "string" or "number" or "json"`

    Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

    - `"boolean"`

    - `"string"`

    - `"number"`

    - `"json"`

  - `updated_at: optional string`

  - `updated_by: optional string`

### Flag Delete Response

- `FlagDeleteResponse object { key }`

  - `key: string`

# Changelog

## Get flag changelog

**get** `/accounts/{account_id}/flagship/apps/{app_id}/flags/{flag_key}/changelog`

Returns the audit history for a flag, newest first. Each entry includes the event type and full flag state after the change; `update` entries include a field-level diff. Capped at 200 entries per flag.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

- `flag_key: string`

  Flag key (slug).

### Query Parameters

- `cursor: optional string`

  Pagination cursor from a previous response.

- `limit: optional string`

  Max items to return (1–200).

### Returns

- `errors: array of object { message }`

  - `message: string`

- `messages: array of object { message }`

  - `message: string`

- `result: array of object { after, event, flag_key }  or object { after, event, flag_key }  or object { after, diff, event, flag_key }`

  - `object { after, event, flag_key }`

    - `after: object { default_variation, enabled, key, 6 more }`

      - `default_variation: string`

        Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

      - `enabled: boolean`

        When false, the flag bypasses all rules and always serves `default_variation`.

      - `key: string`

        Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

      - `rules: array of object { conditions, priority, serve_variation, rollout }`

        Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

        - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                              - `object { attribute, operator, value }`

                                - `attribute: string`

                                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                                  - `"equals"`

                                  - `"not_equals"`

                                  - `"greater_than"`

                                  - `"less_than"`

                                  - `"greater_than_or_equals"`

                                  - `"less_than_or_equals"`

                                  - `"contains"`

                                  - `"starts_with"`

                                  - `"ends_with"`

                                  - `"in"`

                                  - `"not_in"`

                                - `value: unknown`

                                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                              - `object { clauses, logical_operator }`

                                - `clauses: array of string or number or boolean or 2 more`

                                  - `string`

                                  - `number`

                                  - `boolean`

                                  - `map[unknown]`

                                  - `array of unknown`

                                - `logical_operator: "AND" or "OR"`

                                  - `"AND"`

                                  - `"OR"`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `priority: number`

          Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

        - `serve_variation: string`

          Variation served when this rule matches. Must be a key in `variations`.

        - `rollout: optional object { percentage, attribute }`

          - `percentage: number`

            Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

          - `attribute: optional string`

            Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

      - `variations: map[string or number or boolean or 2 more]`

        Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `description: optional string`

      - `type: optional "boolean" or "string" or "number" or "json"`

        Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

        - `"boolean"`

        - `"string"`

        - `"number"`

        - `"json"`

      - `updated_at: optional string`

      - `updated_by: optional string`

    - `event: "create"`

      - `"create"`

    - `flag_key: string`

  - `object { after, event, flag_key }`

    - `after: object { default_variation, enabled, key, 6 more }`

      - `default_variation: string`

        Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

      - `enabled: boolean`

        When false, the flag bypasses all rules and always serves `default_variation`.

      - `key: string`

        Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

      - `rules: array of object { conditions, priority, serve_variation, rollout }`

        Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

        - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                              - `object { attribute, operator, value }`

                                - `attribute: string`

                                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                                  - `"equals"`

                                  - `"not_equals"`

                                  - `"greater_than"`

                                  - `"less_than"`

                                  - `"greater_than_or_equals"`

                                  - `"less_than_or_equals"`

                                  - `"contains"`

                                  - `"starts_with"`

                                  - `"ends_with"`

                                  - `"in"`

                                  - `"not_in"`

                                - `value: unknown`

                                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                              - `object { clauses, logical_operator }`

                                - `clauses: array of string or number or boolean or 2 more`

                                  - `string`

                                  - `number`

                                  - `boolean`

                                  - `map[unknown]`

                                  - `array of unknown`

                                - `logical_operator: "AND" or "OR"`

                                  - `"AND"`

                                  - `"OR"`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `priority: number`

          Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

        - `serve_variation: string`

          Variation served when this rule matches. Must be a key in `variations`.

        - `rollout: optional object { percentage, attribute }`

          - `percentage: number`

            Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

          - `attribute: optional string`

            Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

      - `variations: map[string or number or boolean or 2 more]`

        Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `description: optional string`

      - `type: optional "boolean" or "string" or "number" or "json"`

        Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

        - `"boolean"`

        - `"string"`

        - `"number"`

        - `"json"`

      - `updated_at: optional string`

      - `updated_by: optional string`

    - `event: "delete"`

      - `"delete"`

    - `flag_key: string`

  - `object { after, diff, event, flag_key }`

    - `after: object { default_variation, enabled, key, 6 more }`

      - `default_variation: string`

        Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

      - `enabled: boolean`

        When false, the flag bypasses all rules and always serves `default_variation`.

      - `key: string`

        Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

      - `rules: array of object { conditions, priority, serve_variation, rollout }`

        Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

        - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                              - `object { attribute, operator, value }`

                                - `attribute: string`

                                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                                  - `"equals"`

                                  - `"not_equals"`

                                  - `"greater_than"`

                                  - `"less_than"`

                                  - `"greater_than_or_equals"`

                                  - `"less_than_or_equals"`

                                  - `"contains"`

                                  - `"starts_with"`

                                  - `"ends_with"`

                                  - `"in"`

                                  - `"not_in"`

                                - `value: unknown`

                                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                              - `object { clauses, logical_operator }`

                                - `clauses: array of string or number or boolean or 2 more`

                                  - `string`

                                  - `number`

                                  - `boolean`

                                  - `map[unknown]`

                                  - `array of unknown`

                                - `logical_operator: "AND" or "OR"`

                                  - `"AND"`

                                  - `"OR"`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `priority: number`

          Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

        - `serve_variation: string`

          Variation served when this rule matches. Must be a key in `variations`.

        - `rollout: optional object { percentage, attribute }`

          - `percentage: number`

            Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

          - `attribute: optional string`

            Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

      - `variations: map[string or number or boolean or 2 more]`

        Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `description: optional string`

      - `type: optional "boolean" or "string" or "number" or "json"`

        Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

        - `"boolean"`

        - `"string"`

        - `"number"`

        - `"json"`

      - `updated_at: optional string`

      - `updated_by: optional string`

    - `diff: map[object { from, to } ]`

      - `from: optional string or number or boolean or 2 more`

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `to: optional string or number or boolean or 2 more`

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

    - `event: "update"`

      - `"update"`

    - `flag_key: string`

- `result_info: object { count, cursor }`

  - `count: number`

    Number of items returned in this page.

  - `cursor: string`

    Cursor to pass back to fetch the next page, or null when this is the last page.

- `success: boolean`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/flags/$FLAG_KEY/changelog \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "message": "message"
    }
  ],
  "messages": [
    {
      "message": "message"
    }
  ],
  "result": [
    {
      "after": {
        "default_variation": "x",
        "enabled": true,
        "key": "x",
        "rules": [
          {
            "conditions": [
              {
                "attribute": "x",
                "operator": "equals",
                "value": {}
              }
            ],
            "priority": 1,
            "serve_variation": "x",
            "rollout": {
              "percentage": 0,
              "attribute": "x"
            }
          }
        ],
        "variations": {
          "foo": "string"
        },
        "description": "description",
        "type": "boolean",
        "updated_at": "updated_at",
        "updated_by": "updated_by"
      },
      "event": "create",
      "flag_key": "flag_key"
    }
  ],
  "result_info": {
    "count": 0,
    "cursor": "cursor"
  },
  "success": true
}
```

## Domain Types

### Changelog List Response

- `ChangelogListResponse = object { after, event, flag_key }  or object { after, event, flag_key }  or object { after, diff, event, flag_key }`

  - `object { after, event, flag_key }`

    - `after: object { default_variation, enabled, key, 6 more }`

      - `default_variation: string`

        Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

      - `enabled: boolean`

        When false, the flag bypasses all rules and always serves `default_variation`.

      - `key: string`

        Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

      - `rules: array of object { conditions, priority, serve_variation, rollout }`

        Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

        - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                              - `object { attribute, operator, value }`

                                - `attribute: string`

                                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                                  - `"equals"`

                                  - `"not_equals"`

                                  - `"greater_than"`

                                  - `"less_than"`

                                  - `"greater_than_or_equals"`

                                  - `"less_than_or_equals"`

                                  - `"contains"`

                                  - `"starts_with"`

                                  - `"ends_with"`

                                  - `"in"`

                                  - `"not_in"`

                                - `value: unknown`

                                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                              - `object { clauses, logical_operator }`

                                - `clauses: array of string or number or boolean or 2 more`

                                  - `string`

                                  - `number`

                                  - `boolean`

                                  - `map[unknown]`

                                  - `array of unknown`

                                - `logical_operator: "AND" or "OR"`

                                  - `"AND"`

                                  - `"OR"`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `priority: number`

          Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

        - `serve_variation: string`

          Variation served when this rule matches. Must be a key in `variations`.

        - `rollout: optional object { percentage, attribute }`

          - `percentage: number`

            Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

          - `attribute: optional string`

            Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

      - `variations: map[string or number or boolean or 2 more]`

        Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `description: optional string`

      - `type: optional "boolean" or "string" or "number" or "json"`

        Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

        - `"boolean"`

        - `"string"`

        - `"number"`

        - `"json"`

      - `updated_at: optional string`

      - `updated_by: optional string`

    - `event: "create"`

      - `"create"`

    - `flag_key: string`

  - `object { after, event, flag_key }`

    - `after: object { default_variation, enabled, key, 6 more }`

      - `default_variation: string`

        Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

      - `enabled: boolean`

        When false, the flag bypasses all rules and always serves `default_variation`.

      - `key: string`

        Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

      - `rules: array of object { conditions, priority, serve_variation, rollout }`

        Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

        - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                              - `object { attribute, operator, value }`

                                - `attribute: string`

                                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                                  - `"equals"`

                                  - `"not_equals"`

                                  - `"greater_than"`

                                  - `"less_than"`

                                  - `"greater_than_or_equals"`

                                  - `"less_than_or_equals"`

                                  - `"contains"`

                                  - `"starts_with"`

                                  - `"ends_with"`

                                  - `"in"`

                                  - `"not_in"`

                                - `value: unknown`

                                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                              - `object { clauses, logical_operator }`

                                - `clauses: array of string or number or boolean or 2 more`

                                  - `string`

                                  - `number`

                                  - `boolean`

                                  - `map[unknown]`

                                  - `array of unknown`

                                - `logical_operator: "AND" or "OR"`

                                  - `"AND"`

                                  - `"OR"`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `priority: number`

          Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

        - `serve_variation: string`

          Variation served when this rule matches. Must be a key in `variations`.

        - `rollout: optional object { percentage, attribute }`

          - `percentage: number`

            Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

          - `attribute: optional string`

            Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

      - `variations: map[string or number or boolean or 2 more]`

        Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `description: optional string`

      - `type: optional "boolean" or "string" or "number" or "json"`

        Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

        - `"boolean"`

        - `"string"`

        - `"number"`

        - `"json"`

      - `updated_at: optional string`

      - `updated_by: optional string`

    - `event: "delete"`

      - `"delete"`

    - `flag_key: string`

  - `object { after, diff, event, flag_key }`

    - `after: object { default_variation, enabled, key, 6 more }`

      - `default_variation: string`

        Variation served when no rule matches or the flag is disabled. Must be a key in `variations`.

      - `enabled: boolean`

        When false, the flag bypasses all rules and always serves `default_variation`.

      - `key: string`

        Unique identifier for the flag within an app. Used in all evaluation and SDK calls.

      - `rules: array of object { conditions, priority, serve_variation, rollout }`

        Targeting rules evaluated in ascending `priority`; the first matching rule wins. An empty array means the flag always serves `default_variation`.

        - `conditions: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

          Conditions the context must satisfy for this rule to match. An empty array matches all contexts.

          - `object { attribute, operator, value }`

            - `attribute: string`

            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

              - `"equals"`

              - `"not_equals"`

              - `"greater_than"`

              - `"less_than"`

              - `"greater_than_or_equals"`

              - `"less_than_or_equals"`

              - `"contains"`

              - `"starts_with"`

              - `"ends_with"`

              - `"in"`

              - `"not_in"`

            - `value: unknown`

              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

          - `object { clauses, logical_operator }`

            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

              - `object { attribute, operator, value }`

                - `attribute: string`

                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                  - `"equals"`

                  - `"not_equals"`

                  - `"greater_than"`

                  - `"less_than"`

                  - `"greater_than_or_equals"`

                  - `"less_than_or_equals"`

                  - `"contains"`

                  - `"starts_with"`

                  - `"ends_with"`

                  - `"in"`

                  - `"not_in"`

                - `value: unknown`

                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

              - `object { clauses, logical_operator }`

                - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                  - `object { attribute, operator, value }`

                    - `attribute: string`

                    - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                      - `"equals"`

                      - `"not_equals"`

                      - `"greater_than"`

                      - `"less_than"`

                      - `"greater_than_or_equals"`

                      - `"less_than_or_equals"`

                      - `"contains"`

                      - `"starts_with"`

                      - `"ends_with"`

                      - `"in"`

                      - `"not_in"`

                    - `value: unknown`

                      Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                  - `object { clauses, logical_operator }`

                    - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                      - `object { attribute, operator, value }`

                        - `attribute: string`

                        - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                          - `"equals"`

                          - `"not_equals"`

                          - `"greater_than"`

                          - `"less_than"`

                          - `"greater_than_or_equals"`

                          - `"less_than_or_equals"`

                          - `"contains"`

                          - `"starts_with"`

                          - `"ends_with"`

                          - `"in"`

                          - `"not_in"`

                        - `value: unknown`

                          Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                      - `object { clauses, logical_operator }`

                        - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                          - `object { attribute, operator, value }`

                            - `attribute: string`

                            - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                              - `"equals"`

                              - `"not_equals"`

                              - `"greater_than"`

                              - `"less_than"`

                              - `"greater_than_or_equals"`

                              - `"less_than_or_equals"`

                              - `"contains"`

                              - `"starts_with"`

                              - `"ends_with"`

                              - `"in"`

                              - `"not_in"`

                            - `value: unknown`

                              Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                          - `object { clauses, logical_operator }`

                            - `clauses: array of object { attribute, operator, value }  or object { clauses, logical_operator }`

                              - `object { attribute, operator, value }`

                                - `attribute: string`

                                - `operator: "equals" or "not_equals" or "greater_than" or 8 more`

                                  - `"equals"`

                                  - `"not_equals"`

                                  - `"greater_than"`

                                  - `"less_than"`

                                  - `"greater_than_or_equals"`

                                  - `"less_than_or_equals"`

                                  - `"contains"`

                                  - `"starts_with"`

                                  - `"ends_with"`

                                  - `"in"`

                                  - `"not_in"`

                                - `value: unknown`

                                  Value to compare against the context attribute. Must be an array for `in` and `not_in`; numeric and ISO-8601 datetime strings are accepted by the ordering operators.

                              - `object { clauses, logical_operator }`

                                - `clauses: array of string or number or boolean or 2 more`

                                  - `string`

                                  - `number`

                                  - `boolean`

                                  - `map[unknown]`

                                  - `array of unknown`

                                - `logical_operator: "AND" or "OR"`

                                  - `"AND"`

                                  - `"OR"`

                            - `logical_operator: "AND" or "OR"`

                              - `"AND"`

                              - `"OR"`

                        - `logical_operator: "AND" or "OR"`

                          - `"AND"`

                          - `"OR"`

                    - `logical_operator: "AND" or "OR"`

                      - `"AND"`

                      - `"OR"`

                - `logical_operator: "AND" or "OR"`

                  - `"AND"`

                  - `"OR"`

            - `logical_operator: "AND" or "OR"`

              - `"AND"`

              - `"OR"`

        - `priority: number`

          Evaluation order; lower numbers are evaluated first. Must be unique across the flag's rules.

        - `serve_variation: string`

          Variation served when this rule matches. Must be a key in `variations`.

        - `rollout: optional object { percentage, attribute }`

          - `percentage: number`

            Percentage of matching traffic (0–100) served this variation. For multi-way splits, use cumulative upper bounds across rules (e.g. 30, 70, 100).

          - `attribute: optional string`

            Context attribute used for sticky bucketing. Defaults to `targetingKey`. If absent at evaluation time, bucketing is random per request.

      - `variations: map[string or number or boolean or 2 more]`

        Map of variation name to value. All values must be the same type (boolean, string, number, or JSON object/array). Each serialized value must be 10KB or smaller.

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `description: optional string`

      - `type: optional "boolean" or "string" or "number" or "json"`

        Value type of the flag's variations. Inferred from the variation values on write, so it may be omitted in requests.

        - `"boolean"`

        - `"string"`

        - `"number"`

        - `"json"`

      - `updated_at: optional string`

      - `updated_by: optional string`

    - `diff: map[object { from, to } ]`

      - `from: optional string or number or boolean or 2 more`

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

      - `to: optional string or number or boolean or 2 more`

        - `string`

        - `number`

        - `boolean`

        - `map[unknown]`

        - `array of unknown`

    - `event: "update"`

      - `"update"`

    - `flag_key: string`

# Evaluate

## Evaluate flag

**get** `/accounts/{account_id}/flagship/apps/{app_id}/evaluate`

Evaluates a flag against the provided context. Pass context attributes as query parameters; boolean and numeric strings are coerced automatically. For low-latency in-Worker evaluation, prefer the Flagship binding over this endpoint.

### Path Parameters

- `account_id: string`

  Cloudflare account ID.

- `app_id: string`

  App identifier.

### Query Parameters

- `flagKey: string`

  The flag key to evaluate.

- `targetingKey: optional string`

  Context targeting key (per OpenFeature spec); used for percentage rollout bucketing.

### Returns

- `flagKey: string`

- `reason: "TARGETING_MATCH" or "DEFAULT" or "DISABLED" or "SPLIT"`

  - `"TARGETING_MATCH"`

  - `"DEFAULT"`

  - `"DISABLED"`

  - `"SPLIT"`

- `variant: string`

- `value: optional string or number or boolean or 2 more`

  - `string`

  - `number`

  - `boolean`

  - `map[unknown]`

  - `array of unknown`

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/flagship/apps/$APP_ID/evaluate \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "flagKey": "flagKey",
  "reason": "TARGETING_MATCH",
  "variant": "variant",
  "value": "string"
}
```

## Domain Types

### Evaluate Get Response

- `EvaluateGetResponse object { flagKey, reason, variant, value }`

  - `flagKey: string`

  - `reason: "TARGETING_MATCH" or "DEFAULT" or "DISABLED" or "SPLIT"`

    - `"TARGETING_MATCH"`

    - `"DEFAULT"`

    - `"DISABLED"`

    - `"SPLIT"`

  - `variant: string`

  - `value: optional string or number or boolean or 2 more`

    - `string`

    - `number`

    - `boolean`

    - `map[unknown]`

    - `array of unknown`

---

---
title: Evaluation reasons and error codes
description: Flagship evaluation reason values and error codes returned by binding details methods and the OpenFeature SDK.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Evaluation reasons and error codes

When you evaluate a flag using the binding's `*Details` methods or the OpenFeature SDK, the response includes a `reason` field that explains why a particular value was returned. If an error occurs, the response includes an `errorCode` field.

## Evaluation reasons

| Reason           | Description                                                                                                                      |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| TARGETING\_MATCH | A targeting rule's conditions matched the evaluation context, and the rule's variant was returned.                               |
| SPLIT            | A targeting rule with a percentage rollout matched. The user fell within the rollout percentage and received the rule's variant. |
| DEFAULT          | No targeting rule matched the evaluation context. The flag's default variant was returned.                                       |
| DISABLED         | The flag is disabled. The default variant was returned regardless of targeting rules.                                            |
| CACHED           | The SDK returned a cached evaluation result.                                                                                     |
| ERROR            | Evaluation failed and the default value was returned.                                                                            |

## Error codes

When an evaluation error occurs, the method returns the default value you provided. The `*Details` methods include additional metadata about the error.

| Error code       | Description                                                                                                                                                         |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| TYPE\_MISMATCH   | The flag's variant type does not match the requested type. For example, calling getBooleanValue on a flag whose variant is a string. The default value is returned. |
| FLAG\_NOT\_FOUND | The specified flag key does not exist in the app. The default value is returned.                                                                                    |
| INVALID\_CONTEXT | The evaluation context contains unsupported values, such as objects or arrays in HTTP evaluation. The default value is returned.                                    |
| PARSE\_ERROR     | The SDK received an invalid evaluation response. The default value is returned.                                                                                     |
| GENERAL          | An unexpected error occurred during evaluation, such as a timeout or network failure. The default value is returned.                                                |

## Example

The following example inspects evaluation details returned by `getBooleanDetails`:

* [  JavaScript ](#tab-panel-8900)
* [  TypeScript ](#tab-panel-8901)

JavaScript

```
const details = await env.FLAGS.getBooleanDetails("my-feature", false, {  userId: "user-42",});
switch (details.reason) {  case "TARGETING_MATCH":    console.log(`Matched targeting rule, variant: ${details.variant}`);    break;  case "SPLIT":    console.log(`Included in rollout, variant: ${details.variant}`);    break;  case "DEFAULT":    console.log("No rule matched, using default variant");    break;  case "DISABLED":    console.log("Flag is disabled");    break;}
if (details.errorCode) {  console.error(`Evaluation error: ${details.errorCode}`);}
```

TypeScript

```
const details = await env.FLAGS.getBooleanDetails("my-feature", false, {  userId: "user-42",});
switch (details.reason) {  case "TARGETING_MATCH":    console.log(`Matched targeting rule, variant: ${details.variant}`);    break;  case "SPLIT":    console.log(`Included in rollout, variant: ${details.variant}`);    break;  case "DEFAULT":    console.log("No rule matched, using default variant");    break;  case "DISABLED":    console.log("Flag is disabled");    break;}
if (details.errorCode) {  console.error(`Evaluation error: ${details.errorCode}`);}
```

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/reference/evaluation-reasons/#page","headline":"Evaluation reasons and error codes · Cloudflare Flagship docs","description":"Flagship evaluation reason values and error codes returned by binding details methods and the OpenFeature SDK.","url":"https://developers.cloudflare.com/flagship/reference/evaluation-reasons/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/reference/evaluation-reasons/","name":"Evaluation reasons and error codes"}}]}
```

---

---
title: Limits
description: Platform limits for Flagship, including maximum apps per account, flags per app, condition nesting depth, and configuration size.
image: https://developers.cloudflare.com/dev-products-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/flagship/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Limits

Flagship enforces the following limits.

## Platform limits

| Feature                         | Limit     |
| ------------------------------- | --------- |
| Apps per account                | 10,000    |
| Flags per app                   | 5,000     |
| Flag, app, and variant keys     | 64 chars  |
| Condition attribute names       | 64 chars  |
| Condition string values         | 256 chars |
| Variant value size              | 10 KB     |
| Condition nesting depth         | 5 levels  |
| Flag description                | 512 chars |
| Flag configuration size per app | 25 MB     |

Note

The apps-per-account and flags-per-app limits are soft limits. If your use case requires higher limits, contact Cloudflare support.

## Notes

* Condition nesting depth counts from the top-level condition group. A flat list of conditions (no nesting) has a depth of 1.
* Flag keys, app names, condition set names, and variant keys can contain letters, numbers, hyphens, and underscores.
* All variants on a flag must use the same value type: boolean, string, number, or JSON.
* Flag configuration size refers to the total serialized size of all flags within a single app, including their variants and rules.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/flagship/reference/limits/#page","headline":"Limits · Cloudflare Flagship docs","description":"Platform limits for Flagship, including maximum apps per account, flags per app, condition nesting depth, and configuration size.","url":"https://developers.cloudflare.com/flagship/reference/limits/","inLanguage":"en","image":"https://developers.cloudflare.com/dev-products-preview.png","dateModified":"2026-06-24","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/flagship/","name":"Flagship"}},{"@type":"ListItem","position":3,"item":{"@id":"/flagship/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/flagship/reference/limits/","name":"Limits"}}]}
```
