Public docs

Equipoise API contracts

Integration-first docs for portal APIs and runtime SDK APIs, including fallback semantics and default-value guidance.

Endpoint index

GET/api/experiments

Portal experiment list.

POST/api/experiments

Portal experiment create.

PUT/api/experiments

Portal experiment update.

DELETE/api/experiments

Portal experiment delete.

GET/api/feature-gates

Portal feature gate list (scoped).

POST/api/feature-gates

Portal feature gate create + publish.

PUT/api/feature-gates

Portal feature gate update + publish.

DELETE/api/feature-gates

Portal feature gate delete + publish.

GET/api/v1/sdk-keys

Portal SDK key list (scoped).

POST/api/v1/sdk-keys

Portal SDK key create.

DELETE/api/v1/sdk-keys

Portal SDK key revoke.

POST/api/v1/download_config_specs

Server SDK config download (full specs).

POST/api/v1/initialize

Client SDK initialize (evaluated values only).

POST/api/v1/events

Event ingestion for client/server SDKs.

GET/api/events/catalog

Portal event explorer catalog (grouped by event name).

GET/api/events/stream

Portal event explorer raw stream with filters.

POST/api/v1/evaluate-debug

Portal debug evaluation diagnostics.

Authentication and key scopes

SDK keys are scoped to `projectId + environmentId`. Use `Authorization: Bearer <sdk_key>` for runtime endpoints.

Key typeAllowedDeniedNotes
server_secret/api/v1/download_config_specs, /api/v1/events/api/v1/initializeUse for backend services doing local evaluation after config sync.
client_public/api/v1/initialize, /api/v1/events/api/v1/download_config_specsUse for end-user clients; returns evaluated values, not full targeting rules.

Server SDK flow

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 SDK flow

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.

Event ingestion

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": "..."
}

Fallback and default-value guidance

Recommended runtime order:

  1. Use fresh network values when initialize/download succeeds.
  2. On fetch failure, use last known local SDK cache.
  3. If cache is unavailable, use code defaults provided at call sites.
// 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.

Compatibility notes

Portal CRUD endpoints (`/api/experiments`, `/api/feature-gates`) remain the authoring surface. Runtime SDK integrations should use `/api/v1/*` endpoints.