> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Experiment

An Experiment is a feature flag or A/B test owned by an account. Treatments take stable percentage ranges of traffic and everyone else gets control, so growing an allocation never moves an existing user to another arm.

Use the Experiments API to create a draft, configure its weights, targeting, and resource bindings, then activate, pause, or end it, and to evaluate which arm a user, account, or anonymous visitor gets. Managing experiments requires `experiment:read` or `experiment:manage`; evaluation works without authentication.

## Endpoints

| Endpoint | Request |
| - | - |
| [List Experiments](/api-reference/beta/experiments/list-experiments) | <Badge color="blue" size="sm" stroke>GET</Badge> `/experiments` |
| [Retrieve Experiment](/api-reference/beta/experiments/retrieve-experiment) | <Badge color="blue" size="sm" stroke>GET</Badge> `/experiments/{id}` |
| [Evaluate Experiments](/api-reference/beta/experiments/evaluate-experiments) | <Badge color="blue" size="sm" stroke>GET</Badge> `/experiments/exposures` |
| [Create Experiment](/api-reference/beta/experiments/create-experiment) | <Badge color="green" size="sm" stroke>POST</Badge> `/experiments` |
| [Activate Experiment](/api-reference/beta/experiments/activate-experiment) | <Badge color="green" size="sm" stroke>POST</Badge> `/experiments/{id}/activate` |
| [End Experiment](/api-reference/beta/experiments/end-experiment) | <Badge color="green" size="sm" stroke>POST</Badge> `/experiments/{id}/end` |
| [Pause Experiment](/api-reference/beta/experiments/pause-experiment) | <Badge color="green" size="sm" stroke>POST</Badge> `/experiments/{id}/pause` |
| [Update Experiment](/api-reference/beta/experiments/update-experiment) | <Badge color="orange" size="sm" stroke>PATCH</Badge> `/experiments/{id}` |

## Attributes

<Columns cols={2}>
  <Column>
    <ResponseField name="id" type="string" required>
      Unique identifier for the experiment, prefixed `expt_`.
    </ResponseField>

    <ResponseField name="account_id" type="string" required>
      Owning account ID.
    </ResponseField>

    <ResponseField name="assignment_seed" type="string" required>
      Assignment hashes UTF-8 seed + subject ID with CRC32 modulo 100 and selects
      the stored end-exclusive range.
    </ResponseField>

    <ResponseField name="bucket_by" type="string | null">
      Randomization unit — `user` buckets each user independently, `account` buckets whole accounts (every user of an account gets the same arm). `null` for feature flags.

      Available options: `user`, `account`, `anonymous`
    </ResponseField>

    <ResponseField name="configuration_revision" type="integer" required>
      Revision of the serving configuration. Increments on every configuration
      change, so a cached definition with a lower revision is stale. Does not change
      the assignment seed.
    </ResponseField>

    <ResponseField name="control" type="object" required>
      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="related_resource" type="object | null">
          <Accordion title="Properties" defaultOpen={true}>
            <ResponseField name="id" type="string" required>
              Referenced resource tag, belonging to the experiment owner.
            </ResponseField>

            <ResponseField name="object" type="string" required>
              Available options: `app`, `app_build`, `product`, `plan`
            </ResponseField>
          </Accordion>
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="created_at" type="string | null">
      When the experiment was created, as an ISO 8601 timestamp.
    </ResponseField>

    <ResponseField name="created_by" type="string | null">
      ID of the user who created the experiment, prefixed `user_`. `null` for
      experiments created before creators were recorded.
    </ResponseField>

    <ResponseField name="ended_at" type="string | null">
      When the experiment stopped collecting data, as an ISO 8601 timestamp. `null`
      while still running.
    </ResponseField>

    <ResponseField name="feature_flag_only" type="boolean | null">
      `true` when this was created as a feature flag rather than a full experiment.
      Feature flags share the same evaluation API but do not collect metric results.
    </ResponseField>

    <ResponseField name="findings" type="string | null">
      What was learned and why this outcome, recorded when the experiment was ended.
      `null` until then.
    </ResponseField>

    <ResponseField name="flag_key" type="string" required>
      Developer-chosen handle referenced from code. Anywhere the API takes an
      experiment identifier, the `expt_` id and the flag\_key are interchangeable.
    </ResponseField>

    <ResponseField name="hypothesis" type="string | null">
      Hypothesis for this experiment. `null` when none is set, and always `null` for
      feature flags.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      Human-readable display name.
    </ResponseField>

    <ResponseField name="related_resource" type="object | null" required>
      Resource owned by the account that this experiment is bound to, such as an app or product. `null` when unbound. Fixed once the experiment first activates.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="id" type="string" required>
          Referenced resource tag, belonging to the experiment owner.
        </ResponseField>

        <ResponseField name="object" type="string" required>
          Available options: `app`, `app_build`, `product`, `plan`
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="started_at" type="string | null">
      When the experiment began collecting data, as an ISO 8601 timestamp. `null`
      for drafts.
    </ResponseField>

    <ResponseField name="status" type="string" required>
      Lifecycle state. `draft` — not yet live; `active` — currently running; `paused` — traffic paused; `ended` — concluded.

      Available options: `draft`, `active`, `paused`, `ended`
    </ResponseField>

    <ResponseField name="targeting_rules" type="object[]" required>
      Rules gating who is in the experiment at all. Conditions within a rule are AND-ed, rules are OR-ed, and `exclude` rules always win. Empty means everyone qualifies.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="conditions" type="object[]" required>
          Conditions within this rule, all of which must match.

          <Accordion title="Properties" defaultOpen={true}>
            <ResponseField name="field" type="string | null">
              Property name to read from the user context. Present when `type` is
              `property`.
            </ResponseField>

            <ResponseField name="operator" type="string" required>
              Comparison to apply.

              Available options: `any`, `none`, `eq`, `neq`, `gt`, `gte`, `lt`, `lte`
            </ResponseField>

            <ResponseField name="type" type="string" required>
              What the condition matches on: the user ID, the account ID, or a named user property.

              Available options: `user_id`, `account_id`, `property`
            </ResponseField>

            <ResponseField name="value" type="string" required>
              Value or list of values to match against.
            </ResponseField>
          </Accordion>
        </ResponseField>

        <ResponseField name="type" type="string">
          `include` — users matching this rule qualify; `exclude` — users matching this rule are always excluded, overriding any include rule.

          Available options: `include`, `exclude`
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="updated_at" type="string | null" required />

    <ResponseField name="variants" type="object[]" required>
      Treatment arms. Users outside every arm's allocation form the implicit `control` group. Weights only ever grow and arms are never removed, so a user moves from control into a treatment at most once.

      <Accordion title="Properties" defaultOpen={true}>
        <ResponseField name="name" type="string" required>
          Treatment identifier. `control` is reserved — it is the implicit remainder.
        </ResponseField>

        <ResponseField name="ranges" type="integer[][]">
          Granted bucket ranges (1% units, end-exclusive) recording this arm's
          allocation history. Server-managed; ranges are only ever appended, which is
          what keeps assignments permanent.
        </ResponseField>

        <ResponseField name="related_resource" type="object | null">
          <Accordion title="Properties" defaultOpen={true}>
            <ResponseField name="id" type="string" required>
              Referenced resource tag, belonging to the experiment owner.
            </ResponseField>

            <ResponseField name="object" type="string" required>
              Available options: `app`, `app_build`, `product`, `plan`
            </ResponseField>
          </Accordion>
        </ResponseField>

        <ResponseField name="weight" type="integer" required>
          Percentage of all users assigned to this treatment, 1–100. All weights together sum to at most 100; the remainder is control.
        </ResponseField>
      </Accordion>
    </ResponseField>

    <ResponseField name="winning_arm" type="string | null">
      The treatment that won, set when the experiment was ended. Once set, every
      evaluation returns this arm to every caller regardless of targeting or
      allocation, and no further exposures are recorded. `null` means control won —
      an ended experiment with no winning arm evaluates to `control` for everyone.
      Always `null` for feature flags, which simply evaluate to disabled once ended.
    </ResponseField>
  </Column>

  <Column>
    <div className="api-resource-sticky-example">
      ```json Experiment theme={null}
      {
      	"id": "expt_xxxxxxxxxxxxxx",
      	"account_id": "biz_xxxxxxxxxxxxxx",
      	"flag_key": "checkout_redesign_v2",
      	"name": "Checkout Redesign V2",
      	"hypothesis": "A single-step checkout raises conversion.",
      	"status": "active",
      	"feature_flag_only": false,
      	"bucket_by": "user",
      	"assignment_seed": "checkout_redesign_v21789462000",
      	"configuration_revision": 2,
      	"variants": [
      		{
      			"name": "treatment",
      			"weight": 50,
      			"ranges": [[0, 50]],
      			"related_resource": null
      		}
      	],
      	"control": {
      		"related_resource": null
      	},
      	"related_resource": null,
      	"targeting_rules": [
      		{
      			"type": "include",
      			"conditions": [
      				{
      					"type": "property",
      					"field": "country",
      					"operator": "eq",
      					"value": "US"
      				}
      			]
      		}
      	],
      	"winning_arm": null,
      	"findings": null,
      	"created_by": "user_xxxxxxxxxxxxxx",
      	"created_at": "2026-09-01T12:00:00.000Z",
      	"started_at": "2026-09-02T09:00:00.000Z",
      	"ended_at": null,
      	"updated_at": "2026-09-02T09:00:00.000Z"
      }
      ```
    </div>
  </Column>
</Columns>


## Related topics

- [Activate Experiment](/api-reference/beta/experiments/activate-experiment.md)
- [End Experiment](/api-reference/beta/experiments/end-experiment.md)
- [Pause Experiment](/api-reference/beta/experiments/pause-experiment.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.