@browserstack/mcp-server 1.5.0-beta.24 → 1.5.0-beta.26

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.
@@ -28,7 +28,21 @@
28
28
  ],
29
29
  "responses": {
30
30
  "200": {
31
- "$response": "Success"
31
+ "description": "Standard success envelope; operation data under `data`.",
32
+ "schema": {
33
+ "allOf": [
34
+ {
35
+ "$schema": "SuccessEnvelope"
36
+ },
37
+ {
38
+ "properties": {
39
+ "data": {
40
+ "$schema": "GetLoadTestPlatformStatusData"
41
+ }
42
+ }
43
+ }
44
+ ]
45
+ }
32
46
  },
33
47
  "400": {
34
48
  "$response": "BadRequest"
@@ -51,7 +65,9 @@
51
65
  {
52
66
  "name": "limit",
53
67
  "type": "integer",
54
- "description": "Max items to return (1-100, default 50)."
68
+ "description": "Max items to return (1-100, default 50).",
69
+ "minimum": 1,
70
+ "maximum": 100
55
71
  },
56
72
  {
57
73
  "name": "cursor",
@@ -85,7 +101,21 @@
85
101
  ],
86
102
  "responses": {
87
103
  "200": {
88
- "$response": "Success"
104
+ "description": "Standard success envelope; operation data under `data`.",
105
+ "schema": {
106
+ "allOf": [
107
+ {
108
+ "$schema": "SuccessEnvelope"
109
+ },
110
+ {
111
+ "properties": {
112
+ "data": {
113
+ "$schema": "ListLoadTestProjectsData"
114
+ }
115
+ }
116
+ }
117
+ ]
118
+ }
89
119
  },
90
120
  "400": {
91
121
  "$response": "BadRequest"
@@ -117,7 +147,9 @@
117
147
  {
118
148
  "name": "limit",
119
149
  "type": "integer",
120
- "description": "Max items to return (1-100, default 50)."
150
+ "description": "Max items to return (1-100, default 50).",
151
+ "minimum": 1,
152
+ "maximum": 100
121
153
  },
122
154
  {
123
155
  "name": "cursor",
@@ -158,7 +190,7 @@
158
190
  {
159
191
  "name": "updatedSince",
160
192
  "type": "string",
161
- "description": "ISO-8601 timestamp; only tests updated after it.",
193
+ "description": "ISO-8601 timestamp; only tests updated after it. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
162
194
  "example": "2026-08-01T00:00:00Z"
163
195
  }
164
196
  ],
@@ -177,7 +209,21 @@
177
209
  ],
178
210
  "responses": {
179
211
  "200": {
180
- "$response": "Success"
212
+ "description": "Standard success envelope; operation data under `data`.",
213
+ "schema": {
214
+ "allOf": [
215
+ {
216
+ "$schema": "SuccessEnvelope"
217
+ },
218
+ {
219
+ "properties": {
220
+ "data": {
221
+ "$schema": "ListLoadTestsData"
222
+ }
223
+ }
224
+ }
225
+ ]
226
+ }
181
227
  },
182
228
  "400": {
183
229
  "$response": "BadRequest"
@@ -205,19 +251,23 @@
205
251
  {
206
252
  "name": "name",
207
253
  "type": "string",
208
- "description": "Test name to search for (substring match, case-insensitive); required."
254
+ "description": "Test name to search for (substring match, case-insensitive); required.",
255
+ "example": "checkout"
209
256
  },
210
257
  {
211
258
  "name": "limit",
212
259
  "type": "integer",
213
- "description": "Max items to return (1-100, default 50)."
260
+ "description": "Max items to return (1-100, default 50).",
261
+ "minimum": 1,
262
+ "maximum": 100
214
263
  }
215
264
  ],
216
265
  "intent": "Find a load test by name across ALL of the caller's projects — use this to resolve a named test to a testId without knowing which project it is in.",
217
266
  "guidance": [
218
267
  "Group-scoped: unlike listLoadTests it needs no projectId. Prefer it to resolve a named test in one call instead of paging every project.",
219
268
  "Each row carries testId, projectId, name, testType and framework — disambiguate same-named tests in different projects by projectId.",
220
- "Returns one row per test (its latest version); the numeric testId is what getLoadTest and startLoadTestRun need."
269
+ "Returns one row per test (its latest version); the numeric testId is what getLoadTest and startLoadTestRun need.",
270
+ "hasMore:true means more matches exist beyond the returned limit — there is NO cursor and no page 2; narrow the name query or raise limit to surface them (results are the top matches, not a paginated list)."
221
271
  ],
222
272
  "returns": [
223
273
  "tests",
@@ -225,7 +275,21 @@
225
275
  ],
226
276
  "responses": {
227
277
  "200": {
228
- "$response": "Success"
278
+ "description": "Standard success envelope; operation data under `data`.",
279
+ "schema": {
280
+ "allOf": [
281
+ {
282
+ "$schema": "SuccessEnvelope"
283
+ },
284
+ {
285
+ "properties": {
286
+ "data": {
287
+ "$schema": "SearchLoadTestsData"
288
+ }
289
+ }
290
+ }
291
+ ]
292
+ }
229
293
  },
230
294
  "400": {
231
295
  "$response": "BadRequest"
@@ -283,13 +347,14 @@
283
347
  {
284
348
  "name": "sinceIso",
285
349
  "type": "string",
286
- "description": "ISO-8601 lower bound.",
350
+ "description": "ISO-8601 lower bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
287
351
  "example": "2026-08-01T00:00:00Z"
288
352
  },
289
353
  {
290
354
  "name": "untilIso",
291
355
  "type": "string",
292
- "description": "ISO-8601 upper bound."
356
+ "description": "ISO-8601 upper bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
357
+ "example": "2026-09-12"
293
358
  }
294
359
  ],
295
360
  "intent": "Show how a project's load-test metrics trend across recent runs — use this for 'is performance getting better or worse across this project?'",
@@ -303,7 +368,21 @@
303
368
  ],
304
369
  "responses": {
305
370
  "200": {
306
- "$response": "Success"
371
+ "description": "Standard success envelope; operation data under `data`.",
372
+ "schema": {
373
+ "allOf": [
374
+ {
375
+ "$schema": "SuccessEnvelope"
376
+ },
377
+ {
378
+ "properties": {
379
+ "data": {
380
+ "$schema": "GetLoadTestProjectTrendsData"
381
+ }
382
+ }
383
+ }
384
+ ]
385
+ }
307
386
  },
308
387
  "400": {
309
388
  "$response": "BadRequest"
@@ -336,7 +415,9 @@
336
415
  {
337
416
  "name": "limit",
338
417
  "type": "integer",
339
- "description": "Max items to return (1-100, default 50)."
418
+ "description": "Max items to return (1-100, default 50).",
419
+ "minimum": 1,
420
+ "maximum": 100
340
421
  },
341
422
  {
342
423
  "name": "cursor",
@@ -371,13 +452,14 @@
371
452
  {
372
453
  "name": "sinceIso",
373
454
  "type": "string",
374
- "description": "ISO-8601 lower bound.",
455
+ "description": "ISO-8601 lower bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
375
456
  "example": "2026-08-01T00:00:00Z"
376
457
  },
377
458
  {
378
459
  "name": "untilIso",
379
460
  "type": "string",
380
- "description": "ISO-8601 upper bound."
461
+ "description": "ISO-8601 upper bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
462
+ "example": "2026-09-12"
381
463
  },
382
464
  {
383
465
  "name": "hadSlaBreach",
@@ -390,7 +472,7 @@
390
472
  "description": "Filter to runs carrying this tag (a run's own tags, or the tags it inherits from its test when it has none of its own)."
391
473
  }
392
474
  ],
393
- "intent": "List the execution history across every load test in a project — newest first, paginated. Use for 'what ran last week in this project?' or to find runs across tests to compare.",
475
+ "intent": "List the execution history across every load test in a project — newest first, paginated. Use for 'what ran last week in this project?'.",
394
476
  "guidance": [
395
477
  "Returns run metadata only, not metrics — use getLoadTestRunReport for a run's KPIs.",
396
478
  "Each run carries a tags array — its own run-level tags if set (via updateLoadTest with runId), otherwise the tags inherited from its test. Filter with the tag query param.",
@@ -405,7 +487,21 @@
405
487
  ],
406
488
  "responses": {
407
489
  "200": {
408
- "$response": "Success"
490
+ "description": "Standard success envelope; operation data under `data`.",
491
+ "schema": {
492
+ "allOf": [
493
+ {
494
+ "$schema": "SuccessEnvelope"
495
+ },
496
+ {
497
+ "properties": {
498
+ "data": {
499
+ "$schema": "ListProjectLoadTestRunsData"
500
+ }
501
+ }
502
+ }
503
+ ]
504
+ }
409
505
  },
410
506
  "400": {
411
507
  "$response": "BadRequest"
@@ -433,7 +529,9 @@
433
529
  {
434
530
  "name": "limit",
435
531
  "type": "integer",
436
- "description": "Max items to return (1-200, default 50)."
532
+ "description": "Max items to return (1-200, default 50).",
533
+ "minimum": 1,
534
+ "maximum": 200
437
535
  },
438
536
  {
439
537
  "name": "minElapsedSec",
@@ -468,7 +566,21 @@
468
566
  ],
469
567
  "responses": {
470
568
  "200": {
471
- "$response": "Success"
569
+ "description": "Standard success envelope; operation data under `data`.",
570
+ "schema": {
571
+ "allOf": [
572
+ {
573
+ "$schema": "SuccessEnvelope"
574
+ },
575
+ {
576
+ "properties": {
577
+ "data": {
578
+ "$schema": "ListActiveLoadTestRunsData"
579
+ }
580
+ }
581
+ }
582
+ ]
583
+ }
472
584
  },
473
585
  "400": {
474
586
  "$response": "BadRequest"
@@ -519,7 +631,21 @@
519
631
  ],
520
632
  "responses": {
521
633
  "200": {
522
- "$response": "Success"
634
+ "description": "Standard success envelope; operation data under `data`.",
635
+ "schema": {
636
+ "allOf": [
637
+ {
638
+ "$schema": "SuccessEnvelope"
639
+ },
640
+ {
641
+ "properties": {
642
+ "data": {
643
+ "$schema": "GetLoadTestRunStatusData"
644
+ }
645
+ }
646
+ }
647
+ ]
648
+ }
523
649
  },
524
650
  "400": {
525
651
  "$response": "BadRequest"
@@ -575,7 +701,21 @@
575
701
  ],
576
702
  "responses": {
577
703
  "200": {
578
- "$response": "Success"
704
+ "description": "Standard success envelope; operation data under `data`.",
705
+ "schema": {
706
+ "allOf": [
707
+ {
708
+ "$schema": "SuccessEnvelope"
709
+ },
710
+ {
711
+ "properties": {
712
+ "data": {
713
+ "$schema": "GetLoadTestInsightSummaryData"
714
+ }
715
+ }
716
+ }
717
+ ]
718
+ }
579
719
  },
580
720
  "400": {
581
721
  "$response": "BadRequest"
@@ -667,12 +807,14 @@
667
807
  {
668
808
  "name": "sinceIso",
669
809
  "type": "string",
670
- "description": "ISO-8601 lower bound; slices the report to data in this time window."
810
+ "description": "ISO-8601 lower bound; slices the report to data in this time window. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
811
+ "example": "2026-09-12"
671
812
  },
672
813
  {
673
814
  "name": "untilIso",
674
815
  "type": "string",
675
- "description": "ISO-8601 upper bound for the time-window slice."
816
+ "description": "ISO-8601 upper bound for the time-window slice. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
817
+ "example": "2026-09-12"
676
818
  }
677
819
  ],
678
820
  "intent": "Get the full metrics report for a completed run — KPIs, SLA verdicts, per-transaction and error breakdowns. Use this to answer 'how did this run perform?'",
@@ -683,7 +825,8 @@
683
825
  "metrics accepts dotted names or @ aliases; see getLoadTestMetricsManifest for what applies to this test type.",
684
826
  "Answer a scoped question with the narrowest slice instead of the whole report: one metric → metrics=; error breakdown → errorCategory= (or slaOnly=true); a time window → sinceIso/untilIso; slowest transaction → detail=per-txn with groupBy=transaction and topN.",
685
827
  "One call with the right params returns everything for that question — do not re-fetch the same run with the same params. Fetch the full report (view=full / detail=full) only when the user explicitly asks for the raw or complete report.",
686
- "A plain 'summarize this run' / 'give me a summary' request is answered by getLoadTestInsightSummary, NOT this endpoint. Only call this when the user asks for specific KPIs, SLA verdicts, web vitals, transactions, or the raw/complete report."
828
+ "A plain 'summarize this run' / 'give me a summary' request is answered by getLoadTestInsightSummary, NOT this endpoint. Only call this when the user asks for specific KPIs, SLA verdicts, web vitals, transactions, or the raw/complete report.",
829
+ "durationSec is the run's wall-clock length in WHOLE SECONDS. When presenting it to the user, render it as minutes and seconds (e.g. 330 -> '5m 30s', 90 -> '1m 30s', 45 -> '45s'), not as a raw seconds count; keep the raw seconds only for calculations."
687
830
  ],
688
831
  "returns": [
689
832
  "runId",
@@ -699,7 +842,21 @@
699
842
  ],
700
843
  "responses": {
701
844
  "200": {
702
- "$response": "Success"
845
+ "description": "Standard success envelope; operation data under `data`.",
846
+ "schema": {
847
+ "allOf": [
848
+ {
849
+ "$schema": "SuccessEnvelope"
850
+ },
851
+ {
852
+ "properties": {
853
+ "data": {
854
+ "$schema": "GetLoadTestRunReportData"
855
+ }
856
+ }
857
+ }
858
+ ]
859
+ }
703
860
  },
704
861
  "400": {
705
862
  "$response": "BadRequest"
@@ -741,7 +898,21 @@
741
898
  ],
742
899
  "responses": {
743
900
  "200": {
744
- "$response": "Success"
901
+ "description": "Standard success envelope; operation data under `data`.",
902
+ "schema": {
903
+ "allOf": [
904
+ {
905
+ "$schema": "SuccessEnvelope"
906
+ },
907
+ {
908
+ "properties": {
909
+ "data": {
910
+ "$schema": "StopLoadTestRunData"
911
+ }
912
+ }
913
+ }
914
+ ]
915
+ }
745
916
  },
746
917
  "400": {
747
918
  "$response": "BadRequest"
@@ -775,7 +946,21 @@
775
946
  ],
776
947
  "responses": {
777
948
  "200": {
778
- "$response": "Success"
949
+ "description": "Standard success envelope; operation data under `data`.",
950
+ "schema": {
951
+ "allOf": [
952
+ {
953
+ "$schema": "SuccessEnvelope"
954
+ },
955
+ {
956
+ "properties": {
957
+ "data": {
958
+ "$schema": "GetLoadTestQuotaData"
959
+ }
960
+ }
961
+ }
962
+ ]
963
+ }
779
964
  },
780
965
  "400": {
781
966
  "$response": "BadRequest"
@@ -799,7 +984,8 @@
799
984
  "name": "testId",
800
985
  "type": "integer",
801
986
  "required": true,
802
- "description": "The test to price."
987
+ "description": "The test to price.",
988
+ "example": 1234
803
989
  },
804
990
  {
805
991
  "name": "overrides",
@@ -836,7 +1022,21 @@
836
1022
  ],
837
1023
  "responses": {
838
1024
  "200": {
839
- "$response": "Success"
1025
+ "description": "Standard success envelope; operation data under `data`.",
1026
+ "schema": {
1027
+ "allOf": [
1028
+ {
1029
+ "$schema": "SuccessEnvelope"
1030
+ },
1031
+ {
1032
+ "properties": {
1033
+ "data": {
1034
+ "$schema": "EstimateLoadTestRunCostData"
1035
+ }
1036
+ }
1037
+ }
1038
+ ]
1039
+ }
840
1040
  },
841
1041
  "400": {
842
1042
  "$response": "BadRequest"
@@ -860,13 +1060,17 @@
860
1060
  "name": "baselineRunId",
861
1061
  "type": "string",
862
1062
  "required": true,
863
- "description": "Run UUID to compare against."
1063
+ "description": "Run UUID to compare against.",
1064
+ "format": "uuid",
1065
+ "example": "6f1d2c9a-7b3e-4a10-9c22-0e5f8a1b2c3d"
864
1066
  },
865
1067
  {
866
1068
  "name": "candidateRunId",
867
1069
  "type": "string",
868
1070
  "required": true,
869
- "description": "Run UUID being evaluated; must differ from baselineRunId."
1071
+ "description": "Run UUID being evaluated; must differ from baselineRunId.",
1072
+ "format": "uuid",
1073
+ "example": "b2e4f6a8-1c3d-4e5f-8a90-2b4c6d8e0f11"
870
1074
  },
871
1075
  {
872
1076
  "name": "dimensions",
@@ -881,12 +1085,18 @@
881
1085
  {
882
1086
  "name": "metrics",
883
1087
  "type": "string",
884
- "description": "Comma-separated dotted metric names or @ aliases (e.g. @vitals, @all). Resolve valid names via getLoadTestMetricsManifest."
1088
+ "description": "Comma-separated dotted metric names or @ aliases (e.g. latency.p95, @vitals). Filters kpiDeltas; the first entry with a per-transaction value also picks the transaction metric. Resolve valid names via getLoadTestMetricsManifest."
885
1089
  },
886
1090
  {
887
1091
  "name": "groupBy",
888
1092
  "type": "string",
889
- "description": "Rollup dimension for transaction deltas."
1093
+ "description": "Axis for transaction deltas (default transaction = request name).",
1094
+ "values": [
1095
+ "transaction",
1096
+ "label",
1097
+ "threadGroup",
1098
+ "scenario"
1099
+ ]
890
1100
  },
891
1101
  {
892
1102
  "name": "topN",
@@ -896,27 +1106,50 @@
896
1106
  {
897
1107
  "name": "regressedOnly",
898
1108
  "type": "boolean",
899
- "description": "Return only regressed rows."
1109
+ "description": "Return only regressed transaction rows."
900
1110
  },
901
1111
  {
902
1112
  "name": "pctChangeMin",
903
1113
  "type": "number",
904
- "description": "Minimum percent change to include."
1114
+ "description": "Minimum absolute percent change for a KPI or transaction row to be included."
905
1115
  }
906
1116
  ],
907
- "intent": "Compare two completed runs and surface the deltas — use this for 'did this run regress vs the baseline?'",
1117
+ "intent": "Compare two executions (runs) of the SAME load test and surface the deltas — the regression check ('did the latest run regress vs the previous one?'). Not for comparing different tests: runs of different tests are rejected (DIFFERENT_TESTS). For a trend across more than two runs use getLoadTestHistoricalTrends.",
908
1118
  "guidance": [
909
- "baselineRunId and candidateRunId are run UUIDs and must differ; both runs must be terminal.",
910
- "regressedOnly + pctChangeMin filter to material regressions; dimensions accepts kpi, transaction, sla.",
911
- "Use this to compare two runs — it returns per-KPI and per-transaction deltas directly. Do not fetch both run reports and diff them yourself."
1119
+ "Pick both runs from listLoadTestRuns for ONE testId, filtered to finished runs (status=terminal). The older run is the baseline, the newer the candidate.",
1120
+ "'Compare the latest run' means the latest finished run (candidate) vs the finished run before it (baseline).",
1121
+ "Both runs must be finished and must share the same test types — otherwise the call fails with VALIDATION_ERROR. Runs of different tests fail with DIFFERENT_TESTS; do not retry with other tests' runs.",
1122
+ "Use this to compare two runs — it returns per-KPI, per-transaction and SLA-verdict deltas from the same data as the Compare Runs page. Do not fetch both run reports and diff them yourself.",
1123
+ "pctChange is signed (candidate vs baseline); direction/regressed already account for whether higher or lower is better — report those, do not re-derive them. direction \"unknown\" (regressed null) means one or both runs have no value for that metric: report it as missing data, never as no change.",
1124
+ "Transaction deltas are computed on one metric: the first metrics entry that has a per-transaction value (latency.*, errors.rate, throughput.*), else latency.p95. groupBy picks the transaction axis.",
1125
+ "regressedOnly + pctChangeMin filter to material regressions; regressedOnly applies to transactionDeltas, pctChangeMin to kpiDeltas and transactionDeltas.",
1126
+ "Check warnings before reporting: they name metrics with no data on a run, runs whose SLA thresholds were not evaluated, SLA definitions that changed between the runs, and requested metrics compare cannot serve (e.g. engine.*). Surface any warning to the user."
912
1127
  ],
913
1128
  "returns": [
1129
+ "baseline",
1130
+ "candidate",
914
1131
  "kpiDeltas",
915
- "transactionDeltas"
1132
+ "transactionDeltas",
1133
+ "slaVerdictChanges",
1134
+ "warnings"
916
1135
  ],
917
1136
  "responses": {
918
1137
  "200": {
919
- "$response": "Success"
1138
+ "description": "Standard success envelope; operation data under `data`.",
1139
+ "schema": {
1140
+ "allOf": [
1141
+ {
1142
+ "$schema": "SuccessEnvelope"
1143
+ },
1144
+ {
1145
+ "properties": {
1146
+ "data": {
1147
+ "$schema": "CompareLoadTestRunsData"
1148
+ }
1149
+ }
1150
+ }
1151
+ ]
1152
+ }
920
1153
  },
921
1154
  "400": {
922
1155
  "$response": "BadRequest"
@@ -924,6 +1157,9 @@
924
1157
  "401": {
925
1158
  "$response": "Unauthorized"
926
1159
  },
1160
+ "404": {
1161
+ "$response": "NotFound"
1162
+ },
927
1163
  "500": {
928
1164
  "$response": "InternalServerError"
929
1165
  }
@@ -941,7 +1177,8 @@
941
1177
  "type": "string",
942
1178
  "required": true,
943
1179
  "maxLength": 255,
944
- "description": "Test name. Max 255 characters — truncate before sending; a longer name is rejected with a 400."
1180
+ "description": "Test name. Max 255 characters — truncate before sending; a longer name is rejected with a 400.",
1181
+ "example": "checkout-baseline"
945
1182
  },
946
1183
  {
947
1184
  "name": "testType",
@@ -958,7 +1195,30 @@
958
1195
  "name": "framework",
959
1196
  "type": "string",
960
1197
  "required": true,
961
- "description": "PLU (API) frameworks: k6, jmeter, gatling, locust. BLU (browser) frameworks: playwright, selenium, webdriverio, nightwatch, lcncnightwatch. Must match testType — a PLU framework for testType plu, a BLU framework for testType blu (the backend rejects a mismatched pair).",
1198
+ "description": "The framework MUST match testType (the backend rejects a mismatched pair). Offer ONLY the frameworks for the already-chosen testType — read them from valuesByTestType[testType] below — and NEVER present the full `values` list across types. API (plu): k6, jmeter, gatling, locust. Browser (blu): playwright, selenium, webdriverio, nightwatch, lcncnightwatch. For a hybrid test this top-level framework is the Browser leg; the API leg's framework goes in children[].",
1199
+ "scopedBy": "testType",
1200
+ "valuesByTestType": {
1201
+ "plu": [
1202
+ "k6",
1203
+ "jmeter",
1204
+ "gatling",
1205
+ "locust"
1206
+ ],
1207
+ "blu": [
1208
+ "playwright",
1209
+ "selenium",
1210
+ "webdriverio",
1211
+ "nightwatch",
1212
+ "lcncnightwatch"
1213
+ ],
1214
+ "hybrid": [
1215
+ "playwright",
1216
+ "selenium",
1217
+ "webdriverio",
1218
+ "nightwatch",
1219
+ "lcncnightwatch"
1220
+ ]
1221
+ },
962
1222
  "values": [
963
1223
  "k6",
964
1224
  "jmeter",
@@ -1021,7 +1281,7 @@
1021
1281
  "guidance": [
1022
1282
  "PRECONDITION — do NOT call this endpoint until THREE things are known: (1) testType (plu/blu/hybrid), (2) framework, (3) the script (a built-in sample or the user's own upload). These are MANDATORY and NOT defaultable — never infer or default them. If the user's request does not state one of the three, ASK the user for the missing ones and WAIT for their answer before creating. 'create a test' with no type/framework/script named means all three are missing → ask all three; do not silently pick k6/plu/sample. Only vus, duration, region and load profile are defaultable (see the DEFAULTS line) — the three above are not.",
1023
1283
  "'plu' / 'blu' / 'hybrid' are INTERNAL wire values — send them in the request, but NEVER show them to the user. Do not print them in questions, option labels, confirmations, summaries, or prose (no 'Browser (BLU)', no '(plu+blu)'). User-facing labels are: plu → 'API', blu → 'Browser', hybrid → 'Hybrid (both API and Browser)'. Frameworks (k6, jmeter, selenium, playwright, …) are real product names and ARE shown to the user.",
1024
- "When you ASK the user to pick testType or framework, present the FULL, exact option set — never drop, merge, or cross-contaminate options. testType: offer all THREE, using the user-facing labels above — 'API', 'Browser', and 'Hybrid'; do not omit Hybrid. framework (ask AFTER testType is chosen, and show only that type's frameworks, each as its OWN separate option): for an API test offer exactly k6, jmeter, gatling AND locust (all four — do not drop locust); for a Browser test offer exactly playwright, selenium, webdriverio AND nightwatch (all four — never list the API frameworks under a Browser test, and never merge selenium and playwright into one option). For a Hybrid test, collect an API leg (its framework + script) AND a Browser leg (its framework + script) and assemble them per the children field — Hybrid needs both legs, so it takes more than the three questions a single-type test does.",
1284
+ "When you ASK the user to pick testType or framework, present the FULL, exact option set — never drop, merge, or cross-contaminate options. testType: offer all THREE, using the user-facing labels above — 'API', 'Browser', and 'Hybrid'; do not omit Hybrid. framework (ask AFTER testType is chosen, and show only that type's frameworks — the authoritative per-type list is the `framework.valuesByTestType[testType]` array; present exactly those, each as its OWN separate option, and NEVER the full cross-type `values` list): for an API test offer exactly k6, jmeter, gatling AND locust (all four — do not drop locust); for a Browser test offer exactly playwright, selenium, webdriverio AND nightwatch (all four — never list the API frameworks under a Browser test, and never merge selenium and playwright into one option). For a Hybrid test, collect an API leg (its framework + script) AND a Browser leg (its framework + script) and assemble them per the children field — Hybrid needs both legs, so it takes more than the three questions a single-type test does.",
1025
1285
  "Provide exactly one of projectId or projectName; projectName creates the project if absent.",
1026
1286
  "Script upload is two-phase: send pendingScriptUpload to get a presigned uploadUrl + s3Key, PUT the file, then call create again with the scriptRef source and s3Key returned in the response's nextStep.",
1027
1287
  "To spin up a test from a built-in sample with NO file handling (the dashboard's 'use sample script'), pass scriptRef:{source:'sample'} — the platform's bundled sample for the given framework is used. For Selenium, also pass scriptRef.subType (testng|junit|vanillajava|python|pytest|jest|serenity-cucumber) to pick the binding. testType and framework are still needed; the load profile defaults to constant 1 VU / 30s (see below).",
@@ -1043,7 +1303,21 @@
1043
1303
  ],
1044
1304
  "responses": {
1045
1305
  "200": {
1046
- "$response": "Success"
1306
+ "description": "Standard success envelope; operation data under `data`.",
1307
+ "schema": {
1308
+ "allOf": [
1309
+ {
1310
+ "$schema": "SuccessEnvelope"
1311
+ },
1312
+ {
1313
+ "properties": {
1314
+ "data": {
1315
+ "$schema": "CreateLoadTestData"
1316
+ }
1317
+ }
1318
+ }
1319
+ ]
1320
+ }
1047
1321
  },
1048
1322
  "400": {
1049
1323
  "$response": "BadRequest"
@@ -1125,7 +1399,21 @@
1125
1399
  ],
1126
1400
  "responses": {
1127
1401
  "200": {
1128
- "$response": "Success"
1402
+ "description": "Standard success envelope; operation data under `data`.",
1403
+ "schema": {
1404
+ "allOf": [
1405
+ {
1406
+ "$schema": "SuccessEnvelope"
1407
+ },
1408
+ {
1409
+ "properties": {
1410
+ "data": {
1411
+ "$schema": "StartLoadTestRunData"
1412
+ }
1413
+ }
1414
+ }
1415
+ ]
1416
+ }
1129
1417
  },
1130
1418
  "400": {
1131
1419
  "$response": "BadRequest"
@@ -1158,7 +1446,9 @@
1158
1446
  {
1159
1447
  "name": "limit",
1160
1448
  "type": "integer",
1161
- "description": "Max items to return (1-100, default 50)."
1449
+ "description": "Max items to return (1-100, default 50).",
1450
+ "minimum": 1,
1451
+ "maximum": 100
1162
1452
  },
1163
1453
  {
1164
1454
  "name": "cursor",
@@ -1178,12 +1468,14 @@
1178
1468
  {
1179
1469
  "name": "sinceIso",
1180
1470
  "type": "string",
1181
- "description": "ISO-8601 lower bound."
1471
+ "description": "ISO-8601 lower bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
1472
+ "example": "2026-09-12"
1182
1473
  },
1183
1474
  {
1184
1475
  "name": "untilIso",
1185
1476
  "type": "string",
1186
- "description": "ISO-8601 upper bound."
1477
+ "description": "ISO-8601 upper bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
1478
+ "example": "2026-09-12"
1187
1479
  },
1188
1480
  {
1189
1481
  "name": "verdict",
@@ -1222,7 +1514,21 @@
1222
1514
  ],
1223
1515
  "responses": {
1224
1516
  "200": {
1225
- "$response": "Success"
1517
+ "description": "Standard success envelope; operation data under `data`.",
1518
+ "schema": {
1519
+ "allOf": [
1520
+ {
1521
+ "$schema": "SuccessEnvelope"
1522
+ },
1523
+ {
1524
+ "properties": {
1525
+ "data": {
1526
+ "$schema": "ListLoadTestRunsData"
1527
+ }
1528
+ }
1529
+ }
1530
+ ]
1531
+ }
1226
1532
  },
1227
1533
  "400": {
1228
1534
  "$response": "BadRequest"
@@ -1285,12 +1591,14 @@
1285
1591
  {
1286
1592
  "name": "sinceIso",
1287
1593
  "type": "string",
1288
- "description": "ISO-8601 lower bound."
1594
+ "description": "ISO-8601 lower bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
1595
+ "example": "2026-09-12"
1289
1596
  },
1290
1597
  {
1291
1598
  "name": "untilIso",
1292
1599
  "type": "string",
1293
- "description": "ISO-8601 upper bound."
1600
+ "description": "ISO-8601 upper bound. ISO-8601 — a date (2026-09-12) or a date-time (2026-09-12T10:30:00Z).",
1601
+ "example": "2026-09-12"
1294
1602
  }
1295
1603
  ],
1296
1604
  "intent": "Show how one test's metrics trend across its recent runs — use this for 'is this test getting slower over time?'",
@@ -1304,7 +1612,21 @@
1304
1612
  ],
1305
1613
  "responses": {
1306
1614
  "200": {
1307
- "$response": "Success"
1615
+ "description": "Standard success envelope; operation data under `data`.",
1616
+ "schema": {
1617
+ "allOf": [
1618
+ {
1619
+ "$schema": "SuccessEnvelope"
1620
+ },
1621
+ {
1622
+ "properties": {
1623
+ "data": {
1624
+ "$schema": "GetLoadTestHistoricalTrendsData"
1625
+ }
1626
+ }
1627
+ }
1628
+ ]
1629
+ }
1308
1630
  },
1309
1631
  "400": {
1310
1632
  "$response": "BadRequest"
@@ -1345,7 +1667,21 @@
1345
1667
  ],
1346
1668
  "responses": {
1347
1669
  "200": {
1348
- "$response": "Success"
1670
+ "description": "Standard success envelope; operation data under `data`.",
1671
+ "schema": {
1672
+ "allOf": [
1673
+ {
1674
+ "$schema": "SuccessEnvelope"
1675
+ },
1676
+ {
1677
+ "properties": {
1678
+ "data": {
1679
+ "$schema": "GetLoadTestMetricsManifestData"
1680
+ }
1681
+ }
1682
+ }
1683
+ ]
1684
+ }
1349
1685
  },
1350
1686
  "400": {
1351
1687
  "$response": "BadRequest"
@@ -1388,7 +1724,8 @@
1388
1724
  {
1389
1725
  "name": "ifVersion",
1390
1726
  "type": "string",
1391
- "description": "Optimistic-concurrency guard (ISO timestamp of the version being edited)."
1727
+ "description": "Optimistic-concurrency guard (ISO timestamp of the version being edited).",
1728
+ "format": "date-time"
1392
1729
  },
1393
1730
  {
1394
1731
  "name": "validationToken",
@@ -1424,7 +1761,8 @@
1424
1761
  "config is a partial update, but each field it carries REPLACES that field wholesale — it does not merge. tags overwrites the entire tag set; it does not append. To add a tag to a test (or the same tag across several tests), getLoadTest each one first and send the union under config.tags.",
1425
1762
  "To change the load profile, send config.loadProfile plus that profile's fields (see createLoadTest's load-profile guidance for the four shapes). Switching profiles clears the previous profile's fields — e.g. ramping→throughput empties the stages and drops iterations. iterations and throughput are PLU-only.",
1426
1763
  "To tag a specific RUN rather than the test, pass runId (a run UUID from listLoadTestRuns) together with config.tags — the tags apply to that one run and the saved test is untouched. A run inherits the test's tags until you set its own; setting run tags overrides (they also replace wholesale, so send the union to add). Omit runId to tag the test itself.",
1427
- "Tags live on the load test, not on its runs — there is no per-run tagging, so do not touch runs when asked to tag a test. To tag every test in a project, list them with listLoadTests and page through with cursor until hasMore is false, then updateLoadTest each one — do not stop after the first page or a subset."
1764
+ "Tags live on the load test, not on its runs — there is no per-run tagging, so do not touch runs when asked to tag a test. To tag every test in a project, list them with listLoadTests and page through with cursor until hasMore is false, then updateLoadTest each one — do not stop after the first page or a subset.",
1765
+ "Optimistic concurrency is opt-in: pass ifVersion (the version token from a prior get/create/update) so the edit fails with 409 CONFLICT if the test changed meanwhile; OMITTING ifVersion is a last-write-wins update that overwrites any concurrent change."
1428
1766
  ],
1429
1767
  "returns": [
1430
1768
  "testId",
@@ -1432,7 +1770,21 @@
1432
1770
  ],
1433
1771
  "responses": {
1434
1772
  "200": {
1435
- "$response": "Success"
1773
+ "description": "Standard success envelope; operation data under `data`.",
1774
+ "schema": {
1775
+ "allOf": [
1776
+ {
1777
+ "$schema": "SuccessEnvelope"
1778
+ },
1779
+ {
1780
+ "properties": {
1781
+ "data": {
1782
+ "$schema": "UpdateLoadTestData"
1783
+ }
1784
+ }
1785
+ }
1786
+ ]
1787
+ }
1436
1788
  },
1437
1789
  "400": {
1438
1790
  "$response": "BadRequest"
@@ -1494,7 +1846,21 @@
1494
1846
  ],
1495
1847
  "responses": {
1496
1848
  "200": {
1497
- "$response": "Success"
1849
+ "description": "Standard success envelope; operation data under `data`.",
1850
+ "schema": {
1851
+ "allOf": [
1852
+ {
1853
+ "$schema": "SuccessEnvelope"
1854
+ },
1855
+ {
1856
+ "properties": {
1857
+ "data": {
1858
+ "$schema": "GetLoadTestData"
1859
+ }
1860
+ }
1861
+ }
1862
+ ]
1863
+ }
1498
1864
  },
1499
1865
  "400": {
1500
1866
  "$response": "BadRequest"
@@ -1549,15 +1915,765 @@
1549
1915
  "success",
1550
1916
  "error"
1551
1917
  ]
1918
+ },
1919
+ "GetLoadTestPlatformStatusData": {
1920
+ "type": "object",
1921
+ "properties": {
1922
+ "platformState": {
1923
+ "type": "string"
1924
+ },
1925
+ "components": {
1926
+ "type": "array"
1927
+ },
1928
+ "checkedAt": {
1929
+ "type": "string",
1930
+ "format": "date-time"
1931
+ }
1932
+ }
1933
+ },
1934
+ "ListLoadTestProjectsData": {
1935
+ "type": "object",
1936
+ "properties": {
1937
+ "projects": {
1938
+ "type": "array",
1939
+ "items": {
1940
+ "type": "object",
1941
+ "properties": {
1942
+ "projectId": {
1943
+ "type": "integer"
1944
+ },
1945
+ "name": {
1946
+ "type": "string"
1947
+ },
1948
+ "testCount": {
1949
+ "type": "integer",
1950
+ "nullable": true
1951
+ },
1952
+ "lastActivityAt": {
1953
+ "type": "string",
1954
+ "nullable": true
1955
+ },
1956
+ "owner": {
1957
+ "type": "object",
1958
+ "properties": {
1959
+ "userId": {
1960
+ "type": "integer",
1961
+ "nullable": true
1962
+ },
1963
+ "email": {
1964
+ "type": "string",
1965
+ "nullable": true
1966
+ }
1967
+ }
1968
+ }
1969
+ }
1970
+ }
1971
+ },
1972
+ "hasMore": {
1973
+ "type": "boolean"
1974
+ },
1975
+ "nextCursor": {
1976
+ "type": "string"
1977
+ }
1978
+ }
1979
+ },
1980
+ "ListLoadTestsData": {
1981
+ "type": "object",
1982
+ "properties": {
1983
+ "tests": {
1984
+ "type": "array",
1985
+ "items": {
1986
+ "type": "object",
1987
+ "properties": {
1988
+ "testId": {
1989
+ "type": "integer"
1990
+ },
1991
+ "name": {
1992
+ "type": "string",
1993
+ "nullable": true
1994
+ },
1995
+ "testType": {
1996
+ "type": "string",
1997
+ "description": "plu (API), blu (Browser) or hybrid."
1998
+ },
1999
+ "framework": {
2000
+ "type": "string",
2001
+ "nullable": true
2002
+ },
2003
+ "tags": {
2004
+ "type": "array",
2005
+ "items": {
2006
+ "type": "string"
2007
+ }
2008
+ },
2009
+ "owner": {
2010
+ "type": "object",
2011
+ "properties": {
2012
+ "userId": {
2013
+ "type": "integer",
2014
+ "nullable": true
2015
+ },
2016
+ "email": {
2017
+ "type": "string",
2018
+ "nullable": true
2019
+ }
2020
+ }
2021
+ },
2022
+ "lastRun": {
2023
+ "type": "object",
2024
+ "description": "Most recent execution, when present.",
2025
+ "properties": {
2026
+ "runId": {
2027
+ "type": "string",
2028
+ "nullable": true
2029
+ },
2030
+ "status": {
2031
+ "type": "string",
2032
+ "nullable": true
2033
+ },
2034
+ "startedAt": {
2035
+ "type": "string",
2036
+ "nullable": true
2037
+ },
2038
+ "verdict": {
2039
+ "type": "string",
2040
+ "nullable": true
2041
+ }
2042
+ }
2043
+ }
2044
+ }
2045
+ }
2046
+ },
2047
+ "hasMore": {
2048
+ "type": "boolean"
2049
+ },
2050
+ "nextCursor": {
2051
+ "type": "string"
2052
+ }
2053
+ }
2054
+ },
2055
+ "SearchLoadTestsData": {
2056
+ "type": "object",
2057
+ "properties": {
2058
+ "tests": {
2059
+ "type": "array",
2060
+ "items": {
2061
+ "type": "object",
2062
+ "properties": {
2063
+ "testId": {
2064
+ "type": "integer"
2065
+ },
2066
+ "name": {
2067
+ "type": "string",
2068
+ "nullable": true
2069
+ },
2070
+ "projectId": {
2071
+ "type": "integer",
2072
+ "nullable": true
2073
+ },
2074
+ "testType": {
2075
+ "type": "string"
2076
+ },
2077
+ "framework": {
2078
+ "type": "string",
2079
+ "nullable": true
2080
+ }
2081
+ }
2082
+ }
2083
+ },
2084
+ "hasMore": {
2085
+ "type": "boolean"
2086
+ }
2087
+ }
2088
+ },
2089
+ "GetLoadTestProjectTrendsData": {
2090
+ "type": "object",
2091
+ "properties": {
2092
+ "metrics": {
2093
+ "description": "Trend series payload; shape per getLoadTestMetricsManifest."
2094
+ }
2095
+ }
2096
+ },
2097
+ "ListProjectLoadTestRunsData": {
2098
+ "type": "object",
2099
+ "properties": {
2100
+ "runs": {
2101
+ "type": "array",
2102
+ "items": {
2103
+ "type": "object",
2104
+ "properties": {
2105
+ "runId": {
2106
+ "type": "string"
2107
+ },
2108
+ "status": {
2109
+ "type": "string",
2110
+ "nullable": true
2111
+ },
2112
+ "startedAt": {
2113
+ "type": "string",
2114
+ "nullable": true
2115
+ },
2116
+ "durationSec": {
2117
+ "type": "integer",
2118
+ "nullable": true,
2119
+ "description": "Wall-clock seconds; null while running or when timestamps are missing."
2120
+ },
2121
+ "vus": {
2122
+ "type": "integer",
2123
+ "nullable": true
2124
+ },
2125
+ "verdict": {
2126
+ "type": "string",
2127
+ "nullable": true
2128
+ },
2129
+ "vuHours": {
2130
+ "type": "number",
2131
+ "nullable": true,
2132
+ "description": "Billed VU-hours; null until billed."
2133
+ },
2134
+ "tags": {
2135
+ "type": "array",
2136
+ "items": {
2137
+ "type": "string"
2138
+ },
2139
+ "description": "Run-level tags, or the tags inherited from the test when the run has none."
2140
+ }
2141
+ }
2142
+ }
2143
+ },
2144
+ "hasMore": {
2145
+ "type": "boolean"
2146
+ },
2147
+ "nextCursor": {
2148
+ "type": "string"
2149
+ }
2150
+ }
2151
+ },
2152
+ "ListActiveLoadTestRunsData": {
2153
+ "type": "object",
2154
+ "properties": {
2155
+ "runs": {
2156
+ "type": "array",
2157
+ "items": {
2158
+ "type": "object",
2159
+ "properties": {
2160
+ "runId": {
2161
+ "type": "string"
2162
+ },
2163
+ "testId": {
2164
+ "type": "integer",
2165
+ "nullable": true
2166
+ },
2167
+ "testName": {
2168
+ "type": "string",
2169
+ "nullable": true
2170
+ },
2171
+ "projectId": {
2172
+ "type": "integer",
2173
+ "nullable": true
2174
+ },
2175
+ "startedBy": {
2176
+ "type": "object",
2177
+ "properties": {
2178
+ "userId": {
2179
+ "type": "integer",
2180
+ "nullable": true
2181
+ },
2182
+ "email": {
2183
+ "type": "string",
2184
+ "nullable": true
2185
+ }
2186
+ }
2187
+ },
2188
+ "startedAt": {
2189
+ "type": "string",
2190
+ "nullable": true
2191
+ },
2192
+ "elapsedSec": {
2193
+ "type": "integer",
2194
+ "nullable": true
2195
+ },
2196
+ "vus": {
2197
+ "type": "integer",
2198
+ "nullable": true
2199
+ },
2200
+ "vuHoursBurnedSoFar": {
2201
+ "type": "number"
2202
+ },
2203
+ "status": {
2204
+ "type": "string",
2205
+ "nullable": true
2206
+ },
2207
+ "tags": {
2208
+ "type": "array",
2209
+ "items": {
2210
+ "type": "string"
2211
+ },
2212
+ "description": "Run-level tags, or the tags inherited from the test when the run has none."
2213
+ }
2214
+ }
2215
+ }
2216
+ }
2217
+ }
2218
+ },
2219
+ "GetLoadTestRunStatusData": {
2220
+ "type": "object",
2221
+ "properties": {
2222
+ "status": {
2223
+ "type": "string"
2224
+ },
2225
+ "elapsedSec": {
2226
+ "type": "number"
2227
+ },
2228
+ "remainingSec": {
2229
+ "type": "number"
2230
+ },
2231
+ "pollAfterSeconds": {
2232
+ "type": "number"
2233
+ },
2234
+ "slaBreachFlags": {
2235
+ "type": "array"
2236
+ }
2237
+ }
2238
+ },
2239
+ "GetLoadTestInsightSummaryData": {
2240
+ "type": "object",
2241
+ "properties": {
2242
+ "state": {
2243
+ "type": "string"
2244
+ },
2245
+ "status": {
2246
+ "type": "string"
2247
+ },
2248
+ "report": {
2249
+ "type": "object"
2250
+ }
2251
+ }
2252
+ },
2253
+ "GetLoadTestRunReportData": {
2254
+ "type": "object",
2255
+ "properties": {
2256
+ "runId": {
2257
+ "type": "string",
2258
+ "format": "uuid"
2259
+ },
2260
+ "testType": {
2261
+ "type": "string"
2262
+ },
2263
+ "status": {
2264
+ "type": "string"
2265
+ },
2266
+ "testName": {
2267
+ "type": "string"
2268
+ },
2269
+ "durationSec": {
2270
+ "type": "number",
2271
+ "description": "Run wall-clock duration in whole seconds. Present to the user as minutes + seconds (e.g. 5m 30s)."
2272
+ },
2273
+ "kpis": {
2274
+ "type": "object"
2275
+ },
2276
+ "slaVerdicts": {
2277
+ "type": "array"
2278
+ },
2279
+ "transactions": {
2280
+ "type": "array"
2281
+ },
2282
+ "errorsByCategory": {
2283
+ "type": "object"
2284
+ },
2285
+ "meta": {
2286
+ "type": "object"
2287
+ }
2288
+ }
2289
+ },
2290
+ "StopLoadTestRunData": {
2291
+ "type": "object",
2292
+ "properties": {
2293
+ "runId": {
2294
+ "type": "string",
2295
+ "format": "uuid"
2296
+ },
2297
+ "status": {
2298
+ "type": "string"
2299
+ },
2300
+ "stoppedAt": {
2301
+ "type": "string",
2302
+ "format": "date-time"
2303
+ }
2304
+ }
2305
+ },
2306
+ "GetLoadTestQuotaData": {
2307
+ "type": "object",
2308
+ "properties": {
2309
+ "plan": {
2310
+ "type": "object"
2311
+ },
2312
+ "vuHours": {
2313
+ "type": "object"
2314
+ },
2315
+ "concurrency": {
2316
+ "type": "object"
2317
+ }
2318
+ }
2319
+ },
2320
+ "EstimateLoadTestRunCostData": {
2321
+ "type": "object",
2322
+ "properties": {
2323
+ "estimatedVuHours": {
2324
+ "type": "number"
2325
+ },
2326
+ "estimationBasis": {
2327
+ "type": "string"
2328
+ },
2329
+ "rangeBasis": {
2330
+ "type": "string"
2331
+ },
2332
+ "rangeExplanation": {
2333
+ "type": "string"
2334
+ },
2335
+ "fitsInQuota": {
2336
+ "type": "boolean"
2337
+ },
2338
+ "remainingAfterEstimate": {
2339
+ "type": "number"
2340
+ }
2341
+ }
2342
+ },
2343
+ "CompareLoadTestRunsData": {
2344
+ "type": "object",
2345
+ "properties": {
2346
+ "baseline": {
2347
+ "type": "object",
2348
+ "properties": {
2349
+ "runId": {
2350
+ "type": "string",
2351
+ "format": "uuid"
2352
+ },
2353
+ "testId": {
2354
+ "type": "integer"
2355
+ },
2356
+ "startedAt": {
2357
+ "type": "string",
2358
+ "format": "date-time"
2359
+ }
2360
+ }
2361
+ },
2362
+ "candidate": {
2363
+ "type": "object",
2364
+ "properties": {
2365
+ "runId": {
2366
+ "type": "string",
2367
+ "format": "uuid"
2368
+ },
2369
+ "testId": {
2370
+ "type": "integer"
2371
+ },
2372
+ "startedAt": {
2373
+ "type": "string",
2374
+ "format": "date-time"
2375
+ }
2376
+ }
2377
+ },
2378
+ "kpiDeltas": {
2379
+ "type": "array",
2380
+ "description": "Per-KPI baseline→candidate deltas.",
2381
+ "items": {
2382
+ "type": "object",
2383
+ "properties": {
2384
+ "metric": {
2385
+ "type": "string"
2386
+ },
2387
+ "baseline": {
2388
+ "type": "number",
2389
+ "description": "Null when either run lacks the value.",
2390
+ "nullable": true
2391
+ },
2392
+ "candidate": {
2393
+ "type": "number",
2394
+ "description": "Null when either run lacks the value.",
2395
+ "nullable": true
2396
+ },
2397
+ "absChange": {
2398
+ "type": "number",
2399
+ "description": "Null when either run lacks the value.",
2400
+ "nullable": true
2401
+ },
2402
+ "pctChange": {
2403
+ "type": "number",
2404
+ "description": "Signed percent change, candidate vs baseline. Null when either run lacks the value.",
2405
+ "nullable": true
2406
+ },
2407
+ "direction": {
2408
+ "type": "string",
2409
+ "enum": [
2410
+ "improved",
2411
+ "regressed",
2412
+ "unchanged",
2413
+ "unknown"
2414
+ ],
2415
+ "description": "\"unknown\" when either run has no value for the metric."
2416
+ }
2417
+ }
2418
+ }
2419
+ },
2420
+ "transactionDeltas": {
2421
+ "type": "array",
2422
+ "description": "Per-transaction deltas on one metric, sorted by |pctChange| desc.",
2423
+ "items": {
2424
+ "type": "object",
2425
+ "properties": {
2426
+ "name": {
2427
+ "type": "string"
2428
+ },
2429
+ "metric": {
2430
+ "type": "string"
2431
+ },
2432
+ "baseline": {
2433
+ "type": "number",
2434
+ "description": "Null when either run lacks the value.",
2435
+ "nullable": true
2436
+ },
2437
+ "candidate": {
2438
+ "type": "number",
2439
+ "description": "Null when either run lacks the value.",
2440
+ "nullable": true
2441
+ },
2442
+ "absChange": {
2443
+ "type": "number",
2444
+ "description": "Null when either run lacks the value.",
2445
+ "nullable": true
2446
+ },
2447
+ "pctChange": {
2448
+ "type": "number",
2449
+ "description": "Signed percent change, candidate vs baseline. Null when either run lacks the value.",
2450
+ "nullable": true
2451
+ },
2452
+ "regressed": {
2453
+ "type": "boolean",
2454
+ "description": "Null when either run lacks the transaction (unknown, not unregressed).",
2455
+ "nullable": true
2456
+ }
2457
+ }
2458
+ }
2459
+ },
2460
+ "slaVerdictChanges": {
2461
+ "type": "array",
2462
+ "description": "SLA thresholds whose verdict changed between the runs.",
2463
+ "items": {
2464
+ "type": "object",
2465
+ "properties": {
2466
+ "metric": {
2467
+ "type": "string"
2468
+ },
2469
+ "type": {
2470
+ "type": "string"
2471
+ },
2472
+ "condition": {
2473
+ "type": "string"
2474
+ },
2475
+ "threshold": {},
2476
+ "unit": {
2477
+ "type": "string"
2478
+ },
2479
+ "request": {},
2480
+ "from": {
2481
+ "type": "string",
2482
+ "description": "Null when the threshold is absent on that run.",
2483
+ "nullable": true
2484
+ },
2485
+ "to": {
2486
+ "type": "string",
2487
+ "description": "Null when the threshold is absent on that run.",
2488
+ "nullable": true
2489
+ },
2490
+ "diffStatus": {
2491
+ "type": "string",
2492
+ "enum": [
2493
+ "now_failing",
2494
+ "now_passing",
2495
+ "added",
2496
+ "dropped"
2497
+ ]
2498
+ }
2499
+ }
2500
+ }
2501
+ },
2502
+ "warnings": {
2503
+ "type": "array",
2504
+ "items": {
2505
+ "type": "string"
2506
+ }
2507
+ }
2508
+ }
2509
+ },
2510
+ "CreateLoadTestData": {
2511
+ "type": "object",
2512
+ "properties": {
2513
+ "testId": {
2514
+ "type": "integer"
2515
+ },
2516
+ "name": {
2517
+ "type": "string"
2518
+ },
2519
+ "projectId": {
2520
+ "type": "integer"
2521
+ },
2522
+ "version": {
2523
+ "type": "string",
2524
+ "format": "date-time",
2525
+ "description": "Optimistic-concurrency token: the test's updated_at as an ISO-8601 date-time (seconds precision). Pass it back unchanged as updateLoadTest's ifVersion."
2526
+ },
2527
+ "dashboardLink": {
2528
+ "type": "string"
2529
+ }
2530
+ }
2531
+ },
2532
+ "StartLoadTestRunData": {
2533
+ "type": "object",
2534
+ "properties": {
2535
+ "runId": {
2536
+ "type": "string",
2537
+ "format": "uuid"
2538
+ },
2539
+ "status": {
2540
+ "type": "string"
2541
+ },
2542
+ "startedAt": {
2543
+ "type": "string",
2544
+ "format": "date-time"
2545
+ },
2546
+ "dashboardLink": {
2547
+ "type": "string"
2548
+ },
2549
+ "estimatedVuHoursRange": {
2550
+ "description": "Low/high VU-hour estimate for the started run."
2551
+ }
2552
+ }
2553
+ },
2554
+ "ListLoadTestRunsData": {
2555
+ "type": "object",
2556
+ "properties": {
2557
+ "runs": {
2558
+ "type": "array",
2559
+ "items": {
2560
+ "type": "object",
2561
+ "properties": {
2562
+ "runId": {
2563
+ "type": "string"
2564
+ },
2565
+ "status": {
2566
+ "type": "string",
2567
+ "nullable": true
2568
+ },
2569
+ "startedAt": {
2570
+ "type": "string",
2571
+ "nullable": true
2572
+ },
2573
+ "durationSec": {
2574
+ "type": "integer",
2575
+ "nullable": true,
2576
+ "description": "Wall-clock seconds; null while running or when timestamps are missing."
2577
+ },
2578
+ "vus": {
2579
+ "type": "integer",
2580
+ "nullable": true
2581
+ },
2582
+ "verdict": {
2583
+ "type": "string",
2584
+ "nullable": true
2585
+ },
2586
+ "vuHours": {
2587
+ "type": "number",
2588
+ "nullable": true,
2589
+ "description": "Billed VU-hours; null until billed."
2590
+ },
2591
+ "tags": {
2592
+ "type": "array",
2593
+ "items": {
2594
+ "type": "string"
2595
+ },
2596
+ "description": "Run-level tags, or the tags inherited from the test when the run has none."
2597
+ }
2598
+ }
2599
+ }
2600
+ },
2601
+ "hasMore": {
2602
+ "type": "boolean"
2603
+ },
2604
+ "nextCursor": {
2605
+ "type": "string"
2606
+ }
2607
+ }
2608
+ },
2609
+ "GetLoadTestHistoricalTrendsData": {
2610
+ "type": "object",
2611
+ "properties": {
2612
+ "metrics": {
2613
+ "description": "Trend series payload; shape per getLoadTestMetricsManifest."
2614
+ }
2615
+ }
2616
+ },
2617
+ "GetLoadTestMetricsManifestData": {
2618
+ "type": "object",
2619
+ "properties": {
2620
+ "testType": {
2621
+ "type": "string"
2622
+ },
2623
+ "metrics": {
2624
+ "type": "array"
2625
+ },
2626
+ "aliases": {
2627
+ "type": "object"
2628
+ }
2629
+ }
2630
+ },
2631
+ "UpdateLoadTestData": {
2632
+ "type": "object",
2633
+ "properties": {
2634
+ "testId": {
2635
+ "type": "integer"
2636
+ },
2637
+ "version": {
2638
+ "type": "string",
2639
+ "format": "date-time",
2640
+ "description": "Optimistic-concurrency token: the test's updated_at as an ISO-8601 date-time (seconds precision). Pass it back unchanged as updateLoadTest's ifVersion."
2641
+ }
2642
+ }
2643
+ },
2644
+ "GetLoadTestData": {
2645
+ "type": "object",
2646
+ "properties": {
2647
+ "testId": {
2648
+ "type": "integer"
2649
+ },
2650
+ "name": {
2651
+ "type": "string"
2652
+ },
2653
+ "testType": {
2654
+ "type": "string"
2655
+ },
2656
+ "framework": {
2657
+ "type": "string"
2658
+ },
2659
+ "version": {
2660
+ "type": "string",
2661
+ "format": "date-time",
2662
+ "description": "Optimistic-concurrency token: the test's updated_at as an ISO-8601 date-time (seconds precision). Pass it back unchanged as updateLoadTest's ifVersion."
2663
+ },
2664
+ "projectId": {
2665
+ "type": "integer"
2666
+ },
2667
+ "ownerUserId": {
2668
+ "type": "integer"
2669
+ },
2670
+ "config": {
2671
+ "type": "object"
2672
+ }
2673
+ }
1552
2674
  }
1553
2675
  },
1554
2676
  "responses": {
1555
- "Success": {
1556
- "description": "Standard success envelope; operation data under `data`.",
1557
- "schema": {
1558
- "$schema": "SuccessEnvelope"
1559
- }
1560
- },
1561
2677
  "BadRequest": {
1562
2678
  "description": "Invalid parameters or body.",
1563
2679
  "schema": {
@@ -1613,6 +2729,7 @@
1613
2729
  "loadTest": {
1614
2730
  "entity": "loadTest",
1615
2731
  "title": "Load Test",
2732
+ "description": "A saved load-test configuration (framework, script, load profile and thresholds); addressed by a numeric testId. Runs are executions of it.",
1616
2733
  "aliases": [
1617
2734
  "test",
1618
2735
  "load test",
@@ -1652,6 +2769,7 @@
1652
2769
  "run": {
1653
2770
  "entity": "run",
1654
2771
  "title": "Run",
2772
+ "description": "A single execution of a load test; addressed by runId (a UUID, also called jobId). Carries status, metrics and a report.",
1655
2773
  "aliases": [
1656
2774
  "execution",
1657
2775
  "job",
@@ -1690,6 +2808,7 @@
1690
2808
  "project": {
1691
2809
  "entity": "project",
1692
2810
  "title": "Project",
2811
+ "description": "A container that groups related load tests under a group/account; addressed by a numeric projectId.",
1693
2812
  "aliases": [
1694
2813
  "project",
1695
2814
  "workspace",
@@ -1715,6 +2834,7 @@
1715
2834
  "report": {
1716
2835
  "entity": "report",
1717
2836
  "title": "Run Report",
2837
+ "description": "The results of a completed run (KPIs, SLA verdicts, per-transaction rows, error breakdown); addressed by the run's runId.",
1718
2838
  "aliases": [
1719
2839
  "report",
1720
2840
  "result",
@@ -1742,6 +2862,7 @@
1742
2862
  "insight": {
1743
2863
  "entity": "insight",
1744
2864
  "title": "AI Insight",
2865
+ "description": "AI-generated analysis of a completed run (root cause and recommendations); addressed by the run's runId, and may be pending until generated.",
1745
2866
  "aliases": [
1746
2867
  "insight",
1747
2868
  "ai insight",
@@ -1768,6 +2889,7 @@
1768
2889
  "trend": {
1769
2890
  "entity": "trend",
1770
2891
  "title": "Historical Trend",
2892
+ "description": "Historical time-series of a metric across a test's or project's runs; scoped by testId or projectId, not independently identified.",
1771
2893
  "aliases": [
1772
2894
  "trend",
1773
2895
  "trends",
@@ -1800,6 +2922,7 @@
1800
2922
  "quota": {
1801
2923
  "entity": "quota",
1802
2924
  "title": "Quota & Cost",
2925
+ "description": "The caller's VU-hour entitlement, usage and concurrency limits; account/group-scoped, with no id.",
1803
2926
  "aliases": [
1804
2927
  "quota",
1805
2928
  "vu hours",
@@ -1829,6 +2952,7 @@
1829
2952
  "metrics": {
1830
2953
  "entity": "metrics",
1831
2954
  "title": "Metrics Manifest",
2955
+ "description": "The per-testType catalogue of available metric names, @-aliases and groupBy dimensions; a manifest, not an instance.",
1832
2956
  "aliases": [
1833
2957
  "metric",
1834
2958
  "metrics",
@@ -1856,6 +2980,7 @@
1856
2980
  "platform": {
1857
2981
  "entity": "platform",
1858
2982
  "title": "Platform Status",
2983
+ "description": "Health status of the Load Testing service and its dependencies; a singleton probe with no id.",
1859
2984
  "aliases": [
1860
2985
  "platform",
1861
2986
  "status",