/api/experimentsPortal experiment list.
Public docs
Integration-first docs for portal APIs and runtime SDK APIs, including fallback semantics and default-value guidance.
/api/experimentsPortal experiment list.
/api/experimentsPortal experiment create.
/api/experimentsPortal experiment update.
/api/experimentsPortal experiment delete.
/api/feature-gatesPortal feature gate list (scoped).
/api/feature-gatesPortal feature gate create + publish.
/api/feature-gatesPortal feature gate update + publish.
/api/feature-gatesPortal feature gate delete + publish.
/api/v1/sdk-keysPortal SDK key list (scoped).
/api/v1/sdk-keysPortal SDK key create.
/api/v1/sdk-keysPortal SDK key revoke.
/api/v1/download_config_specsServer SDK config download (full specs).
/api/v1/initializeClient SDK initialize (evaluated values only).
/api/v1/eventsEvent ingestion for client/server SDKs.
/api/events/catalogPortal event explorer catalog (grouped by event name).
/api/events/streamPortal event explorer raw stream with filters.
/api/v1/evaluate-debugPortal debug evaluation diagnostics.
SDK keys are scoped to `projectId + environmentId`. Use `Authorization: Bearer <sdk_key>` for runtime endpoints.
| Key type | Allowed | Denied | Notes |
|---|---|---|---|
| server_secret | /api/v1/download_config_specs, /api/v1/events | /api/v1/initialize | Use for backend services doing local evaluation after config sync. |
| client_public | /api/v1/initialize, /api/v1/events | /api/v1/download_config_specs | Use for end-user clients; returns evaluated values, not full targeting rules. |
Server integrations fetch full config specs, cache them locally, and evaluate without per-check network calls.
POST /api/v1/download_config_specs request
{
"sinceVersion": "7"
}POST /api/v1/download_config_specs response
{
"projectId": "...",
"environmentId": "...",
"version": "8",
"generatedAt": "2026-02-22T15:31:06.000Z",
"hasUpdates": true,
"experiments": [{ "experimentId": "checkout_ui_v2", "targeting": { "rules": [] } }],
"gates": [{ "key": "checkout_redesign_enabled", "targeting": { "rules": [] } }]
}Polling: send `If-None-Match` with previous version (or `sinceVersion`) and cache by `ETag` value.
Client integrations call initialize with a user object and receive evaluated values only.
POST /api/v1/initialize request
{
"user": {
"userId": "user-123",
"country": "US",
"appVersion": "1.9.0"
}
}POST /api/v1/initialize response
{
"projectId": "...",
"environmentId": "...",
"version": "8",
"source": "network",
"identityProvided": true,
"experiments": {
"checkout_ui_v2": "treatment"
},
"gates": {
"checkout_redesign_enabled": true
},
"defaultsRecommended": true,
"defaultUsage": {
"gate": "getGate('gate_key', false)",
"experiment": "getExperiment('experiment_key', 'control')"
}
}Privacy: full targeting/cohort rules are not returned by this endpoint.
experiment_exposure events are persisted to the dedicated exposure store; all other events are written to the general events stream.
POST /api/v1/events request
{
"user": { "userId": "user-123" },
"sdkInfo": { "name": "equipoise-js", "version": "0.1.0" },
"events": [
{
"eventName": "experiment_exposure",
"metadata": { "experimentId": "checkout_ui_v2", "variant": "treatment" },
"time": "2026-02-22T15:30:00.000Z"
},
{
"eventName": "checkout_started",
"value": 1
}
]
}POST /api/v1/events response
{
"accepted": 2,
"dropped": 0,
"projectId": "...",
"environmentId": "..."
}Recommended runtime order:
// Example usage pattern (SDK-side contract)
const enabled = client.getGate("checkout_redesign_enabled", false);
const variant = client.getExperiment("checkout_ui_v2", "control");Integrations should always pass explicit defaults; this avoids undefined behavior when both network and cache are unavailable.
Portal CRUD endpoints (`/api/experiments`, `/api/feature-gates`) remain the authoring surface. Runtime SDK integrations should use `/api/v1/*` endpoints.