# Lifecycle and approvals

Every experiment moves through a small set of statuses. Launch-type actions (anything that changes what live visitors see) can require a person's approval, and every launch runs a checklist first.

## Statuses

| Status | Meaning |
|---|---|
| `draft` | Being built. Nothing reaches visitors except through [preview links](qa-and-preview.md). |
| `scheduled` | Will start at `start_at`. |
| `running` | Visitors are being split and counted. |
| `paused` | Out of your site for now. Visitors who saw it keep their variation for when it resumes. Conversions while paused are not counted. |
| `stopped` | Finished with a decision. The final results are kept. |
| `shipped` | The winning variation is shown to every targeted visitor, without counting, until you build it into your site. |
| `archived` | Put away. Unarchive returns it to its previous status. |

## Actions

| Action | From | To | Needs launch permission |
|---|---|---|---|
| Launch (`start`) | draft | running, or scheduled when `start_at` is in the future | yes |
| Pause | running | paused | no, never needs approval |
| Pause (unschedule) | scheduled | draft | no |
| Resume | paused | running | yes |
| Change traffic | running, paused | same | yes |
| Stop, keep the control | running, paused | stopped | yes |
| Stop and ship a variation | running, paused, stopped | shipped | yes |
| End rollout | shipped | stopped | yes |
| Archive | draft, stopped | archived | no |
| Unarchive | archived | previous status | no |
| Duplicate | any | a new draft | no |
| Delete | draft, archived | gone | see [Delete](#delete) |

TryFast moves experiments itself in three cases, and says why in the experiment's status reason: at the end date (`end_at`) a running experiment pauses (`schedule_end`); a scheduled experiment whose launch checklist fails at its start time goes back to draft (`preflight_failed`); and an unsaved workspace that pauses after 30 days without use pauses its experiments (`workspace_frozen`).

Launches, pauses and stops reach every visitor within 2 minutes.

## Launch

Launching freezes what the statistics depend on: the planned sample size, the audience, the goals' revenue caps and the statistics settings. From then on only names, secondary goals and the end date change ([what can change](index.md#what-you-can-change-and-when)).

### Preflight checks

Every launch, resume and scheduled start runs these checks first, and so does every approval request. A failure blocks the launch (`422 preflight_failed` with the list); a warning does not. `GET /api/v1/experiments/{id}/preflight` runs them without launching.

| Check | Fails when | Warns when |
|---|---|---|
| `compile` | A piece of code, a selector or a regular expression is invalid, or a change is unsafe. | |
| `variations` | Fewer than 2 or more than 8 variations, not exactly one control, weights not adding up to 10,000, duplicate keys, a split URL variation without a redirect, or a redirect back into the experiment's own pages. | Every variation equals the control (an A/A test). |
| `redirect_off_domain` | A redirect leaves the project's domains or the site it starts on. | |
| `hypothesis` | The hypothesis is empty. | |
| `primary_goal` | There is no primary goal, or it is archived. | |
| `plan_limits` | The workspace is at its limit of running experiments, or paused. | More than 80% of the monthly tested users are used. |
| `claim_required` | A workspace without an account would launch custom JavaScript. | |
| `bundle_size` | The project's script would exceed 200 KB uncompressed. | It would exceed 30 KB compressed. |
| `domains` | The project has no domain, or a page rule names a host outside them. | |
| `snippet_seen` | | The snippet was not loaded and no page view arrived in the last 24 hours. |
| `goal_seen` | | The primary goal had no conversion in the last 7 days. |
| `overlap` | | Another running experiment of the project targets overlapping pages. |
| `sample_size` | | The estimated duration is over 60 days, or the baseline conversion rate is unknown. |
| `consent` | | The snippet loads often but no visitor has consented: the cookie banner is probably not connected. |

## Approvals

People with launch permission act directly. So do API keys and agents with **Full access** (`experiments:publish`). Everyone else, notably agents with the default permission, gets an approval request instead: `202` (API) or a tool result (MCP) with `status: "awaiting_approval"` and an `approve_url` such as `https://tryfast.eu/app/approve/apr_Mn2Bv3Cx4Z`.

- The approval page shows exactly what goes live: the complete definition, a diff, and preview links for every variation, valid 24 hours.
- **What you approve is what goes live.** The request stores the experiment's version and a fingerprint of its definition. Any change to the experiment replaces pending requests, and approving an outdated one answers `409 approval_stale`.
- Asking twice for the same thing returns the same request; asking for something different (another traffic share, for example) replaces it.
- The checklist runs before a request is created; a failing check returns `preflight_failed` and no request.
- Only people approve, from their browser. API keys and agents can never approve, including their own requests.
- Requests expire after 24 hours.
- Project settings that change your live site (domains, consent mode, global script and others) also go through approvals, and only owners and admins can approve those.

## Scheduling

Set `start_at` (and optionally `end_at`) to launch later. Times are UTC in the API; the app shows your local time. The scheduler checks every 15 seconds. At the start time the checklist runs again; on failure the experiment goes back to draft with an activity entry. At `end_at` the experiment pauses: pausing loses nothing, and you decide whether to stop or resume.

## Stop and ship

Stop an experiment with a decision:

- **Keep the control** (`keep_control`): the experiment leaves your site.
- **Ship a variation** (`ship_variation` with `variation_id`): the variation is shown to every visitor who matches the experiment's pages, trigger and audience, regardless of traffic and weights, without counting. Shipping is refused while the traffic split check fails ([Statistics](../statistics.md)).

The final results are saved at that moment with the verdict of that moment. A shipped variation keeps running from the TryFast script until you have built it into your site: the app shows its changes, CSS and JavaScript in readable form for your developers. Then **End rollout** (stop on a shipped experiment) removes it. Shipped experiments count as running for plan limits.

A stopped experiment cannot be restarted; duplicate it to test again.

Agents read `recommended_action` in the results and stop with exactly that decision when `safe_to_act` is true.

## Delete

- Experiments that never started (drafts, and drafts that were archived) can be deleted by anyone who can edit them, including agents.
- Experiments that ran can be deleted only by an owner or admin in the app, who confirms with the experiment key. Their results and visitor data are deleted. Agents and API keys cannot delete history; archive instead.
