Complete reference for all Flaggr REST API endpoints — flags, evaluation, projects, services, tokens, audit, and webhooks
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 flg_your_token
Session Cookie
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 flg_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"
}
}' | jqBulk Evaluate
POST /api/flags/evaluate/bulk
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/bulk \
-H "Authorization: Bearer flg_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"
}
}' | jqEvaluation 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.
Flag Management
List Flags
GET /api/flags?projectId=proj-1&serviceId=web-app&environment=production
Query parameters:
| Parameter | Type | Description |
|---|---|---|
projectId | string | Required. Project ID |
serviceId | string | Filter by service |
environment | string | development, staging, or production |
limit | number | Max 100, default 50 |
offset | number | Offset-based pagination |
cursor | string | Cursor-based pagination |
cursor_direction | string | next or prev |
search | string | Search flag keys and names |
tags | string | Comma-separated tag filter |
enabled | boolean | Filter by enabled state |
type | string | boolean, 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 flg_abc123xxxxxxxxxxxx" | jqCreate 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 flg_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
}' | jqGet 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. Returns the updated flag.
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": "flg_abc123..."
}Multi-Language Examples
curl -s -X POST https://flaggr.dev/api/projects/proj-1/tokens \
-H "Authorization: Bearer flg_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 => "flg_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:
| Parameter | Type | Description |
|---|---|---|
projectId | string | Required. |
action | string | Filter by action type |
resourceType | string | flag, service, project, member, invitation, token |
resourceId | string | Specific resource ID |
userId | string | Filter by actor |
startDate | string | ISO date lower bound |
endDate | string | ISO date upper bound |
limit | number | Max 100 |
offset | number | Pagination 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 flg_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
Rate Limiting
All responses include rate limit headers:
| Header | Description |
|---|---|
RateLimit-Limit | Total requests allowed in window |
RateLimit-Remaining | Remaining requests |
RateLimit-Reset | Unix 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'"
}| Status | Description |
|---|---|
400 | Bad request — invalid parameters or validation failure |
401 | Unauthorized — missing or invalid authentication |
403 | Forbidden — insufficient permissions |
404 | Not found |
409 | Conflict — duplicate resource |
429 | Rate limited |
500 | Internal server error |
503 | Service unavailable |
Request Size Limits
| Endpoint | Max Size |
|---|---|
| Flag create/update | 256 KB |
| Flag evaluation | 64 KB |
| Bulk operations | 25.6 MB |