Skip to main content
Connect-RPC / OpenAPI 3.1

API Explorer

Evaluate flags, resolve types, and stream real-time updates over the Connect protocol.

https://flaggr.devProduction
http://localhost:3000Local development

Bearer token required. Pass Authorization: Bearer flg_... on all requests. Public flags can be evaluated without auth. Mint a token at console → profile or project settings — Auth docs →

Evaluation Service

6 endpoints

Flag evaluation service — single flag, bulk, and type-specific resolution (boolean, string, number, object)

POST

BulkEvaluateFlags

Evaluate multiple flags

Request
flaggr.v1.BulkEvaluateFlagsRequest
flagKeysarray<string>Flag keys to evaluate (empty = all flags)
contextobjectEvaluation context containing user/request attributes
targetingKeystringPrimary identifier for targeting (e.g., user ID)
stringAttributesobjectString attributes
numberAttributesobjectNumber attributes
boolAttributesobjectBoolean attributes
timestampstringTimestamp when context was created
serviceIdstringService ID for scoping
environmentenumEnvironment enumeration
ENVIRONMENT_UNSPECIFIEDENVIRONMENT_DEVELOPMENTENVIRONMENT_STAGINGENVIRONMENT_PRODUCTION
Response 200
flaggr.v1.BulkEvaluateFlagsResponse
flagsobjectMap of flag key to evaluation result
flagKeystringFlag key that was evaluated
valueoneOfGeneric value that can hold different types
variantstringVariant name if applicable
reasonenumReason for the evaluation result
errorCodeenumError codes for failed evaluations
errorMessagestringError message if evaluation failed
metadataobjectAdditional metadata
evaluatedAtstringEvaluation timestamp
flagVersionint64Flag version used for this evaluation
totalintegerTotal flags evaluated
evaluatedAtstringEvaluation timestamp
Try it
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST

EvaluateFlag

Evaluate a single flag

Request
flaggr.v1.EvaluateFlagRequest
flagKeystringFlag key to evaluate
contextobjectEvaluation context containing user/request attributes
targetingKeystringPrimary identifier for targeting (e.g., user ID)
stringAttributesobjectString attributes
numberAttributesobjectNumber attributes
boolAttributesobjectBoolean attributes
timestampstringTimestamp when context was created
defaultValueoneOfGeneric value that can hold different types
boolValue*booleanbool value
jsonValue*stringSerialized JSON for object types
numberValue*doublenumber value
stringValue*stringstring value
serviceIdstringService ID for scoping
environmentenumEnvironment enumeration
ENVIRONMENT_UNSPECIFIEDENVIRONMENT_DEVELOPMENTENVIRONMENT_STAGINGENVIRONMENT_PRODUCTION
Response 200
flaggr.v1.EvaluateFlagResponse
flagKeystringFlag key that was evaluated
valueoneOfGeneric value that can hold different types
boolValue*booleanbool value
jsonValue*stringSerialized JSON for object types
numberValue*doublenumber value
stringValue*stringstring value
variantstringVariant name if applicable
reasonenumReason for the evaluation result
EVALUATION_REASON_UNSPECIFIEDEVALUATION_REASON_STATICEVALUATION_REASON_DEFAULTEVALUATION_REASON_TARGETING_MATCHEVALUATION_REASON_SPLITEVALUATION_REASON_CACHEDEVALUATION_REASON_FLAG_NOT_FOUNDEVALUATION_REASON_ERROREVALUATION_REASON_DISABLED
errorCodeenumError codes for failed evaluations
EVALUATION_ERROR_CODE_UNSPECIFIEDEVALUATION_ERROR_CODE_PROVIDER_NOT_READYEVALUATION_ERROR_CODE_FLAG_NOT_FOUNDEVALUATION_ERROR_CODE_PARSE_ERROREVALUATION_ERROR_CODE_TYPE_MISMATCHEVALUATION_ERROR_CODE_GENERALEVALUATION_ERROR_CODE_INVALID_CONTEXT
errorMessagestringError message if evaluation failed
metadataobjectAdditional metadata
evaluatedAtstringEvaluation timestamp
flagVersionint64Flag version used for this evaluation
Try it
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST

ResolveBoolean

Type-specific evaluation methods

Request
flaggr.v1.ResolveBooleanRequest
flagKeystringflag key
defaultValuebooleandefault value
contextobjectEvaluation context containing user/request attributes
targetingKeystringPrimary identifier for targeting (e.g., user ID)
stringAttributesobjectString attributes
numberAttributesobjectNumber attributes
boolAttributesobjectBoolean attributes
timestampstringTimestamp when context was created
serviceIdstringservice id
Response 200
flaggr.v1.ResolveBooleanResponse
valuebooleanvalue
variantstringvariant
reasonenumReason for the evaluation result
EVALUATION_REASON_UNSPECIFIEDEVALUATION_REASON_STATICEVALUATION_REASON_DEFAULTEVALUATION_REASON_TARGETING_MATCHEVALUATION_REASON_SPLITEVALUATION_REASON_CACHEDEVALUATION_REASON_FLAG_NOT_FOUNDEVALUATION_REASON_ERROREVALUATION_REASON_DISABLED
errorCodeenumError codes for failed evaluations
EVALUATION_ERROR_CODE_UNSPECIFIEDEVALUATION_ERROR_CODE_PROVIDER_NOT_READYEVALUATION_ERROR_CODE_FLAG_NOT_FOUNDEVALUATION_ERROR_CODE_PARSE_ERROREVALUATION_ERROR_CODE_TYPE_MISMATCHEVALUATION_ERROR_CODE_GENERALEVALUATION_ERROR_CODE_INVALID_CONTEXT
errorMessagestringerror message
metadataobjectmetadata
Try it
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST

ResolveNumber

Request
flaggr.v1.ResolveNumberRequest
flagKeystringflag key
defaultValuedoubledefault value
contextobjectEvaluation context containing user/request attributes
targetingKeystringPrimary identifier for targeting (e.g., user ID)
stringAttributesobjectString attributes
numberAttributesobjectNumber attributes
boolAttributesobjectBoolean attributes
timestampstringTimestamp when context was created
serviceIdstringservice id
Response 200
flaggr.v1.ResolveNumberResponse
valuedoublevalue
variantstringvariant
reasonenumReason for the evaluation result
EVALUATION_REASON_UNSPECIFIEDEVALUATION_REASON_STATICEVALUATION_REASON_DEFAULTEVALUATION_REASON_TARGETING_MATCHEVALUATION_REASON_SPLITEVALUATION_REASON_CACHEDEVALUATION_REASON_FLAG_NOT_FOUNDEVALUATION_REASON_ERROREVALUATION_REASON_DISABLED
errorCodeenumError codes for failed evaluations
EVALUATION_ERROR_CODE_UNSPECIFIEDEVALUATION_ERROR_CODE_PROVIDER_NOT_READYEVALUATION_ERROR_CODE_FLAG_NOT_FOUNDEVALUATION_ERROR_CODE_PARSE_ERROREVALUATION_ERROR_CODE_TYPE_MISMATCHEVALUATION_ERROR_CODE_GENERALEVALUATION_ERROR_CODE_INVALID_CONTEXT
errorMessagestringerror message
metadataobjectmetadata
Try it
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST

ResolveObject

Request
flaggr.v1.ResolveObjectRequest
flagKeystringflag key
defaultValuestringJSON string
contextobjectEvaluation context containing user/request attributes
targetingKeystringPrimary identifier for targeting (e.g., user ID)
stringAttributesobjectString attributes
numberAttributesobjectNumber attributes
boolAttributesobjectBoolean attributes
timestampstringTimestamp when context was created
serviceIdstringservice id
Response 200
flaggr.v1.ResolveObjectResponse
valuestringJSON string
variantstringvariant
reasonenumReason for the evaluation result
EVALUATION_REASON_UNSPECIFIEDEVALUATION_REASON_STATICEVALUATION_REASON_DEFAULTEVALUATION_REASON_TARGETING_MATCHEVALUATION_REASON_SPLITEVALUATION_REASON_CACHEDEVALUATION_REASON_FLAG_NOT_FOUNDEVALUATION_REASON_ERROREVALUATION_REASON_DISABLED
errorCodeenumError codes for failed evaluations
EVALUATION_ERROR_CODE_UNSPECIFIEDEVALUATION_ERROR_CODE_PROVIDER_NOT_READYEVALUATION_ERROR_CODE_FLAG_NOT_FOUNDEVALUATION_ERROR_CODE_PARSE_ERROREVALUATION_ERROR_CODE_TYPE_MISMATCHEVALUATION_ERROR_CODE_GENERALEVALUATION_ERROR_CODE_INVALID_CONTEXT
errorMessagestringerror message
metadataobjectmetadata
Try it
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
POST

ResolveString

Request
flaggr.v1.ResolveStringRequest
flagKeystringflag key
defaultValuestringdefault value
contextobjectEvaluation context containing user/request attributes
targetingKeystringPrimary identifier for targeting (e.g., user ID)
stringAttributesobjectString attributes
numberAttributesobjectNumber attributes
boolAttributesobjectBoolean attributes
timestampstringTimestamp when context was created
serviceIdstringservice id
Response 200
flaggr.v1.ResolveStringResponse
valuestringvalue
variantstringvariant
reasonenumReason for the evaluation result
EVALUATION_REASON_UNSPECIFIEDEVALUATION_REASON_STATICEVALUATION_REASON_DEFAULTEVALUATION_REASON_TARGETING_MATCHEVALUATION_REASON_SPLITEVALUATION_REASON_CACHEDEVALUATION_REASON_FLAG_NOT_FOUNDEVALUATION_REASON_ERROREVALUATION_REASON_DISABLED
errorCodeenumError codes for failed evaluations
EVALUATION_ERROR_CODE_UNSPECIFIEDEVALUATION_ERROR_CODE_PROVIDER_NOT_READYEVALUATION_ERROR_CODE_FLAG_NOT_FOUNDEVALUATION_ERROR_CODE_PARSE_ERROREVALUATION_ERROR_CODE_TYPE_MISMATCHEVALUATION_ERROR_CODE_GENERALEVALUATION_ERROR_CODE_INVALID_CONTEXT
errorMessagestringerror message
metadataobjectmetadata
Try it
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Flag Stream Service

1 endpoints

Real-time flag streaming — server-sent updates, bidirectional sync, and configuration fetch

STREAM

GetConfiguration

Live

Get current configuration (unary, for initial load)

Request
flaggr.v1.StreamFlagsRequest
serviceIdstringService ID to subscribe to
environmentenumEnvironment enumeration
ENVIRONMENT_UNSPECIFIEDENVIRONMENT_DEVELOPMENTENVIRONMENT_STAGINGENVIRONMENT_PRODUCTION
flagKeysarray<string>Specific flag keys to watch (empty = all flags)
lastKnownVersionstringLast known configuration version (for delta sync)
clientIdstringClient identifier for connection tracking
apiTokenstringAPI token for authentication
Response 200
flaggr.v1.ConfigurationSync
configurationobjectCollection of flags for bulk operations
flagsobjectMap of flag key to flag definition
versionstringConfiguration version
generatedAtstringWhen this configuration was generated
serviceIdstringService ID for scoped configurations
projectIdstringProject ID for scoped configurations
timestampstringTimestamp of sync
Try itStreaming — use SDK
Bearer
Request Body
1
2
3
4
5
6
7
8
9
10

REST API — Control Plane

33 endpoints

The management and evaluation surface at flaggr.dev/api — flag CRUD, batch evaluation, SSE streaming, bulk operations, and the public demo service that powers the landing-page grid.

Every endpoint shows generated cURL / JavaScript / Python / Go examples and a live Try it panel — paste a flg_ token (console → profile) to hit any endpoint, including mutations. Public demo endpoints need nothing at all.

Evaluation

5

Server-side flag evaluation — the same engine the SDKs hit. Public flags evaluate without auth.

POST

Evaluate a single flag

Public flags

Evaluates one flag against the supplied context — the primary server-side eval path. Returns the resolved value, reason, variant, and per-phase timing breakdown.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
  • Flags marked `isPublic` evaluate without any token — useful for client-side reads of deliberately public config.
  • Rate limits: 1,000/min per IP · 5,000/min per token · 10,000/min per service.
Request
curl -X POST 'https://flaggr.dev/api/flags/evaluate' \
  -H 'Content-Type: application/json' \
  -d '{ "flagKey": "checkout-v2", "serviceId": "web-app", "environment": "production", "defaultValue": false, "context": {  "targetingKey": "user-123",  "email": "alice@example.com",  "plan": "enterprise" }}'
Request body
{
  "flagKey": "checkout-v2",
  "serviceId": "web-app",
  "environment": "production",
  "defaultValue": false,
  "context": {
    "targetingKey": "user-123",
    "email": "alice@example.com",
    "plan": "enterprise"
  }
}
Response
{
  "flagKey": "checkout-v2",
  "value": true,
  "reason": "TARGETING_MATCH",
  "variant": "enabled",
  "_debug": {
    "timings": { "rateLimit": 2, "validation": 1, "cacheGet": 0.5, "evaluate": 3 },
    "cacheHit": false,
    "totalMs": 12
  }
}
JavaScript SDK
import { FlaggrProvider } from "@flaggr/sdk";

// SDKs evaluate locally against a hydrated snapshot — this endpoint is the
// server-side path for one-off checks and non-SDK clients.
Try it — live
POST
Request Body
POST

Bulk evaluate flags

Bearer token

Evaluates many flags in one request — the grouped-eval path SDKs use to hydrate or refresh. All flags share one context; per-flag results return in order.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
  • Normal cap: 100 flags per request. Public demo services may send up to 4,096.
  • Response times: warm batches of 4,096 flags measure ~110ms — the engine prefetches experiments once instead of per-flag.
Request
curl -X POST 'https://flaggr.dev/api/flags/evaluate/batch' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "serviceId": "web-app", "environment": "production", "flags": [  { "key": "checkout-v2", "defaultValue": false },  { "key": "new-onboarding", "defaultValue": false } ], "context": { "targetingKey": "user-123", "plan": "enterprise" }}'
Request body
{
  "serviceId": "web-app",
  "environment": "production",
  "flags": [
    { "key": "checkout-v2", "defaultValue": false },
    { "key": "new-onboarding", "defaultValue": false }
  ],
  "context": { "targetingKey": "user-123", "plan": "enterprise" }
}
Response
{
  "flags": [
    { "key": "checkout-v2", "value": true, "reason": "TARGETING_MATCH", "variant": "enabled" },
    { "key": "new-onboarding", "value": false, "reason": "DISABLED", "variant": null }
  ],
  "_meta": {
    "evaluationTimeMs": 4,
    "flagCount": 2,
    "timings": { "auth": 8, "storage": 12, "evaluate": 4, "total": 26 }
  }
}
Try it — live
POST
Request Body
GET

Query evaluation logs

Bearer token

Recent evaluation events — who evaluated what, when, and what they got. Powers the console's eval log views.

Request
curl -X GET 'https://flaggr.dev/api/evaluations' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "evaluations": [
    {
      "flagKey": "checkout-v2",
      "value": true,
      "reason": "TARGETING_MATCH",
      "evaluatedAt": "2026-09-24T03:11:46.470Z",
      "context": { "targetingKey": "user-123" }
    }
  ],
  "nextCursor": "eyJ0cyI6MTc5MDIxOTUwNjQ3MH0=",
  "hasMore": true
}
Try it — live
GET
GET

Evaluation volume stats

Bearer token

Aggregated evaluation counts and latency buckets over a window — used by the analytics dashboards and toggle-impact analysis.

Request
curl -X GET 'https://flaggr.dev/api/evaluations/stats' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "total": 142031,
  "perMinute": 98.6,
  "p50Ms": 4,
  "p95Ms": 18,
  "p99Ms": 41,
  "byFlag": [{ "key": "checkout-v2", "count": 51220 }]
}
Try it — live
GET
GET

Browse evaluation contexts

Bearer token

Recent evaluation contexts grouped by targetingKey — who evaluated, their attributes, and what each flag resolved to. `key` narrows to a single context's flag→value map. Backed by the in-memory eval ring (last ~1,000 evals on the instance).

Request
curl -X GET 'https://flaggr.dev/api/contexts' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "contexts": [
    {
      "targetingKey": "user-alice-1",
      "attributes": { "plan": "pro", "region": "au" },
      "evalCount": 4, "flagCount": 2,
      "flags": [{ "flagKey": "checkout-v2", "value": true, "reason": "TARGETING_MATCH" }]
    }
  ],
  "window": "recent"
}
Try it — live
GET

Flag Management

9

CRUD, toggles, version history, and post-toggle safety analysis for feature flags.

GET

List flags

Bearer token

Lists flags for a project with filtering, pagination, and sparse fieldsets. Supports both offset and cursor pagination; public demo services may be listed without a token.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
  • Public demo service lists emit a weak `ETag` over the result set — send it as `If-None-Match` to get `304 Not Modified` on unchanged revalidations.
  • `fields` whitelist: key, name, description, type, enabled, defaultValue, serviceId, environment, tags, variants, targeting, isPublic, createdAt, updatedAt.
Request
curl -X GET 'https://flaggr.dev/api/flags' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "flags": [
    {
      "key": "checkout-v2",
      "name": "Checkout v2",
      "type": "boolean",
      "enabled": true,
      "serviceId": "web-app",
      "environment": "production",
      "updatedAt": "2026-09-24T03:11:46.470Z"
    }
  ],
  "total": 42,
  "limit": 50,
  "offset": 0,
  "hasMore": false
}
Try it — live
GET
POST

Create a flag

Bearer token

Creates a flag in a service + environment. Publishes a `flag-update` event, writes a version snapshot, and logs an audit entry.

  • Session-authenticated mutations require the CSRF pair (cookie + `x-csrf-token` header). Bearer-token requests skip CSRF entirely — any write-scoped `flg_` token works here.
  • Duplicate keys in the same service+environment return 409.
Request
curl -X POST 'https://flaggr.dev/api/flags' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "key": "checkout-v2", "name": "Checkout v2", "description": "New checkout flow", "type": "boolean", "enabled": false, "defaultValue": false, "serviceId": "web-app", "environment": "production", "tags": ["checkout"], "variants": [], "targeting": [], "isPublic": false}'
Request body
{
  "key": "checkout-v2",
  "name": "Checkout v2",
  "description": "New checkout flow",
  "type": "boolean",
  "enabled": false,
  "defaultValue": false,
  "serviceId": "web-app",
  "environment": "production",
  "tags": ["checkout"],
  "variants": [],
  "targeting": [],
  "isPublic": false
}
Response
{
  "key": "checkout-v2",
  "name": "Checkout v2",
  "type": "boolean",
  "enabled": false,
  "serviceId": "web-app",
  "environment": "production",
  "createdAt": "2026-09-24T03:11:46.470Z",
  "updatedAt": "2026-09-24T03:11:46.470Z"
}
Try it — live
POST
Request Body
GET

Get a flag

Bearer token

Fetches one flag by key within a service and environment.

Request
curl -X GET 'https://flaggr.dev/api/flags/checkout-v2' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "key": "checkout-v2",
  "name": "Checkout v2",
  "type": "boolean",
  "enabled": true,
  "defaultValue": false,
  "variants": [],
  "targeting": [{ "name": "Enterprise", "conditions": [{ "attribute": "plan", "operator": "equals", "value": "enterprise" }], "value": true }],
  "updatedAt": "2026-09-24T03:11:46.470Z"
}
Try it — live
GET
PATCH

Update a flag

Bearer token

Partial update — enabled state, targeting, variants, metadata. Publishes a `flag-update` event and snapshots the previous version.

  • Session-authenticated mutations require the CSRF pair (cookie + `x-csrf-token` header). Bearer-token requests skip CSRF entirely — any write-scoped `flg_` token works here.
Request
curl -X PATCH 'https://flaggr.dev/api/flags/checkout-v2' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "enabled": true, "description": "Rolled out to enterprise", "targeting": [  { "name": "Enterprise", "conditions": [{ "attribute": "plan", "operator": "equals", "value": "enterprise" }], "value": true } ]}'
Request body
{
  "enabled": true,
  "description": "Rolled out to enterprise",
  "targeting": [
    { "name": "Enterprise", "conditions": [{ "attribute": "plan", "operator": "equals", "value": "enterprise" }], "value": true }
  ]
}
Response
{
  "key": "checkout-v2",
  "enabled": true,
  "updatedAt": "2026-09-24T03:15:02.118Z",
  "version": 7
}
Try it — live
PATCH
Request Body
DELETE

Delete a flag

Bearer token

Deletes a flag and publishes a `flag-deleted` event to all subscribers.

  • Session-authenticated mutations require the CSRF pair (cookie + `x-csrf-token` header). Bearer-token requests skip CSRF entirely — any write-scoped `flg_` token works here.
Request
curl -X DELETE 'https://flaggr.dev/api/flags/checkout-v2' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{ "success": true, "key": "checkout-v2" }
Try it — live
DELETE
POST

Toggle a flag

Bearer token

Flips `enabled` on or off — the hot path. Returns immediately after the write commits; versioning, audit, and fanout run deferred via `runAfterResponse`.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
  • Toggle accepts write-scoped tokens — no CSRF needed, unlike the session-auth management routes.
Request
curl -X POST 'https://flaggr.dev/api/flags/checkout-v2/toggle' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "serviceId": "web-app", "environment": "production", "enabled": true}'
Request body
{
  "serviceId": "web-app",
  "environment": "production",
  "enabled": true
}
Response
{
  "key": "checkout-v2",
  "enabled": true,
  "previousValue": false,
  "updatedAt": "2026-09-24T03:15:02.118Z"
}
Try it — live
POST
Request Body
GET

Post-toggle drift analysis

Bearer token

Symmetric before/after analysis around the last toggle — error-rate shift, p99 latency shift, and traffic ratio, classified healthy | warning | degraded.

Request
curl -X GET 'https://flaggr.dev/api/flags/checkout-v2/toggle-impact' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "flagKey": "checkout-v2",
  "healthStatus": "healthy",
  "before": { "errorRate": 0.012, "p99LatencyMs": 210, "evaluations": 8420 },
  "after": { "errorRate": 0.014, "p99LatencyMs": 224, "evaluations": 8391 },
  "delta": { "errorRateShift": 0.002, "p99LatencyShiftMs": 14, "trafficRatio": 0.99 },
  "advice": "No significant drift detected."
}
Try it — live
GET
GET

Flag evaluation time series

Bearer token

Per-flag evaluation volume and latency over time — the data behind the console's flag metrics charts.

Request
curl -X GET 'https://flaggr.dev/api/flags/checkout-v2/metrics' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "flagKey": "checkout-v2",
  "window": "1h",
  "interval": "5m",
  "series": [
    { "ts": "2026-09-24T03:00:00Z", "evaluations": 420, "errors": 3, "p95Ms": 18 }
  ]
}
Try it — live
GET
GET

Flag version history

Bearer token

Immutable version snapshots — every mutation writes one. Feed for the console's diff/rollback UI.

Request
curl -X GET 'https://flaggr.dev/api/flags/checkout-v2/history' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "versions": [
    {
      "version": 7,
      "changeType": "update",
      "changedBy": "user@example.com",
      "changeSummary": "Enabled for enterprise",
      "snapshot": { "enabled": true },
      "createdAt": "2026-09-24T03:15:02.118Z"
    }
  ]
}
Try it — live
GET

Triggers & Watching

6

Scoped trigger URLs for CI/CD flag actions, member flag-watching, and the audit-sourced notification feed.

POST

Create a flag trigger

Bearer token

Mint a scoped, revocable trigger URL for CI/CD — `POST` it (no auth headers; the token is the capability) to enable, disable, or toggle the flag. The raw token is returned exactly once — only its SHA-256 hash is stored.

  • Token shown once at creation — store it as a CI secret.
  • Trigger executions audit-log as `trigger:{name}` and bump `useCount`.
Request
curl -X POST 'https://flaggr.dev/api/flags/checkout-v2/triggers' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "serviceId": "web", "environment": "production", "action": "enable", "name": "deploy-complete"}'
Request body
{
  "serviceId": "web",
  "environment": "production",
  "action": "enable",
  "name": "deploy-complete"
}
Response
{
  "id": "trg-abc",
  "action": "enable",
  "token": "ftr_…",
  "url": "/api/triggers/ftr_…",
  "example": "curl -X POST https://flaggr.dev/api/triggers/ftr_…"
}
Try it — live
POST
Request Body
GET

List flag triggers

Bearer token

Active triggers for a flag — metadata only, never the raw token.

Request
curl -X GET 'https://flaggr.dev/api/flags/checkout-v2/triggers' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{ "triggers": [{ "id": "trg-abc", "name": "deploy-complete", "action": "enable", "useCount": 3, "lastUsedAt": "2026-09-24T11:33Z" }] }
Try it — live
GET
DELETE

Revoke a trigger

Bearer token

Immediately invalidates the trigger URL — the capability is gone.

Request
curl -X DELETE 'https://flaggr.dev/api/flags/checkout-v2/triggers/example-triggerId' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{ "revoked": true, "id": "trg-abc" }
Try it — live
DELETE
POST

Execute a trigger

No auth

The capability URL — `POST` with no auth headers. The token alone grants exactly one scoped action on one flag in one environment. Rate-limited to 30 executions/minute per token.

  • 404 for unknown AND revoked tokens — no oracle.
  • Same mutation path as the toggle route — version snapshot, audit, SSE fanout, cache invalidation.
  • Paste your trigger URL into the editable URL field to try it.
Request
curl -X POST 'https://flaggr.dev/api/triggers/example-token' \
Response
{ "flagKey": "checkout-v2", "action": "enable", "enabled": true, "executedAt": "2026-09-24T11:33Z" }
Try it — live
POST
POST

Watch a flag

Bearer token

Follow a flag — its mutations surface as unread items in the notifications bell (audit-sourced feed). Idempotent. `DELETE` unfollows, `GET` returns current watch state.

Request
curl -X POST 'https://flaggr.dev/api/flags/checkout-v2/watch' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "serviceId": "web", "environment": "production" }'
Request body
{ "serviceId": "web", "environment": "production" }
Response
{ "watching": true, "flagKey": "checkout-v2", "environment": "production" }
Try it — live
POST
Request Body
GET

Notification feed

Bearer token

Recent audit events on flags the caller watches, plus unread count. `POST` marks all watched-flag notifications as read.

Request
curl -X GET 'https://flaggr.dev/api/notifications' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "notifications": [{ "flagKey": "checkout-v2", "action": "flag.toggle", "actorEmail": "alice@x.io", "unread": true }],
  "unreadCount": 1, "watching": 3
}
Try it — live
GET

Bulk Operations

3

Batched create, update, and delete — one request, one storage round-trip per service/environment group.

POST

Bulk create flags

Bearer token

Creates many flags in one request — used by import flows and environment bootstrapping. Per-flag results with `succeeded`/`failed` counts.

  • Session-authenticated mutations require the CSRF pair (cookie + `x-csrf-token` header). Bearer-token requests skip CSRF entirely — any write-scoped `flg_` token works here.
  • Partial success returns 207 Multi-Status with per-flag errors.
Request
curl -X POST 'https://flaggr.dev/api/flags/bulk' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "flags": [  {   "key": "new-header",   "name": "New Header",   "type": "boolean",   "enabled": false,   "defaultValue": false,   "serviceId": "web-app",   "environment": "staging"  } ]}'
Request body
{
  "flags": [
    {
      "key": "new-header",
      "name": "New Header",
      "type": "boolean",
      "enabled": false,
      "defaultValue": false,
      "serviceId": "web-app",
      "environment": "staging"
    }
  ]
}
Response
{
  "success": true,
  "total": 1,
  "succeeded": 1,
  "failed": 0,
  "results": [{ "key": "new-header", "status": "success" }]
}
Try it — live
POST
Request Body
PATCH

Bulk update flags

Bearer token

Updates many flags atomically per service+environment — one SELECT + one UPDATE, then pub/sub fanout. This is the endpoint the pixel-grid demo writes through.

  • Session-authenticated mutations require the CSRF pair (cookie + `x-csrf-token` header). Bearer-token requests skip CSRF entirely — any write-scoped `flg_` token works here.
  • Fanout publishes before version/audit writes — SSE subscribers see the commit immediately, not after durability work.
  • Normal cap: 100 updates. Public demo services may send up to 4,096 (enabled-only).
Request
curl -X PATCH 'https://flaggr.dev/api/flags/bulk' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "flags": [  {   "key": "checkout-v2",   "serviceId": "web-app",   "environment": "production",   "updates": { "enabled": true }  },  {   "key": "new-onboarding",   "serviceId": "web-app",   "environment": "production",   "updates": { "enabled": false, "description": "Paused" }  } ]}'
Request body
{
  "flags": [
    {
      "key": "checkout-v2",
      "serviceId": "web-app",
      "environment": "production",
      "updates": { "enabled": true }
    },
    {
      "key": "new-onboarding",
      "serviceId": "web-app",
      "environment": "production",
      "updates": { "enabled": false, "description": "Paused" }
    }
  ]
}
Response
{
  "success": true,
  "total": 2,
  "succeeded": 2,
  "failed": 0,
  "results": [
    { "key": "checkout-v2", "status": "success", "flag": { "key": "checkout-v2", "enabled": true } }
  ]
}
Try it — live
PATCH
Request Body
DELETE

Bulk delete flags

Bearer token

Deletes many flags in one request with per-flag results and `flag-deleted` events.

  • Session-authenticated mutations require the CSRF pair (cookie + `x-csrf-token` header). Bearer-token requests skip CSRF entirely — any write-scoped `flg_` token works here.
Request
curl -X DELETE 'https://flaggr.dev/api/flags/bulk' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "flags": [  { "key": "old-experiment", "serviceId": "web-app", "environment": "staging" } ]}'
Request body
{
  "flags": [
    { "key": "old-experiment", "serviceId": "web-app", "environment": "staging" }
  ]
}
Response
{ "success": true, "total": 1, "succeeded": 1, "failed": 0, "results": [{ "key": "old-experiment", "status": "success" }] }
Try it — live
DELETE
Request Body

Streaming

2

Server-Sent Events feeds for real-time flag propagation — the transport SDKs use for push updates.

GET · SSE

Flag update stream (SSE)

Bearer tokenLive

Server-Sent Events feed of flag mutations for a service — `connected` on open, then one `flag-update` per mutation carrying the full flag object, and periodic `ping` keepalives.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
  • EventSource in browsers can't set headers — use the `eventsource` npm package, or a public demo service (no token needed).
  • Backed by Redis pub/sub in multi-instance deploys, in-process bus otherwise.
Request
curl -X GET 'https://flaggr.dev/api/flags/stream' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Accept: text/event-stream' \
  -N \
Response (stream)
data: {"type":"connected","serviceId":"web-app","timestamp":1790219485135,"realTimeMethod":"redis-pubsub"}

data: {"type":"flag-update","flagKey":"checkout-v2","serviceId":"web-app","eventType":"UPDATED","timestamp":"2026-09-24T03:15:02.118Z","flag":{"key":"checkout-v2","enabled":true}}

data: {"type":"ping","timestamp":1790219545000}
JavaScript SDK
import { FlaggrProvider } from "@flaggr/sdk";

const provider = new FlaggrProvider({
  baseUrl: "https://flaggr.dev",
  serviceId: "web-app",
  environment: "production",
  apiKey: "flg_…",
  updateMode: "stream", // SSE push — this endpoint under the hood
});
Try it — liveSSE — first 4s of events
GET
GET · SSE

Connect config stream (SSE)

Bearer tokenLive

The Connect-protocol stream SDKs use — emits a full configuration snapshot on connect, then incremental flag events. Pairs with `/api/connect/evaluate`.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
Request
curl -X GET 'https://flaggr.dev/api/connect/stream' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Accept: text/event-stream' \
  -N \
Response (stream)
data: {"type":"configuration","flags":[{...}],"configVersion":"v1790219485135"}

data: {"type":"flag-update","flagKey":"checkout-v2","eventType":"UPDATED"}
Try it — liveSSE — first 4s of events
GET

OpenFeature (OFREP)

3

Vendor-neutral OpenFeature Remote Evaluation Protocol — drop-in compatible with OFREP SDKs.

POST

OFREP single evaluation

Bearer token

OpenFeature Remote Evaluation Protocol — evaluate one flag for a context. Compatible with any OFREP-compliant SDK.

  • Pass `Authorization: Bearer flg_…` — tokens carry read or write scopes.
  • Requires `serviceId`/`environment` via headers or token claims.
Request
curl -X POST 'https://flaggr.dev/api/ofrep/v1/evaluate/flags/checkout-v2' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "context": { "targetingKey": "user-123", "plan": "enterprise" }}'
Request body
{
  "context": { "targetingKey": "user-123", "plan": "enterprise" }
}
Response
{
  "key": "checkout-v2",
  "value": true,
  "reason": "TARGETING_MATCH",
  "variant": "enabled",
  "metadata": { "flagSetId": "web-app" }
}
Try it — live
POST
Request Body
POST

OFREP bulk evaluation

Bearer token

Evaluates all flags in the flagset for one context — the OFREP hydration call.

Request
curl -X POST 'https://flaggr.dev/api/ofrep/v1/evaluate/flags' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "context": { "targetingKey": "user-123", "plan": "enterprise" }}'
Request body
{
  "context": { "targetingKey": "user-123", "plan": "enterprise" }
}
Response
{
  "flags": [
    { "key": "checkout-v2", "value": true, "reason": "TARGETING_MATCH", "variant": "enabled" }
  ],
  "metadata": { "flagSetId": "web-app" }
}
Try it — live
POST
Request Body
GET

OFREP metadata

Bearer token

Provider metadata for OFREP client negotiation — name, capabilities, flagset.

Request
curl -X GET 'https://flaggr.dev/api/ofrep/v1/metadata' \
  -H 'Authorization: Bearer flg_YOUR_TOKEN' \
Response
{
  "name": "Flaggr",
  "capabilities": ["flag-evaluation", "bulk-evaluation"],
  "metadata": { "version": "0.2.0" }
}
Try it — live
GET

Public Demo Service

4

The pixel-grid service (4,096 flags powering the landing-page demo) is addressable without a token — the only public-mutable surface.

GET

List the pixel grid

Public demo

The grid's bootstrap + poll read — the standard list endpoint pointed at the public demo service, with sparse fieldsets and conditional-request support.

  • No token required — `pixel-grid` is the only allowlisted public demo service.
  • Responses carry `ETag`; send `If-None-Match` to get `304 Not Modified` when the grid hasn't changed (~15ms, 0 bytes).
  • Try it below — this endpoint is live right now.
Request
curl -X GET 'https://flaggr.dev/api/flags?serviceId=pixel-grid&environment=development&limit=4096&fields=key,enabled' \
Response
{
  "flags": [
    { "key": "px-0", "enabled": false },
    { "key": "px-1", "enabled": true }
  ],
  "total": 4096,
  "limit": 4096,
  "offset": 0,
  "hasMore": false
}
Try it — liveno token needed
GET
POST

Evaluate the whole grid

Public demo

The grid's batch mode — all 4,096 cells evaluated through the real grouped-eval path in one request. The 100-flag cap relaxes to 4,096 for demo services.

  • The demo sends all 4,096 keys — ~175KB request, ~210KB response, ~110ms warm.
Request
curl -X POST 'https://flaggr.dev/api/flags/evaluate/batch' \
  -H 'Content-Type: application/json' \
  -d '{ "serviceId": "pixel-grid", "environment": "development", "flags": [  { "key": "px-0", "defaultValue": false },  { "key": "px-1", "defaultValue": false } ]}'
Request body
{
  "serviceId": "pixel-grid",
  "environment": "development",
  "flags": [
    { "key": "px-0", "defaultValue": false },
    { "key": "px-1", "defaultValue": false }
  ]
}
Response
{
  "flags": [
    { "key": "px-0", "value": false, "reason": "STATIC", "variant": null },
    { "key": "px-1", "value": true, "reason": "STATIC", "variant": "enabled" }
  ],
  "_meta": { "evaluationTimeMs": 89, "flagCount": 4096 }
}
Try it — liveno token needed
POST
Request Body
GET · SSE

Stream grid updates

Public demoLive

The real SSE feed for the demo service — a bulk pattern apply arrives as a burst of per-flag `flag-update` events.

  • Anonymous-friendly — the landing page's `EventSource` needs no token against this service.
Request
curl -X GET 'https://flaggr.dev/api/flags/stream?serviceId=pixel-grid&environment=development' \
  -H 'Accept: text/event-stream' \
  -N \
Response (stream)
data: {"type":"connected","serviceId":"pixel-grid","realTimeMethod":"redis-pubsub"}

data: {"type":"flag-update","flagKey":"px-512","serviceId":"pixel-grid","flag":{"key":"px-512","enabled":true}}
Try it — liveSSE — first 4s of eventsno token needed
GET
PATCH

Write to the grid

Public demo

Anonymous writes, restricted to the demo service: only `updates.enabled` applies, one write per IP per 2s, attributed to a `public-demo` actor in the audit log.

  • The demo client diffs patterns and sends only changed cells — sparse patterns are ~1–2K updates, not 4,096.
  • Any non-demo serviceId in the request reverts to full CSRF + write-token requirements.
Request
curl -X PATCH 'https://flaggr.dev/api/flags/bulk?summary=true' \
  -H 'Content-Type: application/json' \
  -d '{ "flags": [  { "key": "px-0", "serviceId": "pixel-grid", "environment": "development", "updates": { "enabled": true } },  { "key": "px-1", "serviceId": "pixel-grid", "environment": "development", "updates": { "enabled": false } } ]}'
Request body
{
  "flags": [
    { "key": "px-0", "serviceId": "pixel-grid", "environment": "development", "updates": { "enabled": true } },
    { "key": "px-1", "serviceId": "pixel-grid", "environment": "development", "updates": { "enabled": false } }
  ]
}
Response
{ "success": true, "total": 2, "succeeded": 2, "failed": 0 }
Try it — liveno token needed
PATCH
Request Body

Health

1

Liveness and dependency checks for the control plane.

GET

Application health

No auth

Liveness + dependency probe — reports storage, cache, and pub/sub connectivity. Used by uptime checks and deploy verification.

Request
curl -X GET 'https://flaggr.dev/api/health' \
Response
{
  "status": "ok",
  "timestamp": "2026-09-24T03:15:02.118Z",
  "checks": {
    "database": "ok",
    "cache": "ok",
    "pubsub": "redis-pubsub"
  }
}
Try it — live
GET

Generated from protobuf definitions using protoc-gen-connect-openapi · Protocol docs