@shipeasy/openapi 1.5.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +37 -0
  2. package/dist/chunk-EPLLHLZN.js +1616 -0
  3. package/dist/chunk-EPLLHLZN.js.map +1 -0
  4. package/dist/chunk-SPH5HWCD.js +3326 -0
  5. package/dist/chunk-SPH5HWCD.js.map +1 -0
  6. package/dist/client-pVkoo3Bf.d.ts +11186 -0
  7. package/dist/client.d.ts +1 -0
  8. package/dist/client.js +215 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/custom.d.ts +64 -0
  11. package/dist/custom.js +292 -0
  12. package/dist/custom.js.map +1 -0
  13. package/dist/index.d.ts +29 -17
  14. package/dist/index.js +253 -2458
  15. package/dist/index.js.map +1 -0
  16. package/dist/node-context.d.ts +85 -0
  17. package/dist/node-context.js +110 -0
  18. package/dist/node-context.js.map +1 -0
  19. package/dist/schemas.d.ts +7920 -0
  20. package/dist/schemas.js +1083 -0
  21. package/dist/schemas.js.map +1 -0
  22. package/openapi.json +15297 -3044
  23. package/openapi.yaml +13979 -0
  24. package/package.json +37 -21
  25. package/spec/components/errors.yaml +53 -0
  26. package/spec/components/parameters.yaml +24 -0
  27. package/spec/components/responses.yaml +107 -0
  28. package/spec/components/schemas/alert-rules.yaml +175 -0
  29. package/spec/components/schemas/attributes.yaml +157 -0
  30. package/spec/components/schemas/common.yaml +87 -0
  31. package/spec/components/schemas/configs.yaml +371 -0
  32. package/spec/components/schemas/connectors.yaml +593 -0
  33. package/spec/components/schemas/errors-api.yaml +209 -0
  34. package/spec/components/schemas/events.yaml +321 -0
  35. package/spec/components/schemas/experiments.yaml +865 -0
  36. package/spec/components/schemas/gate-templates.yaml +198 -0
  37. package/spec/components/schemas/gates.yaml +890 -0
  38. package/spec/components/schemas/i18n.yaml +478 -0
  39. package/spec/components/schemas/keys.yaml +186 -0
  40. package/spec/components/schemas/killswitches.yaml +309 -0
  41. package/spec/components/schemas/metrics.yaml +547 -0
  42. package/spec/components/schemas/ops.yaml +1011 -0
  43. package/spec/components/schemas/projects.yaml +222 -0
  44. package/spec/components/schemas/search.yaml +46 -0
  45. package/spec/components/schemas/universes.yaml +127 -0
  46. package/spec/openapi.yaml +348 -0
  47. package/spec/paths/alert-rules.yaml +250 -0
  48. package/spec/paths/attributes.yaml +261 -0
  49. package/spec/paths/configs.yaml +744 -0
  50. package/spec/paths/connectors.yaml +748 -0
  51. package/spec/paths/errors.yaml +382 -0
  52. package/spec/paths/events.yaml +366 -0
  53. package/spec/paths/experiments.yaml +777 -0
  54. package/spec/paths/gate-templates.yaml +263 -0
  55. package/spec/paths/gates.yaml +451 -0
  56. package/spec/paths/i18n.yaml +544 -0
  57. package/spec/paths/keys.yaml +181 -0
  58. package/spec/paths/killswitches.yaml +557 -0
  59. package/spec/paths/metrics.yaml +302 -0
  60. package/spec/paths/ops.yaml +446 -0
  61. package/spec/paths/projects.yaml +210 -0
  62. package/spec/paths/search.yaml +62 -0
  63. package/spec/paths/universes.yaml +247 -0
  64. package/dist/resources/alert-rules.d.ts +0 -50
  65. package/dist/resources/alert-rules.js +0 -75
  66. package/dist/resources/configs.d.ts +0 -681
  67. package/dist/resources/configs.js +0 -509
  68. package/dist/resources/experiments.d.ts +0 -849
  69. package/dist/resources/experiments.js +0 -707
  70. package/dist/resources/gates.d.ts +0 -808
  71. package/dist/resources/gates.js +0 -522
  72. package/dist/resources/index.d.ts +0 -2749
  73. package/dist/resources/index.js +0 -2391
  74. package/dist/resources/killswitches.d.ts +0 -436
  75. package/dist/resources/killswitches.js +0 -514
  76. package/dist/resources/universes.d.ts +0 -185
  77. package/dist/resources/universes.js +0 -234
  78. package/dist/schemas/alert-rules.d.ts +0 -65
  79. package/dist/schemas/alert-rules.js +0 -37
  80. package/dist/schemas/configs.d.ts +0 -154
  81. package/dist/schemas/configs.js +0 -134
  82. package/dist/schemas/constants.d.ts +0 -6
  83. package/dist/schemas/constants.js +0 -7
  84. package/dist/schemas/experiments.d.ts +0 -229
  85. package/dist/schemas/experiments.js +0 -221
  86. package/dist/schemas/folder.d.ts +0 -10
  87. package/dist/schemas/folder.js +0 -8
  88. package/dist/schemas/gates.d.ts +0 -386
  89. package/dist/schemas/gates.js +0 -190
  90. package/dist/schemas/index.d.ts +0 -11
  91. package/dist/schemas/index.js +0 -762
  92. package/dist/schemas/killswitches.d.ts +0 -110
  93. package/dist/schemas/killswitches.js +0 -226
  94. package/dist/schemas/metric-name.d.ts +0 -5
  95. package/dist/schemas/metric-name.js +0 -6
  96. package/dist/schemas/pagination.d.ts +0 -37
  97. package/dist/schemas/pagination.js +0 -44
  98. package/dist/schemas/universes.d.ts +0 -35
  99. package/dist/schemas/universes.js +0 -55
  100. package/dist/transport.d.ts +0 -30
  101. package/dist/transport.js +0 -44
@@ -0,0 +1,777 @@
1
+ /api/admin/experiments:
2
+ get:
3
+ operationId: listExperiments
4
+ summary: List experiments
5
+ description: |-
6
+ Returns a single page of non-archived experiments ordered by `updated_at desc, id desc`. Use the `cursor` query parameter to paginate.
7
+
8
+ **Use case:** Snapshot every active experiment in the project — e.g. render an overview dashboard or drive a CI check that no experiment has been running past its `min_runtime_days`.
9
+ tags:
10
+ - Experiments
11
+ parameters:
12
+ - $ref: ../components/parameters.yaml#/ProjectId
13
+ - $ref: ../components/parameters.yaml#/PaginationLimit
14
+ - $ref: ../components/parameters.yaml#/PaginationCursor
15
+ responses:
16
+ "200":
17
+ description: List experiments
18
+ content:
19
+ application/json:
20
+ schema:
21
+ $ref: ../components/schemas/experiments.yaml#/ListExperimentsResponse
22
+ example:
23
+ data:
24
+ - id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
25
+ name: checkout_button_color
26
+ description: Test green vs. blue CTA on the checkout page.
27
+ tag: checkout
28
+ status: running
29
+ universe: primary_users
30
+ targetingGate: null
31
+ allocationPct: 5000
32
+ salt: 8d3e9a1f6b7c4a5fa1c2b6d3e7c8e3a1
33
+ params:
34
+ cta_color: string
35
+ groups:
36
+ - name: control
37
+ weight: 5000
38
+ params:
39
+ cta_color: blue
40
+ - name: treatment
41
+ weight: 5000
42
+ params:
43
+ cta_color: green
44
+ significanceThreshold: 0.05
45
+ minRuntimeDays: 7
46
+ minSampleSize: 1000
47
+ sequentialTesting: false
48
+ startedAt: 2026-05-01T12:00:00.000Z
49
+ stoppedAt: null
50
+ updatedAt: 2026-05-09T18:22:11.000Z
51
+ next_cursor: null
52
+ "400":
53
+ $ref: ../components/responses.yaml#/BadRequest
54
+ "401":
55
+ $ref: ../components/responses.yaml#/Unauthorized
56
+ "403":
57
+ $ref: ../components/responses.yaml#/Forbidden
58
+ "404":
59
+ $ref: ../components/responses.yaml#/NotFound
60
+ "409":
61
+ $ref: ../components/responses.yaml#/Conflict
62
+ "422":
63
+ $ref: ../components/responses.yaml#/UnprocessableEntity
64
+ x-error-codes:
65
+ - BAD_REQUEST
66
+ - UNAUTHORIZED
67
+ - FORBIDDEN
68
+ x-cli:
69
+ name: list
70
+ post:
71
+ operationId: createExperiment
72
+ summary: Create an experiment
73
+ description: |-
74
+ Creates a new experiment in `draft` status. `name`, `universe`, and `groups` are required; everything else has sensible defaults.
75
+
76
+ Returns `409` if `name` already exists, `422` if the named universe doesn't exist, `403` if a plan-gated option is set (`sequential_testing`, custom `significance_threshold`) on a plan that doesn't include it.
77
+
78
+ **Use cases**
79
+
80
+ - **Minimal 50/50** — `name` + `universe` + two equal-weight groups.
81
+ - **Targeted rollout** — supply `targeting_gate` to restrict the eligible audience and `allocation_pct` to enrol a slice of it.
82
+ - **Multivariant** — three or more groups with weights summing to 10000.
83
+ - **Sequential testing** — `sequential_testing: true` for Premium plans.
84
+ tags:
85
+ - Experiments
86
+ parameters:
87
+ - $ref: ../components/parameters.yaml#/ProjectId
88
+ requestBody:
89
+ required: true
90
+ content:
91
+ application/json:
92
+ schema:
93
+ $ref: ../components/schemas/experiments.yaml#/CreateExperimentRequest
94
+ examples:
95
+ minimal:
96
+ summary: Minimal — two-group 50/50
97
+ description: Smallest valid body. Two groups at 50/50, no allocation, no targeting.
98
+ value:
99
+ name: checkout_button_color
100
+ universe: primary_users
101
+ groups:
102
+ - name: control
103
+ weight: 5000
104
+ - name: treatment
105
+ weight: 5000
106
+ targeted:
107
+ summary: Targeted — gate + allocation + params
108
+ description: Gate the audience with a `targeting_gate`, allocate 50% of it, and parameterise the variants.
109
+ value:
110
+ name: checkout_button_color
111
+ description: Green CTA on checkout for Pro users.
112
+ universe: primary_users
113
+ targeting_gate: pro_plan_only
114
+ allocation_pct: 5000
115
+ params:
116
+ cta_color: string
117
+ groups:
118
+ - name: control
119
+ weight: 5000
120
+ params:
121
+ cta_color: blue
122
+ - name: treatment
123
+ weight: 5000
124
+ params:
125
+ cta_color: green
126
+ multivariant:
127
+ summary: Multivariant — three groups
128
+ description: Three variants splitting 40/30/30. Requires the sum to equal 10000.
129
+ value:
130
+ name: headline_test
131
+ universe: primary_users
132
+ groups:
133
+ - name: control
134
+ weight: 4000
135
+ - name: alt_a
136
+ weight: 3000
137
+ - name: alt_b
138
+ weight: 3000
139
+ sequential:
140
+ summary: Sequential testing — Premium plan
141
+ description: Enable always-valid sequential tests. Requires Premium plan or higher.
142
+ value:
143
+ name: checkout_button_color
144
+ universe: primary_users
145
+ groups:
146
+ - name: control
147
+ weight: 5000
148
+ - name: treatment
149
+ weight: 5000
150
+ sequential_testing: true
151
+ min_runtime_days: 14
152
+ responses:
153
+ "201":
154
+ description: Create an experiment
155
+ content:
156
+ application/json:
157
+ schema:
158
+ $ref: ../components/schemas/experiments.yaml#/CreateExperimentResponse
159
+ example:
160
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
161
+ name: checkout_button_color
162
+ "400":
163
+ $ref: ../components/responses.yaml#/BadRequest
164
+ "401":
165
+ $ref: ../components/responses.yaml#/Unauthorized
166
+ "403":
167
+ $ref: ../components/responses.yaml#/Forbidden
168
+ "404":
169
+ $ref: ../components/responses.yaml#/NotFound
170
+ "409":
171
+ $ref: ../components/responses.yaml#/Conflict
172
+ "422":
173
+ $ref: ../components/responses.yaml#/UnprocessableEntity
174
+ x-error-codes:
175
+ - BAD_REQUEST
176
+ - UNAUTHORIZED
177
+ - FORBIDDEN
178
+ - PLAN_REQUIRED
179
+ - ALREADY_EXISTS
180
+ - GROUPS_WEIGHT_SUM
181
+ - REFERENCED_NOT_FOUND
182
+ - VALIDATION
183
+ x-cli:
184
+ name: create
185
+ positional:
186
+ - name
187
+ /api/admin/experiments/{id}:
188
+ get:
189
+ operationId: getExperiment
190
+ summary: Get one experiment
191
+ description: |-
192
+ Returns the full experiment row including groups, params, allocation, and lifecycle timestamps.
193
+
194
+ **Use case:** Fetch one experiment to render the detail page or to inspect its current allocation and group weights.
195
+ tags:
196
+ - Experiments
197
+ parameters:
198
+ - $ref: ../components/parameters.yaml#/ProjectId
199
+ - name: id
200
+ in: path
201
+ required: true
202
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
203
+ schema:
204
+ type: string
205
+ responses:
206
+ "200":
207
+ description: Get one experiment
208
+ content:
209
+ application/json:
210
+ schema:
211
+ $ref: ../components/schemas/experiments.yaml#/GetExperimentResponse
212
+ example:
213
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
214
+ name: checkout_button_color
215
+ description: Test green vs. blue CTA on the checkout page.
216
+ tag: checkout
217
+ status: running
218
+ universe: primary_users
219
+ targetingGate: null
220
+ allocationPct: 5000
221
+ salt: 8d3e9a1f6b7c4a5fa1c2b6d3e7c8e3a1
222
+ params:
223
+ cta_color: string
224
+ groups:
225
+ - name: control
226
+ weight: 5000
227
+ params:
228
+ cta_color: blue
229
+ - name: treatment
230
+ weight: 5000
231
+ params:
232
+ cta_color: green
233
+ significanceThreshold: 0.05
234
+ minRuntimeDays: 7
235
+ minSampleSize: 1000
236
+ sequentialTesting: false
237
+ startedAt: 2026-05-01T12:00:00.000Z
238
+ stoppedAt: null
239
+ updatedAt: 2026-05-09T18:22:11.000Z
240
+ "400":
241
+ $ref: ../components/responses.yaml#/BadRequest
242
+ "401":
243
+ $ref: ../components/responses.yaml#/Unauthorized
244
+ "403":
245
+ $ref: ../components/responses.yaml#/Forbidden
246
+ "404":
247
+ $ref: ../components/responses.yaml#/NotFound
248
+ "409":
249
+ $ref: ../components/responses.yaml#/Conflict
250
+ "422":
251
+ $ref: ../components/responses.yaml#/UnprocessableEntity
252
+ x-error-codes:
253
+ - BAD_REQUEST
254
+ - UNAUTHORIZED
255
+ - FORBIDDEN
256
+ - NOT_FOUND
257
+ x-cli:
258
+ name: get
259
+ positional:
260
+ - id
261
+ patch:
262
+ operationId: updateExperiment
263
+ summary: Update an experiment
264
+ description: |-
265
+ Partial update. `allocation_pct`, `groups`, `salt`, `universe`, `params` are **immutable while running** — returns `409` if you try. Stop the experiment first.
266
+
267
+ Editing `groups` while in `draft` is fine; weights must still sum to 10000.
268
+
269
+ **Use cases**
270
+
271
+ - **Update metadata** — `description`, `tag`, `targeting_gate` editable any time.
272
+ - **Ramp before launch** — set `allocation_pct` while still in `draft`.
273
+ - **Tighten significance** — `significance_threshold` (Pro+).
274
+ - **Rewire groups** — replace `groups` wholesale while in `draft`; immutable once running.
275
+ tags:
276
+ - Experiments
277
+ parameters:
278
+ - $ref: ../components/parameters.yaml#/ProjectId
279
+ - name: id
280
+ in: path
281
+ required: true
282
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
283
+ schema:
284
+ type: string
285
+ requestBody:
286
+ required: true
287
+ content:
288
+ application/json:
289
+ schema:
290
+ $ref: ../components/schemas/experiments.yaml#/UpdateExperimentRequest
291
+ examples:
292
+ rampAllocation:
293
+ summary: Ramp allocation — 0 → 50%
294
+ description: Bumps the share of the targeted audience enrolled. Allowed only when the experiment is in `draft`.
295
+ value:
296
+ allocation_pct: 5000
297
+ changeWeights:
298
+ summary: Change group weights
299
+ description: Replace the groups array — weights must still sum to 10000.
300
+ value:
301
+ groups:
302
+ - name: control
303
+ weight: 2500
304
+ - name: treatment
305
+ weight: 7500
306
+ tighterSignificance:
307
+ summary: Tighter significance threshold
308
+ description: Drop the p-value cutoff from 0.05 → 0.01. Requires Pro plan or higher.
309
+ value:
310
+ significance_threshold: 0.01
311
+ updateMetadata:
312
+ summary: Update metadata
313
+ description: Change description/tag/targeting_gate freely on running experiments.
314
+ value:
315
+ description: Bumped to 50% after passing canary on 25%.
316
+ tag: checkout
317
+ responses:
318
+ "200":
319
+ description: Update an experiment
320
+ content:
321
+ application/json:
322
+ schema:
323
+ $ref: ../components/schemas/experiments.yaml#/UpdateExperimentResponse
324
+ example:
325
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
326
+ "400":
327
+ $ref: ../components/responses.yaml#/BadRequest
328
+ "401":
329
+ $ref: ../components/responses.yaml#/Unauthorized
330
+ "403":
331
+ $ref: ../components/responses.yaml#/Forbidden
332
+ "404":
333
+ $ref: ../components/responses.yaml#/NotFound
334
+ "409":
335
+ $ref: ../components/responses.yaml#/Conflict
336
+ "422":
337
+ $ref: ../components/responses.yaml#/UnprocessableEntity
338
+ x-error-codes:
339
+ - BAD_REQUEST
340
+ - UNAUTHORIZED
341
+ - FORBIDDEN
342
+ - PLAN_REQUIRED
343
+ - NOT_FOUND
344
+ - IMMUTABLE_FIELD
345
+ - INVALID_TRANSITION
346
+ - GROUPS_WEIGHT_SUM
347
+ - REFERENCED_NOT_FOUND
348
+ - VALIDATION
349
+ x-cli:
350
+ name: update
351
+ positional:
352
+ - id
353
+ delete:
354
+ operationId: deleteExperiment
355
+ summary: Delete an experiment
356
+ description: |-
357
+ Archives the experiment (soft-delete via status transition). Returns `409` if the experiment is still `running` — stop it first.
358
+
359
+ **Use case:** Tear down an experiment after the analysis is signed off.
360
+ tags:
361
+ - Experiments
362
+ parameters:
363
+ - $ref: ../components/parameters.yaml#/ProjectId
364
+ - name: id
365
+ in: path
366
+ required: true
367
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
368
+ schema:
369
+ type: string
370
+ responses:
371
+ "200":
372
+ description: Delete an experiment
373
+ content:
374
+ application/json:
375
+ schema:
376
+ $ref: ../components/schemas/experiments.yaml#/DeleteExperimentResponse
377
+ example:
378
+ ok: true
379
+ "400":
380
+ $ref: ../components/responses.yaml#/BadRequest
381
+ "401":
382
+ $ref: ../components/responses.yaml#/Unauthorized
383
+ "403":
384
+ $ref: ../components/responses.yaml#/Forbidden
385
+ "404":
386
+ $ref: ../components/responses.yaml#/NotFound
387
+ "409":
388
+ $ref: ../components/responses.yaml#/Conflict
389
+ "422":
390
+ $ref: ../components/responses.yaml#/UnprocessableEntity
391
+ x-error-codes:
392
+ - BAD_REQUEST
393
+ - UNAUTHORIZED
394
+ - FORBIDDEN
395
+ - NOT_FOUND
396
+ - INVALID_TRANSITION
397
+ x-cli:
398
+ name: archive
399
+ positional:
400
+ - id
401
+ /api/admin/experiments/{id}/status:
402
+ post:
403
+ operationId: setExperimentStatus
404
+ summary: Transition experiment status
405
+ description: |-
406
+ Drives the experiment lifecycle. Allowed transitions:
407
+
408
+ - `draft → running` — starts allocation. Bumps the `startedAt` timestamp.
409
+ - `running → stopped` — halts allocation. Existing exposures stay in the dataset.
410
+ - `stopped → archived` — soft-delete.
411
+ - `draft → archived` — discard an unstarted experiment.
412
+ - `archived → draft` — restore a soft-deleted experiment so it can be re-completed and started. Allowed only if it never started; one that already ran must be cloned instead.
413
+
414
+ Restarting an `archived` experiment directly is not allowed — restore it to `draft` first. Returns `409` on illegal transitions and `429` if the plan's `experiments_running` limit is exceeded on `→ running`.
415
+
416
+ **Use cases**
417
+
418
+ - **Start** — `{ "status": "running" }` after wiring up the SDK and verifying targeting on staging.
419
+ - **Stop** — `{ "status": "stopped" }` once the experiment hits its `min_runtime_days` and conclusive results land.
420
+ - **Archive** — `{ "status": "archived" }` to soft-delete after sign-off.
421
+ tags:
422
+ - Experiments
423
+ parameters:
424
+ - $ref: ../components/parameters.yaml#/ProjectId
425
+ - name: id
426
+ in: path
427
+ required: true
428
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
429
+ schema:
430
+ type: string
431
+ requestBody:
432
+ required: true
433
+ content:
434
+ application/json:
435
+ schema:
436
+ $ref: ../components/schemas/experiments.yaml#/SetExperimentStatusRequest
437
+ examples:
438
+ start:
439
+ summary: Start — draft → running
440
+ description: Begins allocation. The experiment counts against the plan's `experiments_running` limit.
441
+ value:
442
+ status: running
443
+ stop:
444
+ summary: Stop — running → stopped
445
+ description: Halts allocation. Existing exposures remain analysable.
446
+ value:
447
+ status: stopped
448
+ archive:
449
+ summary: Archive — stopped → archived
450
+ description: Soft-deletes the experiment. List endpoints exclude archived rows by default.
451
+ value:
452
+ status: archived
453
+ restore:
454
+ summary: Restore — archived → draft
455
+ description: Un-deletes a soft-deleted experiment so it can be re-completed and started. Allowed only if it never ran.
456
+ value:
457
+ status: draft
458
+ responses:
459
+ "201":
460
+ description: Transition experiment status
461
+ content:
462
+ application/json:
463
+ schema:
464
+ $ref: ../components/schemas/experiments.yaml#/SetExperimentStatusResponse
465
+ example:
466
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
467
+ status: running
468
+ "400":
469
+ $ref: ../components/responses.yaml#/BadRequest
470
+ "401":
471
+ $ref: ../components/responses.yaml#/Unauthorized
472
+ "403":
473
+ $ref: ../components/responses.yaml#/Forbidden
474
+ "404":
475
+ $ref: ../components/responses.yaml#/NotFound
476
+ "409":
477
+ $ref: ../components/responses.yaml#/Conflict
478
+ "422":
479
+ $ref: ../components/responses.yaml#/UnprocessableEntity
480
+ x-error-codes:
481
+ - BAD_REQUEST
482
+ - UNAUTHORIZED
483
+ - FORBIDDEN
484
+ - NOT_FOUND
485
+ - INVALID_TRANSITION
486
+ - VALIDATION
487
+ x-cli:
488
+ positional:
489
+ - id
490
+ commands:
491
+ - name: start
492
+ summary: Start an experiment (draft → running)
493
+ preset:
494
+ status: running
495
+ - name: stop
496
+ summary: Stop a running experiment
497
+ preset:
498
+ status: stopped
499
+ - name: restore
500
+ summary: Restore an archived experiment (→ draft)
501
+ preset:
502
+ status: draft
503
+ /api/admin/experiments/{id}/metrics:
504
+ post:
505
+ operationId: setExperimentMetrics
506
+ summary: Attach metrics
507
+ description: |-
508
+ Replaces the experiment's metric attachments wholesale. Each entry pairs an existing `metric_id` with a `role` (`goal` / `guardrail` / `secondary`).
509
+
510
+ Returns `422` if any `metric_id` doesn't exist in the project. Pass `{ metrics: [] }` to detach everything.
511
+
512
+ **Use cases**
513
+
514
+ - **Standard setup** — one `goal`, one or two `guardrail`, optional `secondary` metrics for diagnostics.
515
+ - **Detach all** — send `{ "metrics": [] }` before archiving.
516
+ tags:
517
+ - Experiments
518
+ parameters:
519
+ - $ref: ../components/parameters.yaml#/ProjectId
520
+ - name: id
521
+ in: path
522
+ required: true
523
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
524
+ schema:
525
+ type: string
526
+ requestBody:
527
+ required: true
528
+ content:
529
+ application/json:
530
+ schema:
531
+ $ref: ../components/schemas/experiments.yaml#/SetExperimentMetricsRequest
532
+ examples:
533
+ standard:
534
+ summary: Standard — one goal + one guardrail
535
+ description: Attaches one decision metric and one safety metric.
536
+ value:
537
+ metrics:
538
+ - metric_id: met_checkout_completed
539
+ role: goal
540
+ - metric_id: met_page_errors
541
+ role: guardrail
542
+ detach:
543
+ summary: Detach all
544
+ description: Send an empty array to clear every metric.
545
+ value:
546
+ metrics: []
547
+ responses:
548
+ "201":
549
+ description: Attach metrics
550
+ content:
551
+ application/json:
552
+ schema:
553
+ $ref: ../components/schemas/experiments.yaml#/SetExperimentMetricsResponse
554
+ example:
555
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
556
+ metrics:
557
+ - metric_id: met_checkout_completed
558
+ role: goal
559
+ - metric_id: met_page_errors
560
+ role: guardrail
561
+ "400":
562
+ $ref: ../components/responses.yaml#/BadRequest
563
+ "401":
564
+ $ref: ../components/responses.yaml#/Unauthorized
565
+ "403":
566
+ $ref: ../components/responses.yaml#/Forbidden
567
+ "404":
568
+ $ref: ../components/responses.yaml#/NotFound
569
+ "409":
570
+ $ref: ../components/responses.yaml#/Conflict
571
+ "422":
572
+ $ref: ../components/responses.yaml#/UnprocessableEntity
573
+ x-error-codes:
574
+ - BAD_REQUEST
575
+ - UNAUTHORIZED
576
+ - FORBIDDEN
577
+ - NOT_FOUND
578
+ - EVENT_PENDING
579
+ - REFERENCED_NOT_FOUND
580
+ - VALIDATION
581
+ x-cli:
582
+ name: set-metrics
583
+ positional:
584
+ - id
585
+ /api/admin/experiments/{id}/results:
586
+ get:
587
+ operationId: getExperimentResults
588
+ summary: Get analysis results
589
+ description: |-
590
+ Returns the latest analysis output for the experiment — one row per metric/group/day, including sample size, mean, % delta vs. control, p-value, and a sample-ratio mismatch flag.
591
+
592
+ **Use case:** Render the results table on the experiment detail page or drive an automated decision once a `goal` metric reaches significance.
593
+ tags:
594
+ - Experiments
595
+ parameters:
596
+ - $ref: ../components/parameters.yaml#/ProjectId
597
+ - name: id
598
+ in: path
599
+ required: true
600
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
601
+ schema:
602
+ type: string
603
+ responses:
604
+ "200":
605
+ description: Get analysis results
606
+ content:
607
+ application/json:
608
+ schema:
609
+ $ref: ../components/schemas/experiments.yaml#/GetExperimentResultsResponse
610
+ example:
611
+ experiment:
612
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
613
+ name: checkout_button_color
614
+ status: running
615
+ results:
616
+ - metric: checkout_completed
617
+ group_name: control
618
+ ds: 2026-05-09
619
+ n: 12421
620
+ mean: 0.1834
621
+ delta_pct: null
622
+ p_value: null
623
+ srm_detected: 0
624
+ - metric: checkout_completed
625
+ group_name: treatment
626
+ ds: 2026-05-09
627
+ n: 12519
628
+ mean: 0.1922
629
+ delta_pct: 4.8
630
+ p_value: 0.018
631
+ srm_detected: 0
632
+ verdict: ship
633
+ "400":
634
+ $ref: ../components/responses.yaml#/BadRequest
635
+ "401":
636
+ $ref: ../components/responses.yaml#/Unauthorized
637
+ "403":
638
+ $ref: ../components/responses.yaml#/Forbidden
639
+ "404":
640
+ $ref: ../components/responses.yaml#/NotFound
641
+ "409":
642
+ $ref: ../components/responses.yaml#/Conflict
643
+ "422":
644
+ $ref: ../components/responses.yaml#/UnprocessableEntity
645
+ x-error-codes:
646
+ - BAD_REQUEST
647
+ - UNAUTHORIZED
648
+ - FORBIDDEN
649
+ - NOT_FOUND
650
+ x-cli:
651
+ name: results
652
+ positional:
653
+ - id
654
+ /api/admin/experiments/{id}/timeseries:
655
+ get:
656
+ operationId: getExperimentTimeseries
657
+ summary: Get analysis timeseries
658
+ description: |-
659
+ Same row shape as `/results`, but returns every daily slice rather than the latest. Filter to a single metric with the `metric` query parameter.
660
+
661
+ **Use case:** Drive a chart of metric movement over the experiment runtime, or sanity-check the lift is monotonic before deciding.
662
+ tags:
663
+ - Experiments
664
+ parameters:
665
+ - $ref: ../components/parameters.yaml#/ProjectId
666
+ - name: id
667
+ in: path
668
+ required: true
669
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
670
+ schema:
671
+ type: string
672
+ - name: metric
673
+ in: query
674
+ required: false
675
+ description: Optional metric name to filter the series.
676
+ schema:
677
+ type: string
678
+ responses:
679
+ "200":
680
+ description: Get analysis timeseries
681
+ content:
682
+ application/json:
683
+ schema:
684
+ $ref: ../components/schemas/experiments.yaml#/GetExperimentTimeseriesResponse
685
+ example:
686
+ experiment:
687
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
688
+ name: checkout_button_color
689
+ status: running
690
+ series:
691
+ - metric: checkout_completed
692
+ group_name: treatment
693
+ ds: 2026-05-08
694
+ n: 11200
695
+ mean: 0.1903
696
+ delta_pct: 3.9
697
+ p_value: 0.034
698
+ srm_detected: 0
699
+ - metric: checkout_completed
700
+ group_name: treatment
701
+ ds: 2026-05-09
702
+ n: 12519
703
+ mean: 0.1922
704
+ delta_pct: 4.8
705
+ p_value: 0.018
706
+ srm_detected: 0
707
+ "400":
708
+ $ref: ../components/responses.yaml#/BadRequest
709
+ "401":
710
+ $ref: ../components/responses.yaml#/Unauthorized
711
+ "403":
712
+ $ref: ../components/responses.yaml#/Forbidden
713
+ "404":
714
+ $ref: ../components/responses.yaml#/NotFound
715
+ "409":
716
+ $ref: ../components/responses.yaml#/Conflict
717
+ "422":
718
+ $ref: ../components/responses.yaml#/UnprocessableEntity
719
+ x-error-codes:
720
+ - BAD_REQUEST
721
+ - UNAUTHORIZED
722
+ - FORBIDDEN
723
+ - NOT_FOUND
724
+ x-cli:
725
+ name: timeseries
726
+ positional:
727
+ - id
728
+ /api/admin/experiments/{id}/reanalyze:
729
+ post:
730
+ operationId: reanalyzeExperiment
731
+ summary: Re-queue analysis
732
+ description: |-
733
+ Requeues the daily analysis pass for this experiment outside the normal cron cadence. Useful after attaching a new metric or correcting an event taxonomy. The job runs asynchronously.
734
+
735
+ **Use case:** Force-refresh results after wiring up a new metric without waiting for the next nightly cron tick.
736
+ tags:
737
+ - Experiments
738
+ parameters:
739
+ - $ref: ../components/parameters.yaml#/ProjectId
740
+ - name: id
741
+ in: path
742
+ required: true
743
+ description: Stable opaque experiment id (`exp_…`) or the experiment's `name`.
744
+ schema:
745
+ type: string
746
+ responses:
747
+ "201":
748
+ description: Re-queue analysis
749
+ content:
750
+ application/json:
751
+ schema:
752
+ $ref: ../components/schemas/experiments.yaml#/ReanalyzeExperimentResponse
753
+ example:
754
+ id: exp_01j7wb12c3d4e5f6g7h8j9k0l1
755
+ queued: true
756
+ "400":
757
+ $ref: ../components/responses.yaml#/BadRequest
758
+ "401":
759
+ $ref: ../components/responses.yaml#/Unauthorized
760
+ "403":
761
+ $ref: ../components/responses.yaml#/Forbidden
762
+ "404":
763
+ $ref: ../components/responses.yaml#/NotFound
764
+ "409":
765
+ $ref: ../components/responses.yaml#/Conflict
766
+ "422":
767
+ $ref: ../components/responses.yaml#/UnprocessableEntity
768
+ x-error-codes:
769
+ - BAD_REQUEST
770
+ - UNAUTHORIZED
771
+ - FORBIDDEN
772
+ - NOT_FOUND
773
+ - VALIDATION
774
+ x-cli:
775
+ name: reanalyze
776
+ positional:
777
+ - id