Complete REST API documentation for managing feature flags and evaluating them in your applications.
Base URL: http://localhost:3000
Note: For general information about the service, architecture, and deployment, see README.md
This service provides two main API surfaces:
- Management API (
/api/*) - JWT authenticated endpoints for managing projects, flags, and rules - SDK API (
/sdk/*) - SDK key authenticated endpoints for client applications to evaluate flags
All /api/* endpoints require JWT authentication via the Authorization: Bearer {token} header.
Obtaining a Token:
- Register a user account with
POST /auth/register - Login with
POST /auth/loginto receive a JWT token - Include the token in the Authorization header for all subsequent requests
Example:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Token Validity: 24 hours
SDK endpoints use the X-SDK-Key header for authentication. SDK keys are generated when creating a project.
Example:
X-SDK-Key: sdk_your_project_key_hereGET /health
Response: "OK"
Create a new user account.
POST /auth/register
Content-Type: application/json
{
"email": "developer@example.com",
"password": "secure_password_123"
}Response (201 Created):
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "developer@example.com"
}Validation:
- Email must be valid format and unique
- Password must be at least 8 characters
- Password is hashed with Argon2 before storage
Authenticate and receive a JWT token.
POST /auth/login
Content-Type: application/json
{
"email": "developer@example.com",
"password": "secure_password_123"
}Response (200 OK):
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Notes:
- Token is valid for 24 hours
- Include token in
Authorization: Bearer {token}header for all/api/*requests
Request a password reset for an email address.
POST /auth/forgot-password
Content-Type: application/json
{
"email": "developer@example.com"
}Response (200 OK):
{
"message": "If the account exists, a reset link has been sent."
}Notes:
- Returns the same response regardless of whether the email exists.
- Reset tokens are single-use and expire after 30 minutes.
Reset account password using a valid reset token.
POST /auth/reset-password
Content-Type: application/json
{
"token": "reset_token_from_email",
"new_password": "new_secure_password_123"
}Response (200 OK):
Password reset successful
Validation:
new_passwordmust be at least 8 characters.- Token must be valid, unexpired, and unused.
Get the authenticated user's information.
GET /api/me
Authorization: Bearer {token}Response (200 OK):
{
"user_id": "550e8400-e29b-41d4-a716-446655440000"
}Create a new project to organize your feature flags.
POST /api/projects
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "My Mobile App",
"description": "iOS and Android application"
}Parameters:
name(string, required) - Project namedescription(string, optional) - Project description
Response (201 Created):
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "My Mobile App",
"description": "iOS and Android application",
"sdk_key": "sdk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-14T10:00:00Z"
}Notes:
- SDK key is automatically generated and globally unique
- Save the SDK key for client-side flag evaluation
Get all projects owned by the authenticated user.
GET /api/projects
Authorization: Bearer {token}Response (200 OK):
[
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "My Mobile App",
"description": "iOS and Android application",
"sdk_key": "sdk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-14T10:00:00Z"
},
{
"id": "8d0f7780-8536-51ef-a055-f18gd2g01bf8",
"name": "Web Dashboard",
"description": "Admin dashboard",
"sdk_key": "sdk_q1w2e3r4t5y6u7i8o9p0a1s2d3f4g5h6",
"created_at": "2024-12-15T14:30:00Z",
"updated_at": "2024-12-15T14:30:00Z"
}
]Get details of a specific project.
GET /api/projects/{project_id}
Authorization: Bearer {token}Response (200 OK):
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "My Mobile App",
"description": "iOS and Android application",
"sdk_key": "sdk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-14T10:00:00Z"
}Update project name or description.
PUT /api/projects/{project_id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "My Mobile App (Production)",
"description": "Production iOS and Android app"
}Parameters:
name(string, optional) - New project namedescription(string, optional) - New project description- Only provided fields will be updated
Response (200 OK):
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "My Mobile App (Production)",
"description": "Production iOS and Android app",
"sdk_key": "sdk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-16T09:15:00Z"
}Delete a project and all associated flags and rules.
DELETE /api/projects/{project_id}
Authorization: Bearer {token}Response: 204 No Content
Warning: This action is irreversible and will cascade delete:
- All feature flags in the project
- All targeting rules for those flags
- All evaluation history
Generate a new SDK key for a project. Use this if your SDK key has been compromised.
POST /api/projects/{project_id}/regenerate-key
Authorization: Bearer {token}Response (200 OK):
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "My Mobile App",
"description": "iOS and Android application",
"sdk_key": "sdk_z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4",
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-16T10:00:00Z"
}Warning: The old SDK key will be immediately invalidated. Update all client applications with the new key.
POST /api/projects/{project_id}/flags
Body: {
"name": "New Checkout",
"key": "new_checkout", // lowercase, alphanumeric, _, -
"description": "Optional",
"enabled": true, // optional, default: false
"rollout_percentage": 50 // optional, 0-100, default: 0
}
Response: {
"id": "uuid",
"project_id": "uuid",
"name": "New Checkout",
"key": "new_checkout",
"description": "Optional",
"enabled": true,
"rollout_percentage": 50,
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-14T10:00:00Z"
}
Validation Rules:
keymust start with a letterkeycan only contain lowercase letters, numbers,_, and-keymust be unique within the projectrollout_percentagemust be 0-100
GET /api/projects/{project_id}/flags
Response: [ {...flag}, {...flag} ]
GET /api/projects/{project_id}/flags/{flag_id}
Response: {...flag}
PUT /api/projects/{project_id}/flags/{flag_id}
Body: {
"name": "Updated Name",
"description": "Updated description",
"enabled": false,
"rollout_percentage": 75
}
Note: All fields are optional, only provided fields are updated
Response: {...flag}
POST /api/projects/{project_id}/flags/{flag_id}/toggle
Response: {...flag with flipped enabled state}
DELETE /api/projects/{project_id}/flags/{flag_id}
Response: 204 No Content
Target specific users or groups with advanced flag rules. Rules are evaluated for each flag to determine if it should be enabled for a specific user.
POST /api/projects/{project_id}/flags/{flag_id}/rules
Body: {
"rule_type": "user_email", // user_id, user_email, or email_domain
"rule_value": "admin@example.com", // The value to match
"enabled": true, // optional, default: true
"priority": 10 // optional, default: 0, higher = evaluated first
}
Response: {
"id": "uuid",
"flag_id": "uuid",
"rule_type": "user_email",
"rule_value": "admin@example.com",
"enabled": true,
"priority": 10,
"created_at": "2024-12-14T10:00:00Z"
}
Rule Types:
user_id- Match specific user identifieruser_email- Match specific email address (must contain @)email_domain- Match email domain (must start with @, e.g., "@company.com")
Validation Rules:
rule_valuecannot be empty- Email domains must start with @
- User emails must contain @
prioritydetermines evaluation order (higher values evaluated first)
GET /api/projects/{project_id}/flags/{flag_id}/rules
Response: [ {...rule}, {...rule} ]
Note: Rules are returned ordered by priority (highest first)
GET /api/projects/{project_id}/flags/{flag_id}/rules/{rule_id}
Response: {...rule}
PUT /api/projects/{project_id}/flags/{flag_id}/rules/{rule_id}
Body: {
"rule_type": "email_domain",
"rule_value": "@newcompany.com",
"enabled": false,
"priority": 20
}
Note: All fields are optional, only provided fields are updated
Response: {...rule}
DELETE /api/projects/{project_id}/flags/{flag_id}/rules/{rule_id}
Response: 204 No Content
All error responses follow this format:
Status: 4xx or 5xx
Body: "Error message string"
Common status codes:
400 Bad Request- Invalid input (validation failed)401 Unauthorized- Missing or invalid JWT token404 Not Found- Resource doesn't exist409 Conflict- Duplicate key or other constraint violation500 Internal Server Error- Server-side error
The SDK API provides public endpoints for client applications to evaluate feature flags.
SDK endpoints use SDK key authentication via the X-SDK-Key header. SDK keys are generated when you create a project.
X-SDK-Key: sdk_your_key_here
Evaluate all feature flags for a given user context.
POST /sdk/v1/evaluate
Headers:
X-SDK-Key: sdk_your_project_key_here
Content-Type: application/json
Body:
{
"user_id": "user_12345",
"user_email": "alice@example.com",
"custom_attributes": {}
}
Parameters:
user_id(string, required) - Unique identifier for the useruser_email(string, optional) - User's email address for email-based targetingcustom_attributes(object, optional) - Reserved for future custom attribute targeting
{
"dark_mode": {
"enabled": true,
"reason": "rollout"
},
"new_checkout": {
"enabled": true,
"reason": "rule_match"
},
"premium_features": {
"enabled": false,
"reason": "disabled"
}
}Response Format:
- Returns an object where keys are flag keys
- Each flag has:
enabled(boolean) - Whether the flag is enabled for this userreason(string) - Why the flag was enabled/disabled:"disabled"- Flag is globally disabled"rule_match"- User matched a targeting rule"rollout"- User fell within the rollout percentage"rollout_excluded"- User was excluded from rollout percentage
Evaluation Algorithm:
- If flag is disabled → return
falsewith reason"disabled" - Check targeting rules in priority order → return
truewith reason"rule_match"if matched - Apply percentage rollout with consistent hashing → return
true/falsewith reason"rollout"/"rollout_excluded"
Notes:
- All evaluations are logged to the
flag_evaluationstable for analytics - Consistent hashing ensures the same user always gets the same result for a given rollout percentage
- This endpoint is designed for high-throughput client-side evaluation
For more information about the service:
- Architecture & Deployment: See README.md
- Database Schema: See README.md
- Security Features: See README.md
- Client Integration Examples: See README.md
- Testing: Import postman_collection.json for interactive API testing