REST API Reference
The Sidekick server exposes a REST API for managing feature flags. All endpoints require the Authorization: Bearer <SDK_KEY> header when SDK_KEY is configured on the server.
Base URL
http://your-sidekick-server:3000Authentication
Authorization: Bearer your-sdk-keyWhen SDK_KEY is not set on the server, authentication is disabled (development mode only).
Flags
List All Flags
GET /api/flagsReturns all flags from the in-memory store (served without a database round-trip).
Response 200 OK
[
{
"key": "new-checkout-flow",
"is_enabled": true,
"rollout_percentage": 50,
"description": "New checkout UI rollout",
"rules": []
}
]Get a Flag
GET /api/flags/:keyResponse 200 OK
{
"key": "new-checkout-flow",
"is_enabled": true,
"rollout_percentage": 50,
"description": "New checkout UI rollout",
"rules": [
{
"attribute": "plan",
"operator": "equals",
"values": ["enterprise"]
}
]
}Response 404 Not Found — flag does not exist.
Create or Replace a Flag
POST /api/flags
Content-Type: application/jsonCreates a flag. If the key already exists, replaces it entirely.
Request Body
{
"key": "new-checkout-flow",
"is_enabled": true,
"rollout_percentage": 50,
"description": "New checkout UI rollout",
"rules": []
}Response 200 OK — returns the created flag.
Partially Update a Flag
PATCH /api/flags/:key
Content-Type: application/jsonApplies a JSON merge patch. Only the provided fields are updated; omitted fields retain their current values.
Request Body (update only the rollout percentage)
{
"rollout_percentage": 100
}Request Body (disable the flag)
{
"is_enabled": false
}Response 200 OK — returns the updated flag.
Response 404 Not Found — flag does not exist.
Delete a Flag
DELETE /api/flags/:keyDeletes the flag from PostgreSQL, the in-memory store, and broadcasts a DELETE event to all connected SDK clients.
Response 204 No Content
Flag Schema
Flag Object
| Field | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Unique identifier. Use kebab-case. |
is_enabled | boolean | Yes | Master switch. false always evaluates to false. |
rollout_percentage | integer | null | No | 0–100. null is treated as 100%. |
description | string | null | No | Human-readable description. |
rules | TargetingRule[] | No | Targeting rules. Defaults to []. |
TargetingRule Object
| Field | Type | Required | Description |
|---|---|---|---|
attribute | string | Yes | User attribute name to match against. |
operator | Operator | Yes | Comparison operator. |
values | string[] | Yes | One or more values to match. At least one must match. |
Operator Enum
| Value | Description |
|---|---|
equals | Attribute value equals any of the provided values |
not_equals | Attribute value does not equal any of the provided values |
contains | Attribute value contains any of the provided values as a substring |
starts_with | Attribute value starts with any of the provided values |
ends_with | Attribute value ends with any of the provided values |
SSE Stream
Connect
GET /stream
Authorization: Bearer your-sdk-key
Accept: text/event-streamOpens a persistent SSE connection. The server sends:
- A
connectedevent immediately - One
updateevent per existing flag (bootstrap) updateevents as flags change in real time- Keep-alive comments every 15 seconds
Event: connected
event: connected
data: trueSent once when the connection is established. SDK clients should clear their local store on receiving this event to prepare for a clean bootstrap.
Event: update
event: update
data: {"type":"UPSERT","flag":{"key":"my-flag","is_enabled":true,...}}event: update
data: {"type":"DELETE","key":"my-flag"}UPSERT Payload
{
"type": "UPSERT",
"flag": {
"key": "new-checkout-flow",
"is_enabled": true,
"rollout_percentage": 50,
"description": null,
"rules": []
}
}DELETE Payload
{
"type": "DELETE",
"key": "new-checkout-flow"
}Keep-Alive
: keep-alive-textSent every 15 seconds to prevent proxy timeouts. Clients should ignore this.
Reconnection
If the SSE connection drops, clients should reconnect with exponential backoff. On reconnect:
- Server sends
connected→ SDK clears local store - Server replays all current flags → SDK rebuilds from scratch
This guarantees consistency even after missed updates during the disconnected period.