shipeasy-sdk 2.1.0 → 2.3.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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/docs/skill/SKILL.md +6 -2
  4. data/lib/generators/shipeasy/install/USAGE +24 -0
  5. data/lib/generators/shipeasy/install/install_generator.rb +86 -0
  6. data/lib/generators/shipeasy/install/templates/initializer.rb.tt +41 -0
  7. data/lib/shipeasy/admin.rb +85 -0
  8. data/lib/shipeasy/sdk/version.rb +1 -1
  9. data/lib/shipeasy_admin/api/alert_rules_api.rb +292 -0
  10. data/lib/shipeasy_admin/api/attributes_api.rb +82 -0
  11. data/lib/shipeasy_admin/api/configs_api.rb +680 -0
  12. data/lib/shipeasy_admin/api/events_api.rb +438 -0
  13. data/lib/shipeasy_admin/api/experiments_api.rb +727 -0
  14. data/lib/shipeasy_admin/api/gates_api.rb +438 -0
  15. data/lib/shipeasy_admin/api/i18n_api.rb +507 -0
  16. data/lib/shipeasy_admin/api/killswitches_api.rb +526 -0
  17. data/lib/shipeasy_admin/api/metrics_api.rb +281 -0
  18. data/lib/shipeasy_admin/api/ops_api.rb +525 -0
  19. data/lib/shipeasy_admin/api/projects_api.rb +153 -0
  20. data/lib/shipeasy_admin/api/universes_api.rb +306 -0
  21. data/lib/shipeasy_admin/api_client.rb +441 -0
  22. data/lib/shipeasy_admin/api_error.rb +58 -0
  23. data/lib/shipeasy_admin/api_model_base.rb +88 -0
  24. data/lib/shipeasy_admin/configuration.rb +397 -0
  25. data/lib/shipeasy_admin/models/approve_event_request.rb +198 -0
  26. data/lib/shipeasy_admin/models/approve_event_response.rb +166 -0
  27. data/lib/shipeasy_admin/models/create_alert_rule_request.rb +408 -0
  28. data/lib/shipeasy_admin/models/create_alert_rule_response.rb +165 -0
  29. data/lib/shipeasy_admin/models/create_config_request.rb +280 -0
  30. data/lib/shipeasy_admin/models/create_config_response.rb +201 -0
  31. data/lib/shipeasy_admin/models/create_event_request.rb +253 -0
  32. data/lib/shipeasy_admin/models/create_event_response.rb +193 -0
  33. data/lib/shipeasy_admin/models/create_experiment_request.rb +869 -0
  34. data/lib/shipeasy_admin/models/create_experiment_request_goal_metric.rb +336 -0
  35. data/lib/shipeasy_admin/models/create_experiment_response.rb +212 -0
  36. data/lib/shipeasy_admin/models/create_gate_request.rb +529 -0
  37. data/lib/shipeasy_admin/models/create_gate_response.rb +212 -0
  38. data/lib/shipeasy_admin/models/create_i18n_profile_request.rb +188 -0
  39. data/lib/shipeasy_admin/models/create_i18n_profile_response.rb +193 -0
  40. data/lib/shipeasy_admin/models/create_killswitch_request.rb +263 -0
  41. data/lib/shipeasy_admin/models/create_killswitch_response.rb +201 -0
  42. data/lib/shipeasy_admin/models/create_metric_request.rb +415 -0
  43. data/lib/shipeasy_admin/models/create_metric_response.rb +193 -0
  44. data/lib/shipeasy_admin/models/create_ops_item_request.rb +287 -0
  45. data/lib/shipeasy_admin/models/create_ops_item_response.rb +177 -0
  46. data/lib/shipeasy_admin/models/create_universe_request.rb +289 -0
  47. data/lib/shipeasy_admin/models/create_universe_response.rb +212 -0
  48. data/lib/shipeasy_admin/models/delete_alert_rule_response.rb +188 -0
  49. data/lib/shipeasy_admin/models/delete_config_response.rb +188 -0
  50. data/lib/shipeasy_admin/models/delete_event_response.rb +189 -0
  51. data/lib/shipeasy_admin/models/delete_experiment_response.rb +188 -0
  52. data/lib/shipeasy_admin/models/delete_gate_response.rb +188 -0
  53. data/lib/shipeasy_admin/models/delete_killswitch_response.rb +188 -0
  54. data/lib/shipeasy_admin/models/delete_metric_response.rb +189 -0
  55. data/lib/shipeasy_admin/models/delete_universe_response.rb +188 -0
  56. data/lib/shipeasy_admin/models/disable_gate_response.rb +190 -0
  57. data/lib/shipeasy_admin/models/discard_config_draft_request.rb +190 -0
  58. data/lib/shipeasy_admin/models/discard_config_draft_response.rb +188 -0
  59. data/lib/shipeasy_admin/models/enable_gate_response.rb +190 -0
  60. data/lib/shipeasy_admin/models/error_response.rb +185 -0
  61. data/lib/shipeasy_admin/models/get_config_response.rb +351 -0
  62. data/lib/shipeasy_admin/models/get_current_project_response.rb +606 -0
  63. data/lib/shipeasy_admin/models/get_current_project_response_module_translations.rb +104 -0
  64. data/lib/shipeasy_admin/models/get_event_response.rb +344 -0
  65. data/lib/shipeasy_admin/models/get_experiment_response.rb +688 -0
  66. data/lib/shipeasy_admin/models/get_experiment_results_response.rb +243 -0
  67. data/lib/shipeasy_admin/models/get_experiment_results_response_experiment.rb +248 -0
  68. data/lib/shipeasy_admin/models/get_experiment_results_response_results_inner.rb +252 -0
  69. data/lib/shipeasy_admin/models/get_experiment_timeseries_response.rb +192 -0
  70. data/lib/shipeasy_admin/models/get_experiment_timeseries_response_experiment.rb +261 -0
  71. data/lib/shipeasy_admin/models/get_experiment_timeseries_response_series_inner.rb +278 -0
  72. data/lib/shipeasy_admin/models/get_killswitch_response.rb +270 -0
  73. data/lib/shipeasy_admin/models/get_metric_response.rb +378 -0
  74. data/lib/shipeasy_admin/models/get_ops_item_response.rb +349 -0
  75. data/lib/shipeasy_admin/models/link_pr_to_ops_item_request.rb +186 -0
  76. data/lib/shipeasy_admin/models/link_pr_to_ops_item_response.rb +166 -0
  77. data/lib/shipeasy_admin/models/list_alert_rules_response_inner.rb +478 -0
  78. data/lib/shipeasy_admin/models/list_alert_rules_response_inner_notify.rb +177 -0
  79. data/lib/shipeasy_admin/models/list_alert_rules_response_inner_notify_slack_channel.rb +211 -0
  80. data/lib/shipeasy_admin/models/list_attributes_response_inner.rb +176 -0
  81. data/lib/shipeasy_admin/models/list_config_activity_response_inner.rb +280 -0
  82. data/lib/shipeasy_admin/models/list_configs_response.rb +178 -0
  83. data/lib/shipeasy_admin/models/list_configs_response_data_inner.rb +351 -0
  84. data/lib/shipeasy_admin/models/list_configs_response_data_inner_drafts_value.rb +237 -0
  85. data/lib/shipeasy_admin/models/list_configs_response_data_inner_envs_value.rb +237 -0
  86. data/lib/shipeasy_admin/models/list_events_response_inner.rb +344 -0
  87. data/lib/shipeasy_admin/models/list_events_response_inner_properties_inner.rb +289 -0
  88. data/lib/shipeasy_admin/models/list_experiments_response.rb +178 -0
  89. data/lib/shipeasy_admin/models/list_experiments_response_data_inner.rb +688 -0
  90. data/lib/shipeasy_admin/models/list_experiments_response_data_inner_groups_inner.rb +258 -0
  91. data/lib/shipeasy_admin/models/list_gates_response.rb +178 -0
  92. data/lib/shipeasy_admin/models/list_gates_response_data_inner.rb +395 -0
  93. data/lib/shipeasy_admin/models/list_gates_response_data_inner_enabled.rb +104 -0
  94. data/lib/shipeasy_admin/models/list_gates_response_data_inner_rules_inner.rb +238 -0
  95. data/lib/shipeasy_admin/models/list_gates_response_data_inner_stack_inner.rb +105 -0
  96. data/lib/shipeasy_admin/models/list_gates_response_data_inner_stack_inner_one_of.rb +375 -0
  97. data/lib/shipeasy_admin/models/list_gates_response_data_inner_stack_inner_one_of1.rb +331 -0
  98. data/lib/shipeasy_admin/models/list_gates_response_data_inner_stack_inner_one_of_ramp.rb +319 -0
  99. data/lib/shipeasy_admin/models/list_i18n_drafts_response_inner.rb +272 -0
  100. data/lib/shipeasy_admin/models/list_i18n_keys_response.rb +195 -0
  101. data/lib/shipeasy_admin/models/list_i18n_keys_response_keys_inner.rb +284 -0
  102. data/lib/shipeasy_admin/models/list_i18n_profiles_response_inner.rb +224 -0
  103. data/lib/shipeasy_admin/models/list_killswitches_response.rb +178 -0
  104. data/lib/shipeasy_admin/models/list_killswitches_response_data_inner.rb +270 -0
  105. data/lib/shipeasy_admin/models/list_killswitches_response_data_inner_envs_value.rb +248 -0
  106. data/lib/shipeasy_admin/models/list_metrics_response_inner.rb +378 -0
  107. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir.rb +295 -0
  108. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg.rb +113 -0
  109. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of.rb +188 -0
  110. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of1.rb +188 -0
  111. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of2.rb +188 -0
  112. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of3.rb +188 -0
  113. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of4.rb +188 -0
  114. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of5.rb +188 -0
  115. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of6.rb +188 -0
  116. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of7.rb +217 -0
  117. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of8.rb +233 -0
  118. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of9.rb +240 -0
  119. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of9_numerator.rb +266 -0
  120. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_agg_one_of9_numerator_filters_inner.rb +264 -0
  121. data/lib/shipeasy_admin/models/list_metrics_response_inner_query_ir_group_by.rb +228 -0
  122. data/lib/shipeasy_admin/models/list_ops_items_response_inner.rb +349 -0
  123. data/lib/shipeasy_admin/models/list_slack_channels_response.rb +195 -0
  124. data/lib/shipeasy_admin/models/list_slack_channels_response_channels_inner.rb +203 -0
  125. data/lib/shipeasy_admin/models/list_universes_response.rb +178 -0
  126. data/lib/shipeasy_admin/models/list_universes_response_data_inner.rb +305 -0
  127. data/lib/shipeasy_admin/models/notify_ops_request.rb +261 -0
  128. data/lib/shipeasy_admin/models/notify_ops_response.rb +193 -0
  129. data/lib/shipeasy_admin/models/publish_config_draft_request.rb +190 -0
  130. data/lib/shipeasy_admin/models/publish_config_draft_response.rb +260 -0
  131. data/lib/shipeasy_admin/models/publish_i18n_profile_request.rb +149 -0
  132. data/lib/shipeasy_admin/models/publish_i18n_profile_response.rb +404 -0
  133. data/lib/shipeasy_admin/models/push_i18n_keys_request.rb +205 -0
  134. data/lib/shipeasy_admin/models/push_i18n_keys_request_keys_inner.rb +192 -0
  135. data/lib/shipeasy_admin/models/push_i18n_keys_response.rb +261 -0
  136. data/lib/shipeasy_admin/models/reanalyze_experiment_response.rb +214 -0
  137. data/lib/shipeasy_admin/models/save_config_draft_request.rb +202 -0
  138. data/lib/shipeasy_admin/models/save_config_draft_response.rb +286 -0
  139. data/lib/shipeasy_admin/models/set_experiment_metrics_request.rb +168 -0
  140. data/lib/shipeasy_admin/models/set_experiment_metrics_request_metrics_inner.rb +216 -0
  141. data/lib/shipeasy_admin/models/set_experiment_metrics_response.rb +179 -0
  142. data/lib/shipeasy_admin/models/set_experiment_metrics_response_metrics_inner.rb +201 -0
  143. data/lib/shipeasy_admin/models/set_experiment_status_request.rb +190 -0
  144. data/lib/shipeasy_admin/models/set_experiment_status_response.rb +214 -0
  145. data/lib/shipeasy_admin/models/set_killswitch_switch_request.rb +264 -0
  146. data/lib/shipeasy_admin/models/set_killswitch_switch_response.rb +288 -0
  147. data/lib/shipeasy_admin/models/unset_killswitch_switch_request.rb +237 -0
  148. data/lib/shipeasy_admin/models/unset_killswitch_switch_response.rb +289 -0
  149. data/lib/shipeasy_admin/models/update_alert_rule_request.rb +306 -0
  150. data/lib/shipeasy_admin/models/update_alert_rule_response.rb +165 -0
  151. data/lib/shipeasy_admin/models/update_config_request.rb +198 -0
  152. data/lib/shipeasy_admin/models/update_config_response.rb +165 -0
  153. data/lib/shipeasy_admin/models/update_event_request.rb +198 -0
  154. data/lib/shipeasy_admin/models/update_event_response.rb +166 -0
  155. data/lib/shipeasy_admin/models/update_experiment_request.rb +746 -0
  156. data/lib/shipeasy_admin/models/update_experiment_response.rb +165 -0
  157. data/lib/shipeasy_admin/models/update_gate_request.rb +403 -0
  158. data/lib/shipeasy_admin/models/update_gate_response.rb +166 -0
  159. data/lib/shipeasy_admin/models/update_i18n_key_request.rb +176 -0
  160. data/lib/shipeasy_admin/models/update_i18n_key_response.rb +166 -0
  161. data/lib/shipeasy_admin/models/update_killswitch_request.rb +224 -0
  162. data/lib/shipeasy_admin/models/update_killswitch_response.rb +165 -0
  163. data/lib/shipeasy_admin/models/update_ops_item_request.rb +205 -0
  164. data/lib/shipeasy_admin/models/update_ops_item_response.rb +166 -0
  165. data/lib/shipeasy_admin/models/update_universe_request.rb +213 -0
  166. data/lib/shipeasy_admin/models/update_universe_response.rb +165 -0
  167. data/lib/shipeasy_admin/models/upsert_project_request.rb +222 -0
  168. data/lib/shipeasy_admin/models/upsert_project_response.rb +260 -0
  169. data/lib/shipeasy_admin/version.rb +15 -0
  170. data/lib/shipeasy_admin.rb +196 -0
  171. metadata +230 -2
@@ -0,0 +1,727 @@
1
+ =begin
2
+ #Shipeasy Admin API
3
+
4
+ #REST API for managing feature gates, experiments, configs, universes, and killswitches in a Shipeasy project. Authenticate with an admin SDK key (`Authorization: Bearer sdk_admin_…`) and scope every request to a project via the `X-Project-Id` header. Mint admin keys via `POST /api/admin/keys` with `type: \"admin\"`. Keys expire after 90 days; rotate with the `revoke` action.
5
+
6
+ The version of the OpenAPI document: 1.0.0
7
+
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.23.0
10
+
11
+ =end
12
+
13
+ require 'cgi'
14
+
15
+ module Shipeasy::Admin::Generated
16
+ class ExperimentsApi
17
+ attr_accessor :api_client
18
+
19
+ def initialize(api_client = ApiClient.default)
20
+ @api_client = api_client
21
+ end
22
+ # Create an experiment
23
+ # Creates a new experiment in `draft` status. `name`, `universe`, and `groups` are required; everything else has sensible defaults. 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. **Use cases** - **Minimal 50/50** — `name` + `universe` + two equal-weight groups. - **Targeted rollout** — supply `targeting_gate` to restrict the eligible audience and `allocation_pct` to enrol a slice of it. - **Multivariant** — three or more groups with weights summing to 10000. - **Sequential testing** — `sequential_testing: true` for Premium plans.
24
+ # @param create_experiment_request [CreateExperimentRequest]
25
+ # @param [Hash] opts the optional parameters
26
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
27
+ # @return [CreateExperimentResponse]
28
+ def create_experiment(create_experiment_request, opts = {})
29
+ data, _status_code, _headers = create_experiment_with_http_info(create_experiment_request, opts)
30
+ data
31
+ end
32
+
33
+ # Create an experiment
34
+ # Creates a new experiment in `draft` status. `name`, `universe`, and `groups` are required; everything else has sensible defaults. 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. **Use cases** - **Minimal 50/50** — `name` + `universe` + two equal-weight groups. - **Targeted rollout** — supply `targeting_gate` to restrict the eligible audience and `allocation_pct` to enrol a slice of it. - **Multivariant** — three or more groups with weights summing to 10000. - **Sequential testing** — `sequential_testing: true` for Premium plans.
35
+ # @param create_experiment_request [CreateExperimentRequest]
36
+ # @param [Hash] opts the optional parameters
37
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
38
+ # @return [Array<(CreateExperimentResponse, Integer, Hash)>] CreateExperimentResponse data, response status code and response headers
39
+ def create_experiment_with_http_info(create_experiment_request, opts = {})
40
+ if @api_client.config.debugging
41
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.create_experiment ...'
42
+ end
43
+ # verify the required parameter 'create_experiment_request' is set
44
+ if @api_client.config.client_side_validation && create_experiment_request.nil?
45
+ fail ArgumentError, "Missing the required parameter 'create_experiment_request' when calling ExperimentsApi.create_experiment"
46
+ end
47
+ # resource path
48
+ local_var_path = '/api/admin/experiments'
49
+
50
+ # query parameters
51
+ query_params = opts[:query_params] || {}
52
+
53
+ # header parameters
54
+ header_params = opts[:header_params] || {}
55
+ # HTTP header 'Accept' (if needed)
56
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
57
+ # HTTP header 'Content-Type'
58
+ content_type = @api_client.select_header_content_type(['application/json'])
59
+ if !content_type.nil?
60
+ header_params['Content-Type'] = content_type
61
+ end
62
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
63
+
64
+ # form parameters
65
+ form_params = opts[:form_params] || {}
66
+
67
+ # http body (model)
68
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(create_experiment_request)
69
+
70
+ # return_type
71
+ return_type = opts[:debug_return_type] || 'CreateExperimentResponse'
72
+
73
+ # auth_names
74
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
75
+
76
+ new_options = opts.merge(
77
+ :operation => :"ExperimentsApi.create_experiment",
78
+ :header_params => header_params,
79
+ :query_params => query_params,
80
+ :form_params => form_params,
81
+ :body => post_body,
82
+ :auth_names => auth_names,
83
+ :return_type => return_type
84
+ )
85
+
86
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
87
+ if @api_client.config.debugging
88
+ @api_client.config.logger.debug "API called: ExperimentsApi#create_experiment\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
89
+ end
90
+ return data, status_code, headers
91
+ end
92
+
93
+ # Delete an experiment
94
+ # Archives the experiment (soft-delete via status transition). Returns `409` if the experiment is still `running` — stop it first. **Use case:** Tear down an experiment after the analysis is signed off.
95
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
96
+ # @param [Hash] opts the optional parameters
97
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
98
+ # @return [DeleteExperimentResponse]
99
+ def delete_experiment(id, opts = {})
100
+ data, _status_code, _headers = delete_experiment_with_http_info(id, opts)
101
+ data
102
+ end
103
+
104
+ # Delete an experiment
105
+ # Archives the experiment (soft-delete via status transition). Returns &#x60;409&#x60; if the experiment is still &#x60;running&#x60; — stop it first. **Use case:** Tear down an experiment after the analysis is signed off.
106
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
107
+ # @param [Hash] opts the optional parameters
108
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
109
+ # @return [Array<(DeleteExperimentResponse, Integer, Hash)>] DeleteExperimentResponse data, response status code and response headers
110
+ def delete_experiment_with_http_info(id, opts = {})
111
+ if @api_client.config.debugging
112
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.delete_experiment ...'
113
+ end
114
+ # verify the required parameter 'id' is set
115
+ if @api_client.config.client_side_validation && id.nil?
116
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.delete_experiment"
117
+ end
118
+ # resource path
119
+ local_var_path = '/api/admin/experiments/{id}'.sub('{id}', CGI.escape(id.to_s))
120
+
121
+ # query parameters
122
+ query_params = opts[:query_params] || {}
123
+
124
+ # header parameters
125
+ header_params = opts[:header_params] || {}
126
+ # HTTP header 'Accept' (if needed)
127
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
128
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
129
+
130
+ # form parameters
131
+ form_params = opts[:form_params] || {}
132
+
133
+ # http body (model)
134
+ post_body = opts[:debug_body]
135
+
136
+ # return_type
137
+ return_type = opts[:debug_return_type] || 'DeleteExperimentResponse'
138
+
139
+ # auth_names
140
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
141
+
142
+ new_options = opts.merge(
143
+ :operation => :"ExperimentsApi.delete_experiment",
144
+ :header_params => header_params,
145
+ :query_params => query_params,
146
+ :form_params => form_params,
147
+ :body => post_body,
148
+ :auth_names => auth_names,
149
+ :return_type => return_type
150
+ )
151
+
152
+ data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options)
153
+ if @api_client.config.debugging
154
+ @api_client.config.logger.debug "API called: ExperimentsApi#delete_experiment\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
155
+ end
156
+ return data, status_code, headers
157
+ end
158
+
159
+ # Get one experiment
160
+ # Returns the full experiment row including groups, params, allocation, and lifecycle timestamps. **Use case:** Fetch one experiment to render the detail page or to inspect its current allocation and group weights.
161
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
162
+ # @param [Hash] opts the optional parameters
163
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
164
+ # @return [GetExperimentResponse]
165
+ def get_experiment(id, opts = {})
166
+ data, _status_code, _headers = get_experiment_with_http_info(id, opts)
167
+ data
168
+ end
169
+
170
+ # Get one experiment
171
+ # Returns the full experiment row including groups, params, allocation, and lifecycle timestamps. **Use case:** Fetch one experiment to render the detail page or to inspect its current allocation and group weights.
172
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
173
+ # @param [Hash] opts the optional parameters
174
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
175
+ # @return [Array<(GetExperimentResponse, Integer, Hash)>] GetExperimentResponse data, response status code and response headers
176
+ def get_experiment_with_http_info(id, opts = {})
177
+ if @api_client.config.debugging
178
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.get_experiment ...'
179
+ end
180
+ # resource path
181
+ local_var_path = '/api/admin/experiments/{id}'.sub('{id}', CGI.escape(id.to_s))
182
+
183
+ # query parameters
184
+ query_params = opts[:query_params] || {}
185
+
186
+ # header parameters
187
+ header_params = opts[:header_params] || {}
188
+ # HTTP header 'Accept' (if needed)
189
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
190
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
191
+
192
+ # form parameters
193
+ form_params = opts[:form_params] || {}
194
+
195
+ # http body (model)
196
+ post_body = opts[:debug_body]
197
+
198
+ # return_type
199
+ return_type = opts[:debug_return_type] || 'GetExperimentResponse'
200
+
201
+ # auth_names
202
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
203
+
204
+ new_options = opts.merge(
205
+ :operation => :"ExperimentsApi.get_experiment",
206
+ :header_params => header_params,
207
+ :query_params => query_params,
208
+ :form_params => form_params,
209
+ :body => post_body,
210
+ :auth_names => auth_names,
211
+ :return_type => return_type
212
+ )
213
+
214
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
215
+ if @api_client.config.debugging
216
+ @api_client.config.logger.debug "API called: ExperimentsApi#get_experiment\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
217
+ end
218
+ return data, status_code, headers
219
+ end
220
+
221
+ # Get analysis results
222
+ # 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. **Use case:** Render the results table on the experiment detail page or drive an automated decision once a `goal` metric reaches significance.
223
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
224
+ # @param [Hash] opts the optional parameters
225
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
226
+ # @return [GetExperimentResultsResponse]
227
+ def get_experiment_results(id, opts = {})
228
+ data, _status_code, _headers = get_experiment_results_with_http_info(id, opts)
229
+ data
230
+ end
231
+
232
+ # Get analysis results
233
+ # 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. **Use case:** Render the results table on the experiment detail page or drive an automated decision once a &#x60;goal&#x60; metric reaches significance.
234
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
235
+ # @param [Hash] opts the optional parameters
236
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
237
+ # @return [Array<(GetExperimentResultsResponse, Integer, Hash)>] GetExperimentResultsResponse data, response status code and response headers
238
+ def get_experiment_results_with_http_info(id, opts = {})
239
+ if @api_client.config.debugging
240
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.get_experiment_results ...'
241
+ end
242
+ # verify the required parameter 'id' is set
243
+ if @api_client.config.client_side_validation && id.nil?
244
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.get_experiment_results"
245
+ end
246
+ # resource path
247
+ local_var_path = '/api/admin/experiments/{id}/results'.sub('{id}', CGI.escape(id.to_s))
248
+
249
+ # query parameters
250
+ query_params = opts[:query_params] || {}
251
+
252
+ # header parameters
253
+ header_params = opts[:header_params] || {}
254
+ # HTTP header 'Accept' (if needed)
255
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
256
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
257
+
258
+ # form parameters
259
+ form_params = opts[:form_params] || {}
260
+
261
+ # http body (model)
262
+ post_body = opts[:debug_body]
263
+
264
+ # return_type
265
+ return_type = opts[:debug_return_type] || 'GetExperimentResultsResponse'
266
+
267
+ # auth_names
268
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
269
+
270
+ new_options = opts.merge(
271
+ :operation => :"ExperimentsApi.get_experiment_results",
272
+ :header_params => header_params,
273
+ :query_params => query_params,
274
+ :form_params => form_params,
275
+ :body => post_body,
276
+ :auth_names => auth_names,
277
+ :return_type => return_type
278
+ )
279
+
280
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
281
+ if @api_client.config.debugging
282
+ @api_client.config.logger.debug "API called: ExperimentsApi#get_experiment_results\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
283
+ end
284
+ return data, status_code, headers
285
+ end
286
+
287
+ # Get analysis timeseries
288
+ # Same row shape as `/results`, but returns every daily slice rather than the latest. Filter to a single metric with the `metric` query parameter. **Use case:** Drive a chart of metric movement over the experiment runtime, or sanity-check the lift is monotonic before deciding.
289
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
290
+ # @param [Hash] opts the optional parameters
291
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
292
+ # @option opts [String] :metric Optional metric name to filter the series.
293
+ # @return [GetExperimentTimeseriesResponse]
294
+ def get_experiment_timeseries(id, opts = {})
295
+ data, _status_code, _headers = get_experiment_timeseries_with_http_info(id, opts)
296
+ data
297
+ end
298
+
299
+ # Get analysis timeseries
300
+ # Same row shape as &#x60;/results&#x60;, but returns every daily slice rather than the latest. Filter to a single metric with the &#x60;metric&#x60; query parameter. **Use case:** Drive a chart of metric movement over the experiment runtime, or sanity-check the lift is monotonic before deciding.
301
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
302
+ # @param [Hash] opts the optional parameters
303
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
304
+ # @option opts [String] :metric Optional metric name to filter the series.
305
+ # @return [Array<(GetExperimentTimeseriesResponse, Integer, Hash)>] GetExperimentTimeseriesResponse data, response status code and response headers
306
+ def get_experiment_timeseries_with_http_info(id, opts = {})
307
+ if @api_client.config.debugging
308
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.get_experiment_timeseries ...'
309
+ end
310
+ # verify the required parameter 'id' is set
311
+ if @api_client.config.client_side_validation && id.nil?
312
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.get_experiment_timeseries"
313
+ end
314
+ # resource path
315
+ local_var_path = '/api/admin/experiments/{id}/timeseries'.sub('{id}', CGI.escape(id.to_s))
316
+
317
+ # query parameters
318
+ query_params = opts[:query_params] || {}
319
+ query_params[:'metric'] = opts[:'metric'] if !opts[:'metric'].nil?
320
+
321
+ # header parameters
322
+ header_params = opts[:header_params] || {}
323
+ # HTTP header 'Accept' (if needed)
324
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
325
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
326
+
327
+ # form parameters
328
+ form_params = opts[:form_params] || {}
329
+
330
+ # http body (model)
331
+ post_body = opts[:debug_body]
332
+
333
+ # return_type
334
+ return_type = opts[:debug_return_type] || 'GetExperimentTimeseriesResponse'
335
+
336
+ # auth_names
337
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
338
+
339
+ new_options = opts.merge(
340
+ :operation => :"ExperimentsApi.get_experiment_timeseries",
341
+ :header_params => header_params,
342
+ :query_params => query_params,
343
+ :form_params => form_params,
344
+ :body => post_body,
345
+ :auth_names => auth_names,
346
+ :return_type => return_type
347
+ )
348
+
349
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
350
+ if @api_client.config.debugging
351
+ @api_client.config.logger.debug "API called: ExperimentsApi#get_experiment_timeseries\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
352
+ end
353
+ return data, status_code, headers
354
+ end
355
+
356
+ # List experiments
357
+ # Returns a single page of non-archived experiments ordered by `updated_at desc, id desc`. Use the `cursor` query parameter to paginate. **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`.
358
+ # @param [Hash] opts the optional parameters
359
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
360
+ # @option opts [Integer] :limit Page size (1–500). Defaults to 100. (default to 100)
361
+ # @option opts [String] :cursor Opaque cursor returned in the previous page&#39;s &#x60;next_cursor&#x60;. Omit for the first page.
362
+ # @return [ListExperimentsResponse]
363
+ def list_experiments(opts = {})
364
+ data, _status_code, _headers = list_experiments_with_http_info(opts)
365
+ data
366
+ end
367
+
368
+ # List experiments
369
+ # Returns a single page of non-archived experiments ordered by &#x60;updated_at desc, id desc&#x60;. Use the &#x60;cursor&#x60; query parameter to paginate. **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 &#x60;min_runtime_days&#x60;.
370
+ # @param [Hash] opts the optional parameters
371
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
372
+ # @option opts [Integer] :limit Page size (1–500). Defaults to 100. (default to 100)
373
+ # @option opts [String] :cursor Opaque cursor returned in the previous page&#39;s &#x60;next_cursor&#x60;. Omit for the first page.
374
+ # @return [Array<(ListExperimentsResponse, Integer, Hash)>] ListExperimentsResponse data, response status code and response headers
375
+ def list_experiments_with_http_info(opts = {})
376
+ if @api_client.config.debugging
377
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.list_experiments ...'
378
+ end
379
+ if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] > 500
380
+ fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling ExperimentsApi.list_experiments, must be smaller than or equal to 500.'
381
+ end
382
+
383
+ if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] < 1
384
+ fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling ExperimentsApi.list_experiments, must be greater than or equal to 1.'
385
+ end
386
+
387
+ # resource path
388
+ local_var_path = '/api/admin/experiments'
389
+
390
+ # query parameters
391
+ query_params = opts[:query_params] || {}
392
+ query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
393
+ query_params[:'cursor'] = opts[:'cursor'] if !opts[:'cursor'].nil?
394
+
395
+ # header parameters
396
+ header_params = opts[:header_params] || {}
397
+ # HTTP header 'Accept' (if needed)
398
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
399
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
400
+
401
+ # form parameters
402
+ form_params = opts[:form_params] || {}
403
+
404
+ # http body (model)
405
+ post_body = opts[:debug_body]
406
+
407
+ # return_type
408
+ return_type = opts[:debug_return_type] || 'ListExperimentsResponse'
409
+
410
+ # auth_names
411
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
412
+
413
+ new_options = opts.merge(
414
+ :operation => :"ExperimentsApi.list_experiments",
415
+ :header_params => header_params,
416
+ :query_params => query_params,
417
+ :form_params => form_params,
418
+ :body => post_body,
419
+ :auth_names => auth_names,
420
+ :return_type => return_type
421
+ )
422
+
423
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
424
+ if @api_client.config.debugging
425
+ @api_client.config.logger.debug "API called: ExperimentsApi#list_experiments\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
426
+ end
427
+ return data, status_code, headers
428
+ end
429
+
430
+ # Re-queue analysis
431
+ # 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. **Use case:** Force-refresh results after wiring up a new metric without waiting for the next nightly cron tick.
432
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
433
+ # @param [Hash] opts the optional parameters
434
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
435
+ # @return [ReanalyzeExperimentResponse]
436
+ def reanalyze_experiment(id, opts = {})
437
+ data, _status_code, _headers = reanalyze_experiment_with_http_info(id, opts)
438
+ data
439
+ end
440
+
441
+ # Re-queue analysis
442
+ # 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. **Use case:** Force-refresh results after wiring up a new metric without waiting for the next nightly cron tick.
443
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
444
+ # @param [Hash] opts the optional parameters
445
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
446
+ # @return [Array<(ReanalyzeExperimentResponse, Integer, Hash)>] ReanalyzeExperimentResponse data, response status code and response headers
447
+ def reanalyze_experiment_with_http_info(id, opts = {})
448
+ if @api_client.config.debugging
449
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.reanalyze_experiment ...'
450
+ end
451
+ # verify the required parameter 'id' is set
452
+ if @api_client.config.client_side_validation && id.nil?
453
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.reanalyze_experiment"
454
+ end
455
+ # resource path
456
+ local_var_path = '/api/admin/experiments/{id}/reanalyze'.sub('{id}', CGI.escape(id.to_s))
457
+
458
+ # query parameters
459
+ query_params = opts[:query_params] || {}
460
+
461
+ # header parameters
462
+ header_params = opts[:header_params] || {}
463
+ # HTTP header 'Accept' (if needed)
464
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
465
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
466
+
467
+ # form parameters
468
+ form_params = opts[:form_params] || {}
469
+
470
+ # http body (model)
471
+ post_body = opts[:debug_body]
472
+
473
+ # return_type
474
+ return_type = opts[:debug_return_type] || 'ReanalyzeExperimentResponse'
475
+
476
+ # auth_names
477
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
478
+
479
+ new_options = opts.merge(
480
+ :operation => :"ExperimentsApi.reanalyze_experiment",
481
+ :header_params => header_params,
482
+ :query_params => query_params,
483
+ :form_params => form_params,
484
+ :body => post_body,
485
+ :auth_names => auth_names,
486
+ :return_type => return_type
487
+ )
488
+
489
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
490
+ if @api_client.config.debugging
491
+ @api_client.config.logger.debug "API called: ExperimentsApi#reanalyze_experiment\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
492
+ end
493
+ return data, status_code, headers
494
+ end
495
+
496
+ # Attach metrics
497
+ # Replaces the experiment's metric attachments wholesale. Each entry pairs an existing `metric_id` with a `role` (`goal` / `guardrail` / `secondary`). Returns `422` if any `metric_id` doesn't exist in the project. Pass `{ metrics: [] }` to detach everything. **Use cases** - **Standard setup** — one `goal`, one or two `guardrail`, optional `secondary` metrics for diagnostics. - **Detach all** — send `{ \"metrics\": [] }` before archiving.
498
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
499
+ # @param set_experiment_metrics_request [SetExperimentMetricsRequest]
500
+ # @param [Hash] opts the optional parameters
501
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
502
+ # @return [SetExperimentMetricsResponse]
503
+ def set_experiment_metrics(id, set_experiment_metrics_request, opts = {})
504
+ data, _status_code, _headers = set_experiment_metrics_with_http_info(id, set_experiment_metrics_request, opts)
505
+ data
506
+ end
507
+
508
+ # Attach metrics
509
+ # Replaces the experiment&#39;s metric attachments wholesale. Each entry pairs an existing &#x60;metric_id&#x60; with a &#x60;role&#x60; (&#x60;goal&#x60; / &#x60;guardrail&#x60; / &#x60;secondary&#x60;). Returns &#x60;422&#x60; if any &#x60;metric_id&#x60; doesn&#39;t exist in the project. Pass &#x60;{ metrics: [] }&#x60; to detach everything. **Use cases** - **Standard setup** — one &#x60;goal&#x60;, one or two &#x60;guardrail&#x60;, optional &#x60;secondary&#x60; metrics for diagnostics. - **Detach all** — send &#x60;{ \&quot;metrics\&quot;: [] }&#x60; before archiving.
510
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
511
+ # @param set_experiment_metrics_request [SetExperimentMetricsRequest]
512
+ # @param [Hash] opts the optional parameters
513
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
514
+ # @return [Array<(SetExperimentMetricsResponse, Integer, Hash)>] SetExperimentMetricsResponse data, response status code and response headers
515
+ def set_experiment_metrics_with_http_info(id, set_experiment_metrics_request, opts = {})
516
+ if @api_client.config.debugging
517
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.set_experiment_metrics ...'
518
+ end
519
+ # verify the required parameter 'id' is set
520
+ if @api_client.config.client_side_validation && id.nil?
521
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.set_experiment_metrics"
522
+ end
523
+ # verify the required parameter 'set_experiment_metrics_request' is set
524
+ if @api_client.config.client_side_validation && set_experiment_metrics_request.nil?
525
+ fail ArgumentError, "Missing the required parameter 'set_experiment_metrics_request' when calling ExperimentsApi.set_experiment_metrics"
526
+ end
527
+ # resource path
528
+ local_var_path = '/api/admin/experiments/{id}/metrics'.sub('{id}', CGI.escape(id.to_s))
529
+
530
+ # query parameters
531
+ query_params = opts[:query_params] || {}
532
+
533
+ # header parameters
534
+ header_params = opts[:header_params] || {}
535
+ # HTTP header 'Accept' (if needed)
536
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
537
+ # HTTP header 'Content-Type'
538
+ content_type = @api_client.select_header_content_type(['application/json'])
539
+ if !content_type.nil?
540
+ header_params['Content-Type'] = content_type
541
+ end
542
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
543
+
544
+ # form parameters
545
+ form_params = opts[:form_params] || {}
546
+
547
+ # http body (model)
548
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(set_experiment_metrics_request)
549
+
550
+ # return_type
551
+ return_type = opts[:debug_return_type] || 'SetExperimentMetricsResponse'
552
+
553
+ # auth_names
554
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
555
+
556
+ new_options = opts.merge(
557
+ :operation => :"ExperimentsApi.set_experiment_metrics",
558
+ :header_params => header_params,
559
+ :query_params => query_params,
560
+ :form_params => form_params,
561
+ :body => post_body,
562
+ :auth_names => auth_names,
563
+ :return_type => return_type
564
+ )
565
+
566
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
567
+ if @api_client.config.debugging
568
+ @api_client.config.logger.debug "API called: ExperimentsApi#set_experiment_metrics\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
569
+ end
570
+ return data, status_code, headers
571
+ end
572
+
573
+ # Transition experiment status
574
+ # Drives the experiment lifecycle. Allowed transitions: - `draft → running` — starts allocation. Bumps the `startedAt` timestamp. - `running → stopped` — halts allocation. Existing exposures stay in the dataset. - `stopped → archived` — soft-delete. - `draft → archived` — discard an unstarted experiment. - `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. 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`. **Use cases** - **Start** — `{ \"status\": \"running\" }` after wiring up the SDK and verifying targeting on staging. - **Stop** — `{ \"status\": \"stopped\" }` once the experiment hits its `min_runtime_days` and conclusive results land. - **Archive** — `{ \"status\": \"archived\" }` to soft-delete after sign-off.
575
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
576
+ # @param set_experiment_status_request [SetExperimentStatusRequest]
577
+ # @param [Hash] opts the optional parameters
578
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
579
+ # @return [SetExperimentStatusResponse]
580
+ def set_experiment_status(id, set_experiment_status_request, opts = {})
581
+ data, _status_code, _headers = set_experiment_status_with_http_info(id, set_experiment_status_request, opts)
582
+ data
583
+ end
584
+
585
+ # Transition experiment status
586
+ # Drives the experiment lifecycle. Allowed transitions: - &#x60;draft → running&#x60; — starts allocation. Bumps the &#x60;startedAt&#x60; timestamp. - &#x60;running → stopped&#x60; — halts allocation. Existing exposures stay in the dataset. - &#x60;stopped → archived&#x60; — soft-delete. - &#x60;draft → archived&#x60; — discard an unstarted experiment. - &#x60;archived → draft&#x60; — 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. Restarting an &#x60;archived&#x60; experiment directly is not allowed — restore it to &#x60;draft&#x60; first. Returns &#x60;409&#x60; on illegal transitions and &#x60;429&#x60; if the plan&#39;s &#x60;experiments_running&#x60; limit is exceeded on &#x60;→ running&#x60;. **Use cases** - **Start** — &#x60;{ \&quot;status\&quot;: \&quot;running\&quot; }&#x60; after wiring up the SDK and verifying targeting on staging. - **Stop** — &#x60;{ \&quot;status\&quot;: \&quot;stopped\&quot; }&#x60; once the experiment hits its &#x60;min_runtime_days&#x60; and conclusive results land. - **Archive** — &#x60;{ \&quot;status\&quot;: \&quot;archived\&quot; }&#x60; to soft-delete after sign-off.
587
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
588
+ # @param set_experiment_status_request [SetExperimentStatusRequest]
589
+ # @param [Hash] opts the optional parameters
590
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
591
+ # @return [Array<(SetExperimentStatusResponse, Integer, Hash)>] SetExperimentStatusResponse data, response status code and response headers
592
+ def set_experiment_status_with_http_info(id, set_experiment_status_request, opts = {})
593
+ if @api_client.config.debugging
594
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.set_experiment_status ...'
595
+ end
596
+ # verify the required parameter 'id' is set
597
+ if @api_client.config.client_side_validation && id.nil?
598
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.set_experiment_status"
599
+ end
600
+ # verify the required parameter 'set_experiment_status_request' is set
601
+ if @api_client.config.client_side_validation && set_experiment_status_request.nil?
602
+ fail ArgumentError, "Missing the required parameter 'set_experiment_status_request' when calling ExperimentsApi.set_experiment_status"
603
+ end
604
+ # resource path
605
+ local_var_path = '/api/admin/experiments/{id}/status'.sub('{id}', CGI.escape(id.to_s))
606
+
607
+ # query parameters
608
+ query_params = opts[:query_params] || {}
609
+
610
+ # header parameters
611
+ header_params = opts[:header_params] || {}
612
+ # HTTP header 'Accept' (if needed)
613
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
614
+ # HTTP header 'Content-Type'
615
+ content_type = @api_client.select_header_content_type(['application/json'])
616
+ if !content_type.nil?
617
+ header_params['Content-Type'] = content_type
618
+ end
619
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
620
+
621
+ # form parameters
622
+ form_params = opts[:form_params] || {}
623
+
624
+ # http body (model)
625
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(set_experiment_status_request)
626
+
627
+ # return_type
628
+ return_type = opts[:debug_return_type] || 'SetExperimentStatusResponse'
629
+
630
+ # auth_names
631
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
632
+
633
+ new_options = opts.merge(
634
+ :operation => :"ExperimentsApi.set_experiment_status",
635
+ :header_params => header_params,
636
+ :query_params => query_params,
637
+ :form_params => form_params,
638
+ :body => post_body,
639
+ :auth_names => auth_names,
640
+ :return_type => return_type
641
+ )
642
+
643
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
644
+ if @api_client.config.debugging
645
+ @api_client.config.logger.debug "API called: ExperimentsApi#set_experiment_status\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
646
+ end
647
+ return data, status_code, headers
648
+ end
649
+
650
+ # Update an experiment
651
+ # Partial update. `allocation_pct`, `groups`, `salt`, `universe`, `params` are **immutable while running** — returns `409` if you try. Stop the experiment first. Editing `groups` while in `draft` is fine; weights must still sum to 10000. **Use cases** - **Update metadata** — `description`, `tag`, `targeting_gate` editable any time. - **Ramp before launch** — set `allocation_pct` while still in `draft`. - **Tighten significance** — `significance_threshold` (Pro+). - **Rewire groups** — replace `groups` wholesale while in `draft`; immutable once running.
652
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
653
+ # @param update_experiment_request [UpdateExperimentRequest]
654
+ # @param [Hash] opts the optional parameters
655
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
656
+ # @return [UpdateExperimentResponse]
657
+ def update_experiment(id, update_experiment_request, opts = {})
658
+ data, _status_code, _headers = update_experiment_with_http_info(id, update_experiment_request, opts)
659
+ data
660
+ end
661
+
662
+ # Update an experiment
663
+ # Partial update. &#x60;allocation_pct&#x60;, &#x60;groups&#x60;, &#x60;salt&#x60;, &#x60;universe&#x60;, &#x60;params&#x60; are **immutable while running** — returns &#x60;409&#x60; if you try. Stop the experiment first. Editing &#x60;groups&#x60; while in &#x60;draft&#x60; is fine; weights must still sum to 10000. **Use cases** - **Update metadata** — &#x60;description&#x60;, &#x60;tag&#x60;, &#x60;targeting_gate&#x60; editable any time. - **Ramp before launch** — set &#x60;allocation_pct&#x60; while still in &#x60;draft&#x60;. - **Tighten significance** — &#x60;significance_threshold&#x60; (Pro+). - **Rewire groups** — replace &#x60;groups&#x60; wholesale while in &#x60;draft&#x60;; immutable once running.
664
+ # @param id [String] Stable opaque experiment id (&#x60;exp_…&#x60;) or the experiment&#39;s &#x60;name&#x60;.
665
+ # @param update_experiment_request [UpdateExperimentRequest]
666
+ # @param [Hash] opts the optional parameters
667
+ # @option opts [String] :x_project_id Project the request operates on. Optional — defaults to the project the SDK key belongs to; pass it only to scope a multi-project key (the generated client sets it once from its configuration, so per-call callers never thread it).
668
+ # @return [Array<(UpdateExperimentResponse, Integer, Hash)>] UpdateExperimentResponse data, response status code and response headers
669
+ def update_experiment_with_http_info(id, update_experiment_request, opts = {})
670
+ if @api_client.config.debugging
671
+ @api_client.config.logger.debug 'Calling API: ExperimentsApi.update_experiment ...'
672
+ end
673
+ # verify the required parameter 'id' is set
674
+ if @api_client.config.client_side_validation && id.nil?
675
+ fail ArgumentError, "Missing the required parameter 'id' when calling ExperimentsApi.update_experiment"
676
+ end
677
+ # verify the required parameter 'update_experiment_request' is set
678
+ if @api_client.config.client_side_validation && update_experiment_request.nil?
679
+ fail ArgumentError, "Missing the required parameter 'update_experiment_request' when calling ExperimentsApi.update_experiment"
680
+ end
681
+ # resource path
682
+ local_var_path = '/api/admin/experiments/{id}'.sub('{id}', CGI.escape(id.to_s))
683
+
684
+ # query parameters
685
+ query_params = opts[:query_params] || {}
686
+
687
+ # header parameters
688
+ header_params = opts[:header_params] || {}
689
+ # HTTP header 'Accept' (if needed)
690
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
691
+ # HTTP header 'Content-Type'
692
+ content_type = @api_client.select_header_content_type(['application/json'])
693
+ if !content_type.nil?
694
+ header_params['Content-Type'] = content_type
695
+ end
696
+ header_params[:'X-Project-Id'] = opts[:'x_project_id'] if !opts[:'x_project_id'].nil?
697
+
698
+ # form parameters
699
+ form_params = opts[:form_params] || {}
700
+
701
+ # http body (model)
702
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(update_experiment_request)
703
+
704
+ # return_type
705
+ return_type = opts[:debug_return_type] || 'UpdateExperimentResponse'
706
+
707
+ # auth_names
708
+ auth_names = opts[:debug_auth_names] || ['bearerSdkKey']
709
+
710
+ new_options = opts.merge(
711
+ :operation => :"ExperimentsApi.update_experiment",
712
+ :header_params => header_params,
713
+ :query_params => query_params,
714
+ :form_params => form_params,
715
+ :body => post_body,
716
+ :auth_names => auth_names,
717
+ :return_type => return_type
718
+ )
719
+
720
+ data, status_code, headers = @api_client.call_api(:PATCH, local_var_path, new_options)
721
+ if @api_client.config.debugging
722
+ @api_client.config.logger.debug "API called: ExperimentsApi#update_experiment\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
723
+ end
724
+ return data, status_code, headers
725
+ end
726
+ end
727
+ end