# Create Experiment Review

> For AI agents: a documentation index is available at [/llms.txt](/llms.txt). Append `.md` to any page URL for markdown, or send `Accept: text/markdown`.

## Create Experiment Review

**POST** `/console/v1/experiments/{id}/reviews`

Full URL: `https://statsigapi.net/console/v1/experiments/{id}/reviews`

Create Experiment Review

## Authorizations

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| STATSIG-API-KEY | string | Yes | — | apiKey (header) |

## Path parameters

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| id (path) | string | Yes | — | — |

## Body (application/json)

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| type | string | Yes | — | The kind of experiment change the review proposes. Allowed values: start, stop, pause, restart, abandon, archive, delete, make_decision, rollout, schedule_rollout, reallocate, change_enabled_groups, unarchive, update_owners, update_team, update_settings, update_overrides, update_target_applications, update_allowed_reviewers, update_default_impact_multiplier, scheduled_start, scheduled_start_edit, disable_reviews_locally |
| description | string | No | — | Human-readable description of the proposed change. Optional; recorded empty when omitted (e.g. `update_owners`, mirroring the console owner-edit flow, which collects no description). Constraints: max length: 2000 |
| reviewer_ids | string[] | No | [] | User IDs to request review from. |
| reviewer_group_ids | string[] | No | [] | Reviewer group IDs to request review from. |
| reason | string | No | — | Optional reason recorded with the change, applied when committed (e.g. stop / pause / abandon / decision reason). Constraints: max length: 2000 |
| winning_group_id | string | No | — | For `make_decision`: the group to ship. Required. |
| remove_targeting | boolean | No | — | For `make_decision`: drop targeting on ship (default false). |
| remove_overrides | boolean | No | — | For `make_decision`: drop overrides on ship (default false). |
| start_date | string | No | — | For `start`: optional scheduled start date. |
| group_id | string | No | — | For `rollout` / `schedule_rollout`: the group to roll out. Required. |
| rollout_percentage | number | No | — | For `rollout`: the pass percentage to roll the group out to. Required. Constraints: format: double, min: 0, max: 100 |
| clear_phases | boolean | No | — | For `rollout`: clear any scheduled rollout phases (default false). |
| rollout_phases | object[] | No | — | For `schedule_rollout`: the ordered rollout phases to schedule. Required. |
| rollout_phases.percentage | number | Yes | — | Pass percentage for this phase (0–100). Constraints: min: 0, max: 100 |
| rollout_phases.time | number | No | — | Absolute start time of the phase (epoch ms). |
| rollout_phases.time_string | string | No | — | Human-readable start time of the phase. |
| rollout_phases.is_complete | boolean | No | — | Whether this phase is already complete (default false). |
| rollout_phases.phase_duration_ms | number | No | — | Duration of the phase, used for progressive rollouts. |
| enabled_group_names | string[] | No | — | For `change_enabled_groups`: group names to enable. |
| disabled_group_names | string[] | No | — | For `change_enabled_groups`: group names to disable. |
| owners | object[] | No | — | For `update_owners`: the replacement owner set. Required. |
| owners.owner_id | string | Yes | — | ID of the owner (user ID or SDK key ID). Constraints: min length: 1 |
| owners.owner_type | string | No | — | Kind of owner. Defaults to `user`. Allowed values: user, sdk_key |
| team_id | string | No | — | For `update_team`: the team to assign, or `null` to clear it. Constraints: nullable, min length: 1 |
| default_impact_multiplier | number | No | — | For `update_default_impact_multiplier`: the new multiplier. Required. Constraints: format: double |
| target_app_ids | string[] | No | — | For `update_target_applications`: the full set of target application IDs. Required. |
| allowed_reviewer_user_ids | string[] | No | — | For `update_allowed_reviewers`: the full set of allowed reviewer user IDs. |
| allowed_reviewer_group_ids | string[] | No | — | For `update_allowed_reviewers`: the full set of allowed reviewer group IDs. |
| start_time | integer | No | — | For `scheduled_start`: epoch-ms time to schedule the start. Required. Constraints: format: int64 |
| new_time | integer | No | — | For `scheduled_start_edit`: epoch-ms time to reschedule the start to. Required. Constraints: format: int64 |
| overrides | object[] | No | — | For `update_overrides`: the full set of gate/segment overrides. Omit to preserve the experiment’s current overrides; send `[]` to clear them. |
| overrides.type | string | Yes | — | Allowed values: gate, segment |
| overrides.group_id | string | Yes | — | — |
| overrides.name | string | Yes | — | — |
| overrides.environment | string | No | — | Constraints: nullable |
| id_overrides | object[] | No | — | For `update_overrides`: the full set of ID overrides. Omit to preserve the experiment’s current ID overrides; send `[]` to clear them. |
| id_overrides.ids | string[] | Yes | — | — |
| id_overrides.group_id | string | Yes | — | — |
| id_overrides.environment | string | No | — | Constraints: nullable |
| id_overrides.unit_type | string | No | — | Constraints: nullable |
| allow_overrides_in_pulse | boolean | No | — | For `update_overrides`: whether overridden units are included in Pulse. Omit to preserve the current setting. |
| settings | object | No | — | For `update_settings`: the full experiment settings payload, matching the `PATCH /console/v1/experiments/:id` body. Required for `update_settings`. Fields omitted from the payload fall back to the experiment’s current values. |
| settings.name | string | No | — | The display name of the experiment Constraints: min length: 3, max length: 100, pattern: ^[a-zA-Z0-9_\- ]*$ |
| settings.description | string | Yes | — | A helpful summary of what this experiment does Constraints: max length: 1000 |
| settings.idType | string | Yes | — | The type of ID which the experiment is based on |
| settings.secondaryIDType | string | No | — | The secondary ID type for the experiment used in WHN for ID resolution Constraints: nullable |
| settings.identifierMappingMode | string | No | — | The identifier mapping mode for the experiment used in WHN for ID resolution Allowed values: strictOneToOne, firstTouchOneToMany, lastTouchOneToMany |
| settings.identityResolutionSource | string | No | — | The identity resolution entity property source for the experiment used in WHN for ID resolution Constraints: nullable |
| settings.hypothesis | string | Yes | — | A statement that will be tested by this experiment |
| settings.links | object[] | No | — | Links to relevant documentation or resources |
| settings.links.url | string | Yes | — | The URL of the link Constraints: format: uri |
| settings.links.title | string | No | — | The title of the link |
| settings.externalEvents | object[] | No | — | — |
| settings.externalEvents.name | string | Yes | — | — |
| settings.externalEvents.timestamp | number | Yes | — | — |
| settings.groups | object[] | Yes | — | The test groups for your experiment |
| settings.groups.name | string | Yes | — | — |
| settings.groups.id | string | No | — | Constraints: nullable |
| settings.groups.size | number | Yes | — | Constraints: min: 0, max: 100 |
| settings.groups.parameterValues | object | Yes | — | A map of parameter name to the value this group serves. Sidecar (Visual Editor) experiments also return `sidecarURLFilters`, `sidecarDisableAutoRun`, `sidecarPrerunScript`, and `sidecarExperimentName` here, copied from the experiment itself on read. Sending them here does nothing; set them as experiment fields instead. |
| settings.groups.disabled | boolean | No | — | — |
| settings.groups.description | string | No | — | — |
| settings.groups.foreignGroupID | string | No | — | — |
| settings.groups.highlighted | boolean | No | — | Marks this experiment group as highlighted in analysis views. Highlighted groups are prioritized (shown first) and can be used to filter. |
| settings.controlGroupID | string | No | — | Optional control group ID |
| settings.allocation | number | Yes | — | Percent of layer allocated to this experiment Constraints: format: double, min: 0, max: 100 |
| settings.userBuckets | number[] | No | — | — |
| settings.primaryMetricTags | string[] | No | — | Primary metric tags for the experiment |
| settings.secondaryMetricTags | string[] | No | — | Secondary metric tags for the experiment |
| settings.primaryMetrics | object[] | No | — | Main metrics needed to evaluate your hypothesis |
| settings.primaryMetrics.name | string | Yes | — | The metric name. |
| settings.primaryMetrics.type | string | Yes | — | The metric type. |
| settings.primaryMetrics.direction | string | No | — | The expected direction for one-sided testing (a feature to only measure metric movements in a single direction) Allowed values: increase, decrease |
| settings.primaryMetrics.hypothesizedValue | number | No | — | The comparison value for the one-sample testing (a feature to use a fixed baseline as the control value) |
| settings.secondaryMetrics | object[] | No | — | Additional metrics to monitor that might impact the analysis or final decision of the experiment |
| settings.secondaryMetrics.name | string | Yes | — | The metric name. |
| settings.secondaryMetrics.type | string | Yes | — | The metric type. |
| settings.secondaryMetrics.direction | string | No | — | The expected direction for one-sided testing (a feature to only measure metric movements in a single direction) Allowed values: increase, decrease |
| settings.secondaryMetrics.hypothesizedValue | number | No | — | The comparison value for the one-sample testing (a feature to use a fixed baseline as the control value) |
| settings.otherMetrics | object[] | No | — | Additional metrics you want to investigate or learn from. The usual corrections applied to Primary and Secondary metrics are not applied to these. |
| settings.otherMetrics.name | string | Yes | — | The metric name. |
| settings.otherMetrics.type | string | Yes | — | The metric type. |
| settings.otherMetrics.direction | string | No | — | The expected direction for one-sided testing (a feature to only measure metric movements in a single direction) Allowed values: increase, decrease |
| settings.otherMetrics.hypothesizedValue | number | No | — | The comparison value for the one-sample testing (a feature to use a fixed baseline as the control value) |
| settings.targetApps | oneOf | No | — | Target apps assigned to this experiment Constraints: string, string[] |
| settings.tags | string[] | No | — | Tags associated with the experiment |
| settings.duration | integer | No | — | How long the experiment is expected to last in days Constraints: format: int64, min: 1 |
| settings.targetExposures | integer | No | — | Target exposures for the experiment Constraints: format: int64, min: 1 |
| settings.targetingGateID | string | Yes | — | Restrict your experiment to users passing the selected feature gate Constraints: nullable |
| settings.sequentialTesting | boolean | No | — | Apply sequential testing? |
| settings.bonferroniCorrection | boolean | Yes | — | Is Bonferroni correction applied per variant? |
| settings.bonferroniCorrectionPerMetric | boolean | No | — | Is Bonferroni correction applied per metric? |
| settings.benjaminiHochbergPerVariant | boolean | No | — | Is Benjamini-Hochberg procedure applied per variant? |
| settings.benjaminiHochbergPerMetric | boolean | No | — | Is Benjamini-Hochberg procedure applied per metric? |
| settings.benjaminiPrimaryMetricsOnly | boolean | No | — | Is Benjamini-Hochberg procedure applied for primary metrics only? |
| settings.defaultConfidenceInterval | string | Yes | — | Default error margin used for results Allowed values: 80, 90, 95, 98, 99 |
| settings.defaultRollupWindow | integer | No | — | Default rollup window in days for experiment results. Use -1 for cumulative. Only -1, 1, and 7 allowed for cloud experiments. Constraints: format: int64 |
| settings.defaultChanceToBeatThreshold | number | No | — | Default chance-to-beat threshold used for Bayesian results. Constraints: format: double |
| settings.bayesianPriors | object[] | No | — | Bayesian prior settings by metric. |
| settings.bayesianPriors.metric | object | Yes | — | — |
| settings.bayesianPriors.metric.name | string | Yes | — | — |
| settings.bayesianPriors.metric.type | string | Yes | — | — |
| settings.bayesianPriors.priorMean | number | Yes | — | — |
| settings.bayesianPriors.priorStdDev | number | Yes | — | Constraints: min: 0 |
| settings.manualQualityScores | object[] | No | — | Up to 10 manually set quality scores for an experiment. The scores and weights will be added to the existing weights and scores, and then weights will be renormalized to 100. This can be set via the Statsig Console API. If targeting a default check, the weight of the check will be updated, but not the status or description. A default score can be removed by setting the weight to 0. The default score identifiers are one of: HYPOTHESIS_LENGTH, BALANCED_EXPOSURE, PRIMARY_METRICS_LENGTH, COMPARISON_CORRECTION, GUARDRAIL_METRIC_TAGS, SUFFICIENT_SAMPLE, POWER_ANALYSIS, SEQUENTIAL_TESTING |
| settings.manualQualityScores.criteriaName | oneOf | Yes | — | Constraints: string, string |
| settings.manualQualityScores.status | string | Yes | — | Allowed values: PASSED, FAILED, WARNING |
| settings.manualQualityScores.criteriaDescription | string | Yes | — | — |
| settings.manualQualityScores.score | number | Yes | — | — |
| settings.manualQualityScores.weight | number | Yes | — | — |
| settings.status | string | Yes | — | The current status of the experiment Allowed values: active, setup, decision_made, abandoned, archived, experiment_stopped, assignment_stopped |
| settings.launchedGroupID | string | No | — | ID of the launched group, null otherwise Constraints: nullable |
| settings.assignmentSourceName | string | No | — | Source name of the assignment |
| settings.assignmentSourceExperimentName | string | No | — | Name of the source experiment for assignment |
| settings.creatorID | string | No | — | The Statsig ID of the creator of this experiment Constraints: nullable |
| settings.creatorEmail | string | No | — | The email of the creator of this experiment Constraints: nullable |
| settings.isAnalysisOnly | boolean | No | — | For Warehouse Native Constraints: nullable |
| settings.team | string | No | — | The team name associated with the experiment, Enterprise only. Constraints: nullable |
| settings.teamID | string | No | — | The team ID associated with the experiment, Enterprise only. Constraints: nullable |
| settings.allocationDuration | integer | No | — | Warehouse Native Only - Allocation duration in days Constraints: format: int64, nullable, min: 1 |
| settings.cohortedAnalysisDuration | integer | No | — | Warehouse Native Only - Cohorted analysis duration in days Constraints: format: int64, min: 1 |
| settings.cohortedMetricsMatureAfterEnd | boolean | No | — | Warehouse Native Only - Allow cohort metrics to mature after experiment end |
| settings.cohortWaitUntilEndToInclude | boolean | No | — | Warehouse Native Only - Whether to filter to units whose experiment cohort analysis duration is complete, if cohortedAnalysisDuration exists |
| settings.fixedAnalysisDuration | integer | No | — | Fixed analysis duration in days Constraints: format: int64, min: 1 |
| settings.scheduledReloadHour | integer | No | — | Warehouse Native only - UTC hour at which to run scheduled pulse loads Constraints: format: int64, nullable, min: 0, max: 23 |
| settings.scheduledReloadType | string | No | — | Warehouse Native only - reload type for scheduled reloads Allowed values: full, incremental |
| settings.scheduledReloadDays | integer[] | No | — | Warehouse Native only - days on which to run scheduled reloads from 0 to 6, 0 meaning Sunday. Null to run reloads on all days. Constraints: nullable |
| settings.turboMode | boolean | No | — | Warehouse Native only - whether to run scheduled reloads with Turbo mode. |
| settings.autoLoadToplineImpact | boolean | No | — | Warehouse Native only - whether to automatically run topline and projected launch impact calculations when reloading experiments. |
| settings.analysisEndTime | string | No | — | Warehouse Native only - end time for analysis only experiments |
| settings.assignmentSourceFilters | object[] | No | — | Array of criteria for filtering assignment sources. |
| settings.assignmentSourceFilters.column | string | No | — | Column to filter on. |
| settings.assignmentSourceFilters.condition | string | Yes | — | Allowed values: in, not_in, =, >, <, >=, <=, is_null, non_null, contains, not_contains, sql_filter, starts_with, ends_with, after_exposure, before_exposure, is_true, is_false |
| settings.assignmentSourceFilters.values | string[] | No | — | Optional array of values for the criterion to match against. |
| settings.analyticsType | string | No | — | The mode of analysis for the experiment, e.g frequentist, bayesian, sprt Allowed values: frequentist, bayesian, sprt |
| settings.defaultSPRTPowerParam | number | No | — | SPRT power parameter percentage used as the default for experiment analysis. Constraints: format: double |
| settings.defaultSPRTMDE | number | No | — | Default MDE value for every metric if one isn't provided. Only used in manual mode. Constraints: format: double |
| settings.sprtBaselineMode | string | No | — | In manual mode, mde/mean/stdDev must be provided for every metric in the experiment. In in_experiment_control, only the mde is needed for every metric, or the defaultSPRTMDE field must be passed. Allowed values: manual, in_experiment_control |
| settings.sprtMDESettings | object[] | No | — | The SPRT values for use in the experiment. |
| settings.sprtMDESettings.metricKey | string | Yes | — | — |
| settings.sprtMDESettings.groupSettings | object[] | Yes | — | — |
| settings.sprtMDESettings.groupSettings.groupKey | string | Yes | — | — |
| settings.sprtMDESettings.groupSettings.mde | number | Yes | — | — |
| settings.sprtMDESettings.groupSettings.mean | number | No | — | — |
| settings.sprtMDESettings.groupSettings.stdDev | number | No | — | — |
| settings.isSidecar | boolean | No | — | Whether this is a Statsig Sidecar experiment. `sidecarEditorURL`, `sidecarURLFilters`, `sidecarDisableAutoRun`, and `sidecarPrerunScript` are saved only when this is `true`. |
| settings.sidecarEditorURL | string | No | — | Sidecar (Visual Editor) only: the URL of the page being modified. The Visual Editor cannot open without it, and it must be an `http` or `https` URL. |
| settings.sidecarURLFilters | object[] | No | — | Sidecar (Visual Editor) only: filters on the current URL used to determine whether the experiment should be applied. Each entry looks like `{ "type": "contains", "value": "/pricing" }`, where `type` is `contains`, `equals`, `regex`, or `path`. Put `type` inside each filter object, not alongside the array. |
| settings.sidecarURLFilters.type | string | Yes | — | Allowed values: contains, equals, regex, path |
| settings.sidecarURLFilters.value | string | Yes | — | — |
| settings.sidecarDisableAutoRun | boolean | No | — | Sidecar (Visual Editor) only: whether to disable auto-running the experiment on page load. By default the experiment auto runs. |
| settings.sidecarPrerunScript | string | No | — | Sidecar (Visual Editor) only: a script to run before the experiment starts. Send `null` to clear it. Constraints: nullable |
| settings.decisionReason | string | No | — | Experiment notes reported after experiment completes |
| settings.preComputedUserDimensions | object[] | No | — | User dimensions that will be computed for every metric in WHN |
| settings.preComputedUserDimensions.propertySource | string | No | — | — |
| settings.preComputedUserDimensions.name | string | Yes | — | — |
| settings.cureCovariates | object[] | No | — | CURE Covariates to use in this experiment |
| settings.cureCovariates.name | string | Yes | — | — |
| settings.cureCovariates.type | string | Yes | — | — |
| settings.stratifiedSampling | object | No | — | The stratified sampling settings for the experiment Constraints: nullable |
| settings.stratifiedSampling.status | string | Yes | — | Allowed values: pending, success, error |
| settings.stratifiedSampling.metric | object | No | — | — |
| settings.stratifiedSampling.metric.name | string | Yes | — | — |
| settings.stratifiedSampling.metric.type | string | No | — | — |
| settings.stratifiedSampling.metric.startDate | string | Yes | — | — |
| settings.stratifiedSampling.metric.endDate | string | Yes | — | — |
| settings.stratifiedSampling.entityPropertySource | object | No | — | — |
| settings.stratifiedSampling.entityPropertySource.propertySourceName | string | Yes | — | — |
| settings.stratifiedSampling.entityPropertySource.column | string | Yes | — | — |
| settings.stratifiedSampling.csv | object | No | — | — |
| settings.stratifiedSampling.csv.original | string | Yes | — | — |
| settings.stratifiedSampling.csv.identifier | string | Yes | — | — |
| settings.stratifiedSampling.useStratifiedSalt | boolean | No | — | Whether successful stratified sampling is currently used for experiment assignment. |
| settings.stratifiedSampling.useUnits | boolean | No | — | Whether stratified sampling was configured to use allocated units directly. |
| settings.stratifiedSampling.deltaReduction | number | No | — | Observed reduction in delta after running stratified sampling. Constraints: format: double |
| settings.stratifiedSampling.spreadReduction | number | No | — | Observed reduction in spread after running stratified sampling. Constraints: format: double |
| settings.enabledNonProdEnvironments | string[] | No | — | — |

## Response (application/json)

**201** — The created experiment review.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| message | string | Yes | — | A simple string explaining the result of the operation. |
| data | object | Yes | — | — |
| data.review_id | string | Yes | — | Unique ID of the review. |
| data.status | string | Yes | — | Lifecycle status of the review. Allowed values: pending, accepted, rejected, committed, changes_requested, pending_webhook_validation, failed_webhook_validation, approved_webhook_validation |
| data.type | string | Yes | — | Kind of change the review proposes. Allowed values: start, stop, pause, restart, abandon, archive, delete, make_decision, update_settings, update_overrides, update_target_applications, update_allowed_reviewers, update_default_impact_multiplier, scheduled_start, scheduled_start_edit, disable_reviews_locally, rollout, schedule_rollout, reallocate, change_enabled_groups, unarchive, update_owners, update_team |
| data.author | object | Yes | — | The user who created the review. |
| data.author.id | string | Yes | — | — |
| data.author.email | string | Yes | — | Constraints: nullable |
| data.reviewers | object[] | Yes | — | Requested reviewers (users and groups). |
| data.reviewers.id | string | Yes | — | — |
| data.reviewers.kind | string | Yes | — | Allowed values: user, group |
| data.description | string | Yes | — | Human-readable description of the proposed change. |
| data.created_at | string | Yes | — | ISO-8601 timestamp of when the review was created. |
| data.content | object | No | — | The proposed change this review would apply, as `{ current, proposed }` over exactly the fields committing the review would write. `current` is the live value read at request time; where commit treats an unset argument as "leave unchanged", `proposed` repeats the live value rather than a default. Populated on single-review responses only — list responses omit it so a page of reviews does not pay an extra read per row. When the review does propose something but it could not be read back, `content` is PRESENT with `unavailable_reason` set and both value objects empty, never `null` — so "this type proposes nothing" stays distinguishable from "we cannot tell you what this would do". This surface's reasons are `review_data_unavailable` (the stored change data is missing or does not match the type the review declares; expected on legacy rows) and `content_unreadable` (the data is present but the before/after could not be assembled; a logged server-side fault). `null` when the review type is a bare action with no recoverable proposed value: `stop`, `pause`, `restart`, `reallocate`, `delete`, `disable_reviews_locally` (always), `start` (unless the review carries a backdated start date that commit will actually write — analysis-only experiments on warehouse-native projects), `scheduled_start_edit` when `new_time` is `ignore` (commit is a no-op), and `update_settings` on an autotune (the stored settings have no experiment-contract shape). Every other type carries content, including `archive`, `unarchive`, `update_owners`, `update_team`, `change_enabled_groups` and `update_allowed_reviewers`, for which the Console currently shows no before/after. Keys by type: `archive`/`unarchive` -> `archived`, `allocation` (archiving a layer-bound experiment zeroes its allocation); `abandon` -> `decision_note_title`, `decision_reason`; `start` -> `start_time`; `scheduled_start`/`scheduled_start_edit` -> `start_time`; `rollout` -> `group_id`, `rollout_percentage`, `rollout_phases`, `has_upcoming_automated_rollout`; `schedule_rollout` -> `group_id`, `rollout_phases`; `make_decision` -> `winning_group_id`, `decision_note_title`, `decision_reason`, and on experiments `overrides`, `id_overrides`, `inline_targeting_rules_json`, `targeting_gate_id`; `update_overrides` -> `overrides`, `id_overrides`, `allow_overrides_in_pulse`; `update_target_applications` -> `target_app_ids`; `update_default_impact_multiplier` -> `default_impact_multiplier`; `update_owners` -> `owners`; `update_team` -> `team_id`, `allowed_reviewer_user_ids`, `allowed_reviewer_group_ids` (moving to a team whose approval mode is `admin_only`/`team_only` widens who may approve future reviews); `update_allowed_reviewers` -> `allowed_reviewer_user_ids`, `allowed_reviewer_group_ids`; `change_enabled_groups` -> `groups` (the full list, with the delta applied); `update_settings` -> a single `settings` object holding the full resolved settings set, including `overrides`, `idOverrides`, `allowOverridesInPulse` and `customScorecardSections`. Constraints: nullable |
| data.content.type | string | Yes | — | Same value as the envelope `type`, repeated for self-containment. Allowed values: start, stop, pause, restart, abandon, archive, delete, make_decision, update_settings, update_overrides, update_target_applications, update_allowed_reviewers, update_default_impact_multiplier, scheduled_start, scheduled_start_edit, disable_reviews_locally, rollout, schedule_rollout, reallocate, change_enabled_groups, unarchive, update_owners, update_team |
| data.content.current | object | Yes | — | The entity's live value at read time, for each field this review type updates. Matches the Console's "Original Version (Before)" column for pending reviews. This is NOT status-dependent: for a committed or rejected review it is still the live entity as it stands now, which for a committed review normally equals `proposed`. |
| data.content.proposed | object | Yes | — | The value this review proposes — what commit will apply. Carries exactly the same keys as `current`. Array-valued fields carry the full array on both sides, never only the changed elements. |
| data.content.unavailable_reason | string | No | — | Present ONLY when the change could not be read back, in which case `current` and `proposed` are both empty objects and carry no meaning. This exists so that "this review type has nothing to propose" (`content: null`) is never confused with "we could not tell you what this review would do". `review_data_unavailable`: the review's stored change data is missing, or does not match the type the review declares — expected on legacy rows. `content_unreadable`: the data is present but the before/after could not be assembled; that is a server-side fault and is logged. Allowed values: review_data_unavailable, content_unreadable |

```json
{
  "message": "string",
  "data": {
    "review_id": "string",
    "status": "pending",
    "type": "start",
    "author": {
      "id": "string",
      "email": "string"
    },
    "reviewers": [
      {
        "id": "string",
        "kind": "user"
      }
    ],
    "description": "string",
    "created_at": "string",
    "content": {
      "type": "start",
      "current": {},
      "proposed": {},
      "unavailable_reason": "review_data_unavailable"
    }
  }
}
```

## Code samples

### cURL

```bash
curl -X POST "https://statsigapi.net/console/v1/experiments/{id}/reviews" \
  -H "Content-Type: application/json" \
  -H "STATSIG-API-KEY: YOUR_API_KEY"
```

### Python

```python
import requests

response = requests.post(
    "https://statsigapi.net/console/v1/experiments/{id}/reviews",
    headers={
        "Content-Type": "application/json",
        "STATSIG-API-KEY": "YOUR_API_KEY"
    }
)
data = response.json()
```

### JavaScript

```javascript
const response = await fetch("https://statsigapi.net/console/v1/experiments/{id}/reviews", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "STATSIG-API-KEY": "YOUR_API_KEY"
  }
});
const data = await response.json();
```

### PHP

```php
<?php
$ch = curl_init("https://statsigapi.net/console/v1/experiments/{id}/reviews");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "STATSIG-API-KEY: YOUR_API_KEY"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
```

### Go

```go
package main

import (
  "bytes"
  "net/http"
)

func main() {
req, _ := http.NewRequest("POST", "https://statsigapi.net/console/v1/experiments/{id}/reviews", nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("STATSIG-API-KEY", "YOUR_API_KEY")
  client := &http.Client{}
  resp, _ := client.Do(req)
  defer resp.Body.Close()
}
```

### Java

```java
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://statsigapi.net/console/v1/experiments/{id}/reviews"))
      .method("POST", HttpRequest.BodyPublishers.noBody())
.header("Content-Type", "application/json")
      .header("STATSIG-API-KEY", "YOUR_API_KEY")
      .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
```

### Ruby

```ruby
require "net/http"
require "json"

uri = URI("https://statsigapi.net/console/v1/experiments/{id}/reviews")
request = Net::HTTP::Post.new(uri)
request["Content-Type"] = "application/json"
request["STATSIG-API-KEY"] = "YOUR_API_KEY"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end
```
