---
title: "Start splitting shoppers"
method: POST
path: "/v1/experiments/{experiment_id}/start"
tags: ["experiments"]
---

# Start splitting shoppers

`POST /v1/experiments/{experiment_id}/start`

## Request

- Base URL: `https://api.octaneai.com`
- URL: `https://api.octaneai.com/v1/experiments/{experiment_id}/start`
- Auth: HTTP bearer

## Path parameters

- `experiment_id` string, required

## Request body

- StartRequest
  - `confirm` true, required

## Response `200`

The experiment after the action. Start and end require confirm: true.

- ExperimentResponse
  - `id` string, required
  - `app_id` string, required
  - `name` string, required
  - `status` 'draft' | 'running' | 'waiting' | 'ended', required: draft: set up, not started. running: shoppers are being split. waiting: still splitting, automatic decisions paused. ended: no longer assigning.
  - `decision_metric` string, required: completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
  - `decision_target` object, nullable: What a targeted metric points at: reached_page {mode: specific | after, page_key}, button_clicked {page_key, component_key}, chose_answer {page_key, component_key, option_id}; null for any other metric
  - `decision_option` 'manual' | 'when_clear' | 'on_date' | 'ai', required: manual: the merchant decides. when_clear: publish at the first clear result. on_date: decide on a date. ai: the AI decides.
  - `ai_trigger` 'when_clear' | 'on_date'
  - `decision_date` string, date, nullable: The day the test decides, read in timezone, at least seven days out; null when it decides on no date
  - `decides_at` string, date-time, nullable: decision_date as an instant, midnight at its start in timezone, UTC ISO 8601; null without a date
  - `timezone` string, required: IANA name of the timezone decision_date is read in
  - `fallback` 'keep' | 'revert' | 'notify', required: What happens on the date without a clear result: keep running, put the live version back, or tell the merchant and wait.
  - `ai_max_runs` integer, nullable: How many times the AI may run before it stops; null lets it run as often as the test asks
  - `ai_fallback` 'when_clear' | 'notify', required: What the test does once the AI has run ai_max_runs times without ending it: decide at the first clear result without the AI, or tell the merchant and wait.
  - `revenue_tiers` string[], required: The kinds of revenue counted: added_from_quiz | shown_bought_later | bought_not_shown
  - `protect_metrics` string[], required: The metrics the test watches for harm: completion_rate | email_opt_in | order_conversion | rpv | aov | phone_opt_in | reached_page | product_page_clicked | custom_url_clicked | button_clicked | chose_answer
  - `weekly_digest` boolean, required: Whether a weekly email reports where the test stands
  - `long_run_reminders` boolean, required: Whether reminder emails go out six weeks after the start and every two weeks after until it ends
  - `merchant_note` string, nullable: A note our AI weighs when it decides, up to 2000 characters: context, never an order
  - `period` integer, required: The current counting period: 0 on a draft, 1 once started, one higher each time a new one opens
  - `period_started_at` string, date-time, nullable: When the current counting period began, UTC ISO 8601; null on a draft
  - `period_reason` 'started' | 'split_changed' | 'control_published' | 'variant_republished' | 'metric_changed' | 'revenue_tiers_changed', required: Why a counting period began.
  - `clear_since_at` string, date-time, nullable: When the decision metric first read clear in this counting period, UTC ISO 8601; null until then
  - `srm_flagged_at` string, date-time, nullable: When the split check found shoppers not landing in the versions as set, UTC ISO 8601; null while healthy
  - `ai_verdict` 'publish' | 'keep_running' | 'no_change': What the AI decided last, as the trusted decide path accepted it; a refused verdict lives on the timeline only.
  - `ai_rationale` string, nullable: Our AI's reasoning for its last decision; null before it has decided
  - `winner_arm_id` string, nullable
  - `ended_by` 'manual' | 'auto' | 'ai' | 'fallback_revert'
  - `ended_at` string, date-time, nullable
  - `outcome` 'winner_manual' | 'winner_auto' | 'winner_ai' | 'ai_no_change' | 'ai_recommended' | 'ai_keep_running' | 'ai_blocked_credits' | 'srm_flagged' | 'no_winner_notify' | 'reverted' | 'plan_downgraded' | 'ended_manual' | 'cancelled': How a test ended, in one word.
  - `revision` integer, required: A number that goes up with every change to the test
  - `started_at` string, date-time, nullable
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `arms` ExperimentArmResponse[], required
    - `id` string, required
    - `position` integer, required: 0 for the live version, 1 for the variant
    - `label` string, required
    - `weight` integer, required: The arm's share of the split, a whole number weighed against the other arm's
    - `version_id` string, required
    - `version_number` integer, required
    - `is_control` boolean, required

## Other responses

- `401`: The key is missing, malformed, revoked or expired.
- `403`: The store's plan has no API access, or the key lacks the scope.
- `404`: Not found
- `409`: Only a draft test can be started.
- `422`: Automatic decisions wait a full seven days, whatever the numbers look like earlier.
- `429`: The key's or the store's bucket is full; Retry-After says when to try again.
- `503`: Request limits cannot be checked right now; retry shortly.
- `504`: The request timed out.

---

[API](https://skmtc.dev/octaneai/apis/octane-ai-merchant-api.md) - [All operations](https://skmtc.dev/octaneai/apis/octane-ai-merchant-api/llms.txt) - [OpenAPI document](https://skmtc.dev/octaneai/apis/octane-ai-merchant-api/revisions/dc2d1aa2b7c6?raw)
