Skip to main content

Complete reference for all Flaggr REST API endpoints — flags, evaluation, projects, services, tokens, audit, and webhooks

Last updated October 6, 2026

REST API Reference

Base URL: https://flaggr.dev (or your self-hosted instance).

All endpoints accept and return application/json. State-changing requests (POST, PATCH, DELETE) require a CSRF token in the X-CSRF-Token header.

Authentication

Bearer Token

Authorization: Bearer fgr_your_token

Firebase session cookies are sent automatically by the dashboard.

Get CSRF Token

GET /api/csrf-token
{ "token": "abc123", "headerName": "x-csrf-token" }

Flag Evaluation

Evaluate a Single Flag

POST /api/flags/evaluate

Evaluates a flag against the provided context. This is the primary evaluation endpoint.

Request:

{
  "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
  }
}

Auth: API token (read) OR session. Public flags can be evaluated without auth.

Rate limits: 1,000/min (IP) · 5,000/min (token) · 10,000/min (service)

Multi-Language Examples

curl -s -X POST https://flaggr.dev/api/flags/evaluate \
  -H "Authorization: Bearer fgr_abc123xxxxxxxxxxxx" \
  -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"
    }
  }' | jq

Bulk Evaluate

POST /api/flags/evaluate/batch

Evaluates multiple flags in a single request. Use this to reduce round-trips when your application needs several flags at once.

Request:

{
  "serviceId": "web-app",
  "environment": "production",
  "flags": [
    { "flagKey": "checkout-v2", "defaultValue": false },
    { "flagKey": "dark-mode", "defaultValue": false },
    { "flagKey": "new-pricing", "defaultValue": "off" }
  ],
  "context": {
    "targetingKey": "user-123",
    "plan": "enterprise"
  }
}

Response:

{
  "results": [
    { "flagKey": "checkout-v2", "value": true, "reason": "TARGETING_MATCH", "variant": "enabled" },
    { "flagKey": "dark-mode", "value": false, "reason": "DEFAULT" },
    { "flagKey": "new-pricing", "value": "tier-b", "reason": "VARIANT", "variant": "tier-b" }
  ]
}

Multi-Language Examples

curl -s -X POST https://flaggr.dev/api/flags/evaluate/batch \
  -H "Authorization: Bearer fgr_abc123xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "web-app",
    "environment": "production",
    "flags": [
      { "flagKey": "checkout-v2", "defaultValue": false },
      { "flagKey": "dark-mode", "defaultValue": false },
      { "flagKey": "new-pricing", "defaultValue": "off" }
    ],
    "context": {
      "targetingKey": "user-123",
      "plan": "enterprise"
    }
  }' | jq

Evaluation Logs

GET /api/evaluations?flagKey=checkout-v2&serviceId=web-app&limit=100&since=2025-01-01

Returns recent evaluation events for debugging.

DELETE /api/evaluations?flagKey=checkout-v2

Clears evaluation logs.


Public Demo Service

The pixel-grid service (4,096 boolean flags — a 64×64 grid where flag px-N is cell N) is a designated public demo service. The standard core endpoints below work unauthenticated against it — no token required. This is what powers the landing-page demo; it uses no special transport.

List the grid

GET /api/flags?serviceId=pixel-grid&environment=development&limit=4096

When serviceId is a public demo service, projectId may be omitted and the page-size cap relaxes to 4,096 (the whole grid in one call). For every other service, projectId and a read-scoped token are still required.

Sparse fieldsets — pass ?fields=key,enabled to project each flag to just the named fields (whitelist: key, name, description, type, enabled, defaultValue, serviceId, environment, tags, variants, targeting, isPublic, createdAt, updatedAt). For the full grid this cuts the response from ~2.3MB of flag documents to ~140KB. Works on authenticated lists too.

Conditional requests — public demo list responses carry a weak ETag over the result set. Send it back as If-None-Match; when nothing changed the response is 304 Not Modified with an empty body — the poll path in the demo does this so unchanged 6s ticks cost a roundtrip, not a download.

Evaluate the grid

POST /api/flags/evaluate/batch
{
  "serviceId": "pixel-grid",
  "environment": "development",
  "flags": [{ "key": "px-0", "defaultValue": false }, "..."]
}

Public demo services may batch up to 4,096 flags per request (the normal cap is 100) and skip token auth. All flags in the service are also isPublic, so POST /api/flags/evaluate works flag-by-flag too.

Stream updates

GET /api/flags/stream?serviceId=pixel-grid&environment=development

The standard SSE stream, open without a token for demo services. Each message is a data: JSON payload — type: "connected" on open, then type: "flag-update" per mutated flag with the full flag object included (flag.enabled, flag.updatedAt, …).

Write to the grid

PATCH /api/flags/bulk
{
  "flags": [
    {
      "key": "px-0",
      "serviceId": "pixel-grid",
      "environment": "development",
      "updates": { "enabled": true }
    }
  ]
}

When every serviceId in the request is a public demo service, bulk updates run unauthenticated — the demo grid is intentionally shared and mutable. Public writes are constrained:

  • Only updates.enabled is applied; all other fields are ignored.
  • Up to 4,096 flag updates per request (normal cap is 100).
  • One write per IP per 2 seconds.
  • Writes are attributed to a public-demo actor in the audit log.

Summary responses — PATCH /api/flags/bulk?summary=true returns only {success,total,succeeded,failed} instead of the per-flag result array (~50B vs ~2.6MB for a full-grid write). Works on authenticated calls too.

Any non-demo service in the same request reverts to the normal CSRF + write-token requirements — public access never crosses service boundaries.


Flag Management

List Flags

GET /api/flags?projectId=proj-1&serviceId=web-app&environment=production

Query parameters:

ParameterTypeDescription
projectIdstringRequired. Project ID
serviceIdstringFilter by service
environmentstringdevelopment, staging, or production
limitnumberMax 100, default 50
offsetnumberOffset-based pagination
cursorstringCursor-based pagination
cursor_directionstringnext or prev
searchstringSearch flag keys and names
tagsstringComma-separated tag filter
enabledbooleanFilter by enabled state
typestringboolean, string, number, or object

Response:

{
  "flags": [...],
  "total": 42,
  "limit": 50,
  "offset": 0,
  "hasMore": false,
  "nextCursor": null,
  "prevCursor": null
}

Multi-Language Examples

curl -s "https://flaggr.dev/api/flags?projectId=proj-1&serviceId=web-app&environment=production&limit=10" \
  -H "Authorization: Bearer fgr_abc123xxxxxxxxxxxx" | jq

Create Flag

POST /api/flags
{
  "key": "checkout-v2",
  "name": "Checkout V2",
  "description": "New checkout flow",
  "type": "boolean",
  "enabled": false,
  "defaultValue": false,
  "serviceId": "web-app",
  "environment": "production",
  "tags": ["checkout", "experiment"],
  "variants": [
    { "name": "control", "value": false, "weight": 50 },
    { "name": "treatment", "value": true, "weight": 50 }
  ],
  "targeting": [],
  "isPublic": false
}

Returns 201 with the created flag. Triggers flag.created event (Pub/Sub + webhooks), saves version snapshot, and writes audit log.

Multi-Language Examples

curl -s -X POST https://flaggr.dev/api/flags \
  -H "Authorization: Bearer fgr_abc123xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: $CSRF_TOKEN" \
  -d '{
    "key": "checkout-v2",
    "name": "Checkout V2",
    "description": "New checkout flow",
    "type": "boolean",
    "enabled": false,
    "defaultValue": false,
    "serviceId": "web-app",
    "environment": "production",
    "tags": ["checkout", "experiment"],
    "variants": [
      { "name": "control", "value": false, "weight": 50 },
      { "name": "treatment", "value": true, "weight": 50 }
    ],
    "targeting": [],
    "isPublic": false
  }' | jq

Get Flag

GET /api/flags/{key}?serviceId=web-app&environment=production

Update Flag

PATCH /api/flags/{key}?serviceId=web-app&environment=production

Send a partial update — only include fields you want to change:

{
  "enabled": true,
  "targeting": [
    {
      "id": "beta-users",
      "conditions": [
        { "property": "betaUser", "operator": "equals", "value": true }
      ],
      "value": true
    }
  ]
}

Delete Flag

DELETE /api/flags/{key}?serviceId=web-app&environment=production

Toggle Flag

POST /api/flags/{key}/toggle?serviceId=web-app&environment=production

Flips the enabled state (or explicitly sets it when passing {"enabled": boolean} in the JSON body). Broadcasts real-time updates over SSE, records a version snapshot and audit log entry, and purges Redis cache keys asynchronously via serverless durability lifecycles.

Post-Toggle Safety & Drift Analysis

GET /api/flags/{key}/toggle-impact?serviceId=web-app&environment=production&range=24h&windowMinutes=30

Evaluates post-toggle safety, health, and performance drift by comparing metrics before and after the latest toggle event.

Query parameters:

ParameterRequiredDescription
serviceIdYesService identifier
environmentNoEnvironment filter (e.g. production, staging, development)
rangeNoTime range for evaluation discovery: 1h, 24h, 7d, 30d (default 24h)
windowMinutesNoComparison window duration before/after toggle (e.g. 15, 30, 60)

Response:

{
  "flagKey": "checkout-v2",
  "serviceId": "web-app",
  "environment": "production",
  "range": "24h",
  "impact": {
    "hasRecentToggle": true,
    "latestToggle": {
      "id": "audit-f9e4a8b2",
      "timestamp": "2026-09-12T08:00:00.000Z",
      "timestampMs": 1789200000000,
      "actor": "release-engineer@flaggr.dev",
      "transition": { "from": false, "to": true },
      "environment": "production",
      "durationMs": 42
    },
    "healthStatus": "healthy",
    "windowMinutes": 30,
    "before": {
      "evaluations": 1200,
      "errors": 2,
      "errorRate": 0.0017,
      "avgLatencyMs": 1.5,
      "p99LatencyMs": 4.2
    },
    "after": {
      "evaluations": 1250,
      "errors": 1,
      "errorRate": 0.0008,
      "avgLatencyMs": 1.48,
      "p99LatencyMs": 4.15
    },
    "delta": {
      "errorRateDelta": -0.0009,
      "latencyP99DeltaMs": -0.05,
      "evaluationsRatio": 1.04
    },
    "recommendation": "Healthy: Post-toggle metrics are stable with no significant error or latency regression."
  },
  "recentToggles": [
    {
      "id": "audit-f9e4a8b2",
      "timestamp": "2026-09-12T08:00:00.000Z",
      "timestampMs": 1789200000000,
      "actor": "release-engineer@flaggr.dev",
      "transition": { "from": false, "to": true },
      "environment": "production",
      "durationMs": 42
    }
  ]
}

Flag Evaluation Metrics & Time Series

GET /api/flags/{key}/metrics?serviceId=web-app&environment=production&range=24h

Returns comprehensive evaluation metrics, real-time rates, value and reason breakdowns, time-series data, and correlated toggle impact analysis.

Query parameters:

ParameterRequiredDescription
serviceIdYesService identifier
environmentNoEnvironment filter
rangeNoTime range: 1h, 24h, 7d, 30d (default 24h)

Response:

{
  "flagKey": "checkout-v2",
  "serviceId": "web-app",
  "environment": "production",
  "source": "memory",
  "range": {
    "start": 1789113600000,
    "end": 1789200000000,
    "rangeLabel": "24h",
    "minutes": 1440
  },
  "summary": {
    "totalEvaluations": 48500,
    "totalErrors": 24,
    "errorRate": 0.0005,
    "avgLatencyMs": 1.42,
    "p50LatencyMs": 1.1,
    "p95LatencyMs": 3.8,
    "p99LatencyMs": 6.2,
    "evaluationsPerMinute": 33.68,
    "evaluationsPerSecond": 0.56
  },
  "realtime": {
    "evaluationsPerSecond": 1.2,
    "evaluationsPerMinute": 72,
    "evaluationsLastMinute": 72,
    "evaluationsLast5Min": 340,
    "errorRateLastMinute": 0,
    "trend": "stable",
    "lastEvaluatedAt": "2026-09-12T08:15:00.000Z",
    "topReason": "TARGETING_MATCH"
  },
  "toggleImpact": { ... },
  "recentToggles": [ ... ],
  "reasonBreakdown": {
    "TARGETING_MATCH": 38200,
    "DEFAULT_VALUE": 10276,
    "ERROR": 24
  },
  "valueBreakdown": {
    "true": 38200,
    "false": 10300
  },
  "timeSeries": [
    {
      "timestamp": 1789113600000,
      "evaluations": 2040,
      "errors": 1,
      "avgLatencyMs": 1.38,
      "p50LatencyMs": 1.05,
      "p95LatencyMs": 3.5,
      "p99LatencyMs": 5.9
    }
  ]
}

Automated Guardrail Circuit Breaking & Rollback

POST /api/flags/{key}/auto-rollback
GET /api/flags/{key}/auto-rollback?serviceId=web-app&environment=production

Evaluates post-toggle safety drift and automatically reverts the feature flag to its previous version snapshot if health metrics are degraded. Also supports dry-run preview mode.

Request body (or query parameters):

FieldTypeDescription
serviceIdstringService identifier (required)
environmentstringTarget environment (default: production)
dryRunbooleanIf true, returns what action would be taken without mutating flag state
maxErrorRateDeltanumberMaximum allowed error rate increase before tripping (default: 0.02 for +2%)
maxLatencyDeltaMsnumberMaximum allowed P99 latency increase in ms (default: 200)
windowMinutesnumberPre/post toggle evaluation window in minutes

Response:

{
  "flagKey": "checkout-v2",
  "serviceId": "web-app",
  "environment": "production",
  "actionTaken": "rolled_back",
  "reason": "Rollback completed: Guardrails tripped due to error rate surge +5.00%. Flag reverted to version 2.",
  "tripped": true,
  "targetVersionNumber": 2,
  "alertNotifiedChannels": ["ch-slack-prod", "ch-pagerduty"]
}

Project Stale Flags & Technical Debt Analysis

GET /api/projects/{id}/stale-flags

Scans all flags in a project to discover candidates for codebase cleanup, archiving, or deletion based on evaluation inactivity and 100% rollout duration.

Response:

{
  "total": 5,
  "staleCount": 2,
  "inactiveCount": 1,
  "launchedCount": 1,
  "potentialTechDebtFlags": 3,
  "reports": [
    {
      "flagKey": "legacy-auth",
      "serviceId": "svc-auth",
      "environment": "production",
      "status": "stale",
      "category": "stale_rolled_out",
      "daysInactive": 0,
      "daysSinceLastMutation": 45,
      "rolloutPercentage": 100,
      "stalenessScore": 90,
      "recommendation": "100% rolled out for 45 days. Candidate for permanent code migration.",
      "codeRemovalAdvice": "Replace flag('legacy-auth') check with true branch; delete fallback code."
    }
  ]
}

Organization Alert Channels

GET /api/orgs/{orgId}/alert-channels
POST /api/orgs/{orgId}/alert-channels
DELETE /api/orgs/{orgId}/alert-channels/{channelId}
POST /api/orgs/{orgId}/alert-channels/{channelId}/test

Manage organization-wide alert destinations (Slack, Discord, PagerDuty, Email, Webhook) automatically inherited by all projects in the organization.

SDK Ingest & Telemetry Analytics

POST /api/analytics/sdk-telemetry
GET /api/analytics/sdk-telemetry?serviceId=web-app&environment=production&range=24h

Ingests batched client-side telemetry (evaluations, Core Web Vitals, and errors) and provides aggregated analytics reports correlated with active feature flags.

Ingest SDK Telemetry (POST)

Request Body:

{
  "serviceId": "web-app",
  "environment": "production",
  "summaries": [
    {
      "flagKey": "checkout-v2",
      "variant": "enabled",
      "evaluations": 1420,
      "cacheHits": 1395,
      "cacheMisses": 25,
      "avgLatencyMs": 0.12
    }
  ],
  "webVitals": [
    {
      "name": "LCP",
      "value": 1420.5,
      "rating": "good",
      "activeFlags": { "checkout-v2": "enabled" },
      "timestamp": 1718000000000
    }
  ],
  "errors": [
    {
      "message": "Payment gateway timeout",
      "stack": "Error: Payment gateway timeout\n    at submitPayment (checkout.js:142)",
      "activeFlags": { "checkout-v2": "enabled" },
      "timestamp": 1718000005000
    }
  ],
  "diagnostics": {
    "totalEvaluations": 1420,
    "cacheHits": 1395,
    "cacheHitRatio": 0.982,
    "trackedFlagsCount": 1
  }
}

Response (200 OK):

{
  "success": true,
  "processed": {
    "evaluations": 1420,
    "webVitals": 1,
    "errors": 1
  }
}

Query Aggregated Telemetry Report (GET)

Query Parameters:

  • serviceId (optional): Filter by service ID.
  • environment (optional): Filter by environment.
  • flagKey (optional): Filter by specific flag key.
  • range (optional): Time range (1h, 6h, 24h, 7d, default: 24h).

Response (200 OK):

{
  "range": "24h",
  "totalEvaluations": 45200,
  "cacheHitRatio": 0.985,
  "evaluationSummaries": [
    {
      "flagKey": "checkout-v2",
      "evaluations": 25400,
      "cacheHits": 25100,
      "cacheMisses": 300,
      "avgLatencyMs": 0.14
    }
  ],
  "webVitals": [
    {
      "metric": "LCP",
      "count": 3120,
      "p75": 1640.2,
      "ratings": { "good": 2800, "needs-improvement": 280, "poor": 40 }
    }
  ],
  "topErrors": [
    {
      "message": "Payment gateway timeout",
      "count": 4,
      "firstSeen": "2026-09-12T10:15:00.000Z",
      "lastSeen": "2026-09-12T11:45:00.000Z",
      "correlatedFlags": ["checkout-v2"]
    }
  ]
}

Flag Version History

GET /api/flags/{key}/history?serviceId=web-app&limit=20&offset=0
{
  "versions": [...],
  "total": 15,
  "hasMore": false
}

Rollback to Version

POST /api/flags/{key}/rollback/{version}

Restores the flag to a previous version snapshot.


Bulk Operations

All bulk endpoints accept arrays of flag operations and return per-item results.

Bulk Create

POST /api/flags/bulk
{
  "flags": [
    { "key": "flag-a", "name": "Flag A", "type": "boolean", "serviceId": "web-app", "defaultValue": false },
    { "key": "flag-b", "name": "Flag B", "type": "string", "serviceId": "web-app", "defaultValue": "off" }
  ]
}

Bulk Update

PATCH /api/flags/bulk
{
  "flags": [
    { "key": "flag-a", "serviceId": "web-app", "environment": "production", "updates": { "enabled": true } },
    { "key": "flag-b", "serviceId": "web-app", "environment": "production", "updates": { "enabled": false } }
  ]
}

Bulk Delete

DELETE /api/flags/bulk
{
  "flags": [
    { "key": "flag-a", "serviceId": "web-app", "environment": "production" },
    { "key": "flag-b", "serviceId": "web-app", "environment": "production" }
  ]
}

Response (all bulk):

{
  "success": true,
  "total": 2,
  "succeeded": 2,
  "failed": 0,
  "results": [
    { "key": "flag-a", "status": "success", "flag": {...} },
    { "key": "flag-b", "status": "success", "flag": {...} }
  ]
}

Status codes: 201 (all succeed on create), 200 (all succeed on update/delete), 207 (mixed results).


Export & Import

Export Flags

GET /api/flags/export?projectId=proj-1&serviceId=web-app&format=json&includeDisabled=true

Returns a downloadable JSON file:

{
  "version": "1.0",
  "exportedAt": "2025-07-20T10:00:00Z",
  "projectId": "proj-1",
  "flagCount": 42,
  "flags": [...]
}

Import Flags

POST /api/flags/import

Upload an exported JSON file to restore flags.


Projects

List Projects

GET /api/projects

Returns all projects the authenticated user has access to, including their role.

Create Project

POST /api/projects
{
  "name": "My Project",
  "description": "Feature flags for the platform",
  "slug": "my-project",
  "tags": ["platform"]
}

The creator is automatically assigned the owner role.

Get Project

GET /api/projects/{id}

Get Project by Slug

GET /api/projects/by-slug/{slug}

Update Project

PATCH /api/projects/{id}

Requires manage_settings permission. Only owners can change slugs.

Delete Project

DELETE /api/projects/{id}

Requires delete_project permission. Cascade-deletes all resources.


Services

List Services

GET /api/services?projectId=proj-1&limit=50&search=web

Create Service

POST /api/services
{
  "projectId": "proj-1",
  "name": "Web App",
  "description": "Frontend web application",
  "tags": ["frontend"]
}

Get / Update / Delete Service

GET    /api/services/{id}
PATCH  /api/services/{id}
DELETE /api/services/{id}
GET    /api/services/by-slug/{slug}

Team Members

List Members

GET /api/projects/{id}/members

Add Member

POST /api/projects/{id}/members
{ "userId": "user-456", "role": "member" }

Roles: owner, admin, member, viewer.

Update / Remove Member

PATCH  /api/projects/{id}/members/{memberId}
DELETE /api/projects/{id}/members/{memberId}

Invitations

List Invitations

GET /api/projects/{id}/invitations

Create Invitation

POST /api/projects/{id}/invitations
{ "email": "bob@example.com", "role": "member" }

Invitations expire after 7 days. Cannot invite as owner.


API Tokens

List Project Tokens

GET /api/projects/{id}/tokens

Create Opaque Token

POST /api/projects/{id}/tokens
{
  "name": "CI Read Token",
  "permissions": { "read": true, "write": false, "delete": false },
  "expiresAt": "2026-12-31T00:00:00Z"
}

The plain token value is only returned on creation:

{
  "token": { "id": "...", "name": "CI Read Token", ... },
  "value": "fgr_abc123..."
}

Multi-Language Examples

curl -s -X POST https://flaggr.dev/api/projects/proj-1/tokens \
  -H "Authorization: Bearer fgr_abc123xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: $CSRF_TOKEN" \
  -d '{
    "name": "CI Read Token",
    "permissions": { "read": true, "write": false, "delete": false },
    "expiresAt": "2026-12-31T00:00:00Z"
  }' | jq
 
# Save the token value — it is only shown once
# .value => "fgr_abc123..."

Create JWT Token

POST /api/projects/{id}/tokens
{
  "name": "Service JWT",
  "scopes": ["read", "write"]
}

Returns accessToken, refreshToken, and expiration timestamps.

Refresh JWT

POST /api/projects/{id}/tokens/refresh
Authorization: Bearer {refreshToken}

List My Tokens

GET /api/users/me/tokens

Returns all tokens created by the authenticated user across all projects.

Revoke Token

DELETE /api/projects/{id}/tokens/{tokenId}

Audit Logs

Query Audit Logs

GET /api/audit?projectId=proj-1&action=flag.update&limit=50

Query parameters:

ParameterTypeDescription
projectIdstringRequired.
actionstringFilter by action type
resourceTypestringflag, service, project, member, invitation, token
resourceIdstringSpecific resource ID
userIdstringFilter by actor
startDatestringISO date lower bound
endDatestringISO date upper bound
limitnumberMax 100
offsetnumberPagination offset

Actions: flag.create, flag.update, flag.delete, flag.toggle, service.create, service.update, service.delete, member.add, member.remove, member.role_change, invitation.create, invitation.accept, invitation.cancel, token.create, token.update, token.revoke

Response:

{
  "logs": [
    {
      "id": "log-1",
      "projectId": "proj-1",
      "userId": "user-123",
      "action": "flag.update",
      "resourceType": "flag",
      "resourceId": "checkout-v2",
      "resourceName": "Checkout V2",
      "before": { "enabled": false },
      "after": { "enabled": true },
      "changes": [
        { "field": "enabled", "oldValue": false, "newValue": true }
      ],
      "metadata": {},
      "timestamp": "2025-07-20T10:30:00Z",
      "ipAddress": "203.0.113.1",
      "userAgent": "Mozilla/5.0..."
    }
  ],
  "total": 150,
  "limit": 50,
  "offset": 0
}

Webhooks

List Webhooks

GET /api/webhooks

Register Webhook

POST /api/webhooks
{
  "url": "https://example.com/webhook",
  "secret": "whsec_your_secret",
  "events": ["flag.created", "flag.updated", "flag.deleted", "flag.toggled"],
  "active": true
}

Update / Delete Webhook

PATCH  /api/webhooks/{id}
DELETE /api/webhooks/{id}

See Webhooks Guide for payload format and signature verification.


Health Checks

Application Health

GET /api/health
{
  "status": "healthy",
  "timestamp": "2025-07-20T10:00:00Z",
  "version": {
    "app": "1.0.0",
    "commit": "abc123",
    "environment": "production"
  },
  "cache": {
    "backend": "redis",
    "readCache": { "working": true, "testTime": 2 },
    "writeCache": { "working": true, "testTime": 3 }
  },
  "storage": { "backend": "firestore" }
}

Admin Health

GET /api/health/admin

Detailed health including storage, cache, and auth subsystem status.

Evaluation Health

GET /api/health/evaluation

Validates the flag evaluation pipeline is functional.


Alerts

Get Alert Status

GET /api/alerts
GET /api/alerts?firing=true
{
  "status": "ok",
  "firingCount": 0,
  "alerts": [
    {
      "name": "HighErrorRate",
      "status": "resolved",
      "severity": "critical",
      "description": "Error rate exceeds 1%",
      "value": 0.2,
      "threshold": 1
    }
  ],
  "evaluatedAt": "2025-07-20T10:00:00Z"
}

Streaming

Connect Stream (SSE)

GET /api/connect/stream?serviceId=web-app&environment=production&clientId=client-1

Returns a text/event-stream with real-time flag change events. See Protocols for details.

Multi-Language Examples

# SSE streams stay open — press Ctrl-C to stop
curl -N "https://flaggr.dev/api/flags/stream?serviceId=web-app" \
  -H "Authorization: Bearer fgr_abc123xxxxxxxxxxxx" \
  -H "Accept: text/event-stream"

Legacy Stream

GET /api/flags/stream?serviceId=web-app

Backward-compatible SSE stream.


Connect Protocol

Evaluate (Connect)

POST /api/connect/evaluate

Uses structured Connect protocol format with protobuf-style values. See Protocols.

Bulk Evaluate (Connect)

POST /api/connect/bulk-evaluate

OFREP v1 — Single

POST /api/ofrep/v1/evaluate/flags/{key}
X-Service-Id: web-app

OFREP v1 — Bulk

POST /api/ofrep/v1/evaluate/flags
X-Service-Id: web-app

OFREP Metadata

GET /api/ofrep/v1/metadata

Closed-Loop Canary Rollout Pipelines

Automated progressive delivery pipelines with metric health gates, minimum soak periods, and automated circuit-breaker rollbacks.

Start Canary Pipeline

POST /api/flags/[key]/canary
{
  "serviceId": "web-app",
  "environment": "production",
  "initialRolloutPercent": 5,
  "targetRolloutPercent": 100,
  "rampStepPercent": 20,
  "soakPeriodMinutes": 30,
  "errorRateGateDelta": 0.01,
  "latencyGateDeltaMs": 50,
  "autoRollbackOnBreach": true
}

Get Canary Pipeline Status

GET /api/flags/[key]/canary?serviceId=web-app&environment=production

Returns the current active stage, completed stages, remaining soak time, and real-time metric health assessment.

Advance Canary Stage

POST /api/flags/[key]/canary/advance
{
  "serviceId": "web-app",
  "environment": "production",
  "force": false
}

Abort Canary Pipeline

POST /api/flags/[key]/canary/abort
{
  "serviceId": "web-app",
  "environment": "production",
  "reason": "Elevated P99 latency during 25% stage"
}

Targeting Rule Explanation & Blast-Radius Simulator

Explain Flag Evaluation

POST /api/flags/[key]/explain

Step-by-step diagnostic evaluation debugger explaining clause-by-clause why a user context resolved to a specific variant.

{
  "serviceId": "web-app",
  "environment": "production",
  "context": {
    "targetingKey": "user-42",
    "tier": "enterprise",
    "country": "US"
  }
}

Simulate Blast-Radius

POST /api/flags/[key]/simulate

Counterfactual blast-radius simulation comparing current baseline flag vs proposed candidate flag across synthetic user cohorts.

{
  "serviceId": "web-app",
  "environment": "production",
  "cohortSize": 200,
  "candidateFlag": {
    "targeting": [
      {
        "id": "new-rule",
        "conditions": [{ "property": "tier", "operator": "equals", "value": "enterprise" }],
        "rolloutPercentage": 100,
        "value": true
      }
    ]
  }
}

Adaptive Multi-Armed Bandits

Bayesian Thompson Sampling and Epsilon-Greedy dynamic traffic weight reallocation with automated statistical stopping rules.

List Bandit Experiments

GET /api/experiments/bandit?projectId=proj-1&serviceId=web-app

Create Bandit Experiment

POST /api/experiments/bandit
{
  "name": "Checkout CTA Optimization",
  "projectId": "proj-1",
  "serviceId": "web-app",
  "flagKey": "checkout-cta",
  "algorithm": "thompson_sampling",
  "minExplorationFloor": 5,
  "minSampleSizePerVariant": 100,
  "confidenceThreshold": 0.95,
  "autoRolloutWinner": true
}

Get Bandit Status

GET /api/experiments/[id]/bandit-status

Reallocate Bandit Traffic

POST /api/experiments/[id]/reallocate

Rebalances variant traffic allocations according to posterior win probabilities. If the statistical confidence threshold is met, automatically promotes the winner to 100% rollout.

Record Bandit Reward

POST /api/experiments/[id]/reward
{
  "variantName": "variant-b",
  "converted": true
}

Dynamic Audience Cohorts & Membership

Evaluate Cohort Membership

POST /api/projects/[id]/cohorts/[cohortId]/evaluate
{
  "userId": "user-123",
  "context": {
    "email": "alice@corp.com",
    "country": "AU"
  }
}

Flag Triggers (CI/CD)

Scoped, revocable URLs that apply a flag action — designed for pipelines ("enable the flag when deploy completes"). The token is the capability: POST the URL with no auth headers.

Create a Trigger

POST /api/flags/{key}/triggers
Authorization: Bearer flg_...

{
  "serviceId": "web",
  "environment": "production",
  "action": "enable",          // enable | disable | toggle
  "name": "deploy-complete"
}

Returns the trigger url and raw token once — only the SHA-256 hash is stored. Triggers are also managed from the flag's Triggers tab in the console.

Execute a Trigger

POST /api/triggers/{token}     // no auth — the token is the capability

Applies the action through the full mutation path (version snapshot, audit as trigger:{name}, SSE fanout, cache invalidation). Rate-limited to 30 executions/minute per token. 404 for unknown and revoked tokens.

List / Revoke

GET    /api/flags/{key}/triggers?serviceId=web
DELETE /api/flags/{key}/triggers/{triggerId}?serviceId=web

Watching Flags & Notifications

Follow a flag to see its mutations in the console notifications bell.

POST   /api/flags/{key}/watch     { "serviceId": "web", "environment": "production" }
DELETE /api/flags/{key}/watch?serviceId=web&environment=production
GET    /api/flags/{key}/watch?serviceId=web&environment=production   // { "watching": true }

GET    /api/notifications          // recent audit events on watched flags + unreadCount
POST   /api/notifications          // mark all read

Evaluation Contexts

GET /api/contexts?serviceId=web&environment=production
GET /api/contexts?serviceId=web&key=user-alice-1     // one context's flag→value map

Recent evaluation contexts grouped by targetingKey — attributes, eval count, and what each flag resolved to. Backed by the in-memory evaluation ring (last ~1,000 evals per instance).

Rate Limiting

All responses include rate limit headers:

HeaderDescription
RateLimit-LimitTotal requests allowed in window
RateLimit-RemainingRemaining requests
RateLimit-ResetUnix timestamp when limit resets

Limits: 1,000/min per IP, 5,000/min per API token, 10,000/min per service.

When rate limited, you'll receive a 429 Too Many Requests response.

Error Responses

All errors follow a consistent format:

{
  "error": "Not Found",
  "message": "Flag 'checkout-v3' not found in service 'web-app'"
}
StatusDescription
400Bad request — invalid parameters or validation failure
401Unauthorized — missing or invalid authentication
403Forbidden — insufficient permissions
404Not found
409Conflict — duplicate resource
429Rate limited
500Internal server error
503Service unavailable

Request Size Limits

EndpointMax Size
Flag create/update256 KB
Flag evaluation64 KB
Bulk operations25.6 MB