Experimentation
This capability is granted by an API key scoped to the `` product (product face). See the product reference below.
Experimentation capability — a durable, org-scoped experiment registry with a DETERMINISTIC variant assignment engine (stable SHA-256 hash of (salt, key, user_id) → a fixed bucket space → sliced by cumulative normalized weight; sticky by construction, no per-user assignment row). Products stop re-rolling an A/B engine + an exposure pipeline; they define experiments, assign users, and record exposures over this one capability. I4: own Postgres store (fleet_experiments); the results SoT is the local exposures table, analytics is a downstream mirror.
- Group: Governance & platform
- Contract:
contracts/experimentation/v1/openapi.yaml - Public base:
https://api.vagarylabs.com(the consolidated API gateway — one host, per-brand siblingapi.<zone>) - Auth: a product API key (
vgk_…) issued from the console —Authorization: Bearer vgk_… - Product face (customer-keyed):
https://api.vagarylabs.com/product/v1/experiments
Endpoints
| Method | Path | Summary |
|---|---|---|
POST | /v1/experiments | Define (idempotent upsert) an experiment — key, weighted variants, status, metric |
GET | /v1/experiments | List the org's experiments (newest first) |
GET | /v1/experiments/{experiment_id} | One experiment definition or 404 |
PATCH | /v1/experiments/{experiment_id} | Partially update an experiment (name / variants / status / metric) |
GET | /v1/assign | Deterministically assign a user to a variant (sticky; control on not-running / kill-switch) |
POST | /v1/exposures | Record a user's exposure (persist to results SoT + fan out to analytics, fail-open) |
GET | /v1/experiments/{experiment_id}/results | Per-variant exposure / unique-user readout for the experiment |
GET | /health | liveness |
GET | /metrics | Prometheus |
Schemas
Variant
| Field | Type | Description |
|---|---|---|
name | string | variant name (unique within the experiment; the first is control) |
weight | number | relative weight; normalized across variants (equal split when all omitted) |
ExperimentRequest
| Field | Type | Description |
|---|---|---|
organization_id | string | product-tier end-customer tenant (I6) |
experiment_id | string | server-generated (exp_...) if omitted; supply to upsert an existing one |
key | string | stable human key, unique per org — the /v1/assign lookup handle |
name | string | |
variants | array | |
status | string | |
metric | string | the primary success metric name (recorded on emitted exposure events) |
salt | string | per-experiment bucketing salt; server default when omitted. Rotating it re-randomizes assignment — never on a live experiment |
ExperimentPatch
| Field | Type | Description |
|---|---|---|
organization_id | string | |
name | string | |
variants | array | |
status | string | |
metric | string |
Experiment
| Field | Type | Description |
|---|---|---|
experiment_id | string | |
key | string | |
name | string | |
variants | array | |
status | string | |
metric | string | |
salt | string | |
created_at | number | epoch seconds |
updated_at | number |
ExperimentList
| Field | Type | Description |
|---|---|---|
experiments | array | |
count | integer |
Assignment
| Field | Type | Description |
|---|---|---|
experiment | string | the experiment key |
experiment_id | string | |
variant | string | assigned variant name (control when not-running/killed) |
sticky | boolean | always true — a pure deterministic function of (key, user_id, salt) |
reason | string | assigned |
ExposureRequest
| Field | Type | Description |
|---|---|---|
organization_id | string | |
experiment | string | experiment_id or key |
user_id | string | |
variant | string | omit → recomputed deterministically server-side |
ExposureResult
| Field | Type | Description |
|---|---|---|
experiment | string | |
experiment_id | string | |
user_id | string | |
variant | string | |
recorded | boolean | persisted to the local exposures SoT |
emitted_to_analytics | boolean | fanned out to the analytics capability (fail-open — false on a downstream outage) |
Generated by scripts/gen-capability-docs.py from contracts/experimentation/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page.