Experiments
For instructions on how to authenticate to use this endpoint, see API overview.
Endpoints
GET | |
POST | |
GET | |
PATCH | |
DELETE | |
POST | |
POST | |
POST | |
POST | |
POST | |
POST | |
POST | |
POST | |
GET | |
GET | |
POST | |
POST | |
POST | |
POST |
List all experiments
List experiments for the current project. Supports filtering by status and archival state.
Required API key scopes
experiment:readQuery parameters
- archivedboolean
- created_by_idstring
- eventstring
- feature_flag_idinteger
- limitinteger
- offsetinteger
- orderstring
- prompt_namestring
- searchstring
- statusstringOne of:
"all""complete""draft""exposure_frozen""paused""running""stopped"
Response
Example request
GET /api /projects /:project_id /experimentsExample response
Status 200
Create experiments
Also available via the PostHog MCP server:
experiment-create— Create experiment
Create a new experiment in draft status with optional metrics.
Required API key scopes
experiment:writeRequest parameters
- namestring
- descriptionstringnull
- start_datestringnull
- end_datestringnull
- feature_flag_keystring
- feature_flag
- holdout_idintegernull
- parameters
- running_time_calculation
- excluded_variantsarraynull
- secondary_metrics
- saved_metrics_idsarraynull
- filters
- archivedbooleanDefault:
false - deletedbooleannull
- type
- exposure_criteria
- metrics
- metrics_secondary
- stats_config
- scheduling_config
- allow_unknown_eventsbooleanDefault:
false - _create_in_folderstring
- conclusion
- conclusion_commentstringnull
- primary_metrics_ordered_uuids
- secondary_metrics_ordered_uuids
- only_count_matured_usersboolean
- update_feature_flag_paramsbooleanDefault:
false
Response
Example request
POST /api /projects /:project_id /experimentsExample response
Status 201
Retrieve experiments
Also available via the PostHog MCP server:
experiment-get— Get experiment details
Retrieve a single experiment by ID, including its current status, metrics, feature flag, and results metadata.
Required API key scopes
experiment:readPath parameters
- idinteger
Response
Example request
GET /api /projects /:project_id /experiments /:idExample response
Status 200
Update experiments
Also available via the PostHog MCP server:
experiment-update— Update experiment
Update an experiment. Use this to modify experiment properties such as name, description, metrics, variants, and configuration. Metrics can be added, changed and removed at any time. Feature-flag config (variants, rollout, payloads) is sent via the feature_flag object.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- namestring
- descriptionstringnull
- start_datestringnull
- end_datestringnull
- feature_flag_keystring
- feature_flag
- holdout_idintegernull
- parameters
- running_time_calculation
- excluded_variantsarraynull
- secondary_metrics
- saved_metrics_idsarraynull
- filters
- archivedbooleanDefault:
false - deletedbooleannull
- type
- exposure_criteria
- metrics
- metrics_secondary
- stats_config
- scheduling_config
- allow_unknown_eventsbooleanDefault:
false - _create_in_folderstring
- conclusion
- conclusion_commentstringnull
- primary_metrics_ordered_uuids
- secondary_metrics_ordered_uuids
- only_count_matured_usersboolean
- update_feature_flag_paramsbooleanDefault:
false
Response
Example request
PATCH /api /projects /:project_id /experiments /:idExample response
Status 200
Delete experiments
Hard delete of this model is not allowed. Use a patch API call to set "deleted" to true
Required API key scopes
experiment:writePath parameters
- idinteger
Example request
DELETE /api /projects /:project_id /experiments /:idExample response
Status 405 No response body
Create experiments archive
Archive an ended experiment.
Hides the experiment from the default list view. The experiment can be restored at any time by updating archived=false. When the linked feature flag is still enabled, pass disable_feature_flag=true to also disable and archive it. Returns 400 if the experiment is already archived or has not ended yet.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- disable_feature_flagbooleanDefault:
false
Response
Example request
POST /api /projects /:project_id /experiments /:id /archiveExample response
Status 200
Create experiments copy to project
Copy an experiment into another project in the same organization as a new draft.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- target_team_idinteger
- feature_flag_keystring
- namestring
Response
Example request
POST /api /projects /:project_id /experiments /:id /copy_to_projectExample response
Status 200
Create experiments create exposure cohort for experiment
Mixin for ViewSets to handle approval-gate exceptions raised from decorated serializers.
Intercepts ApprovalRequired (409) and PolicyConflict (400) raised by the @approval_gate decorator on serializer methods and converts them into the same responses the viewset path produces (see decorators._result_to_response), so both paths share one contract.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- namestring
- descriptionstringnull
- start_datestringnull
- end_datestringnull
- feature_flag_keystring
- holdout_idintegernull
- parameters
- running_time_calculation
- excluded_variantsarraynull
- secondary_metrics
- saved_metrics_idsarraynull
- filters
- archivedbooleanDefault:
false - deletedbooleannull
- type
- exposure_criteria
- metrics
- metrics_secondary
- stats_config
- scheduling_config
- allow_unknown_eventsbooleanDefault:
false - _create_in_folderstring
- conclusion
- conclusion_commentstringnull
- primary_metrics_ordered_uuids
- secondary_metrics_ordered_uuids
- only_count_matured_usersboolean
- update_feature_flag_paramsbooleanDefault:
false
Example request
POST /api /projects /:project_id /experiments /:id /create_exposure_cohort_for_experimentExample response
Status 200 No response body
Create experiments duplicate
Mixin for ViewSets to handle approval-gate exceptions raised from decorated serializers.
Intercepts ApprovalRequired (409) and PolicyConflict (400) raised by the @approval_gate decorator on serializer methods and converts them into the same responses the viewset path produces (see decorators._result_to_response), so both paths share one contract.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- namestring
- descriptionstringnull
- start_datestringnull
- end_datestringnull
- feature_flag_keystring
- holdout_idintegernull
- parameters
- running_time_calculation
- excluded_variantsarraynull
- secondary_metrics
- saved_metrics_idsarraynull
- filters
- archivedbooleanDefault:
false - deletedbooleannull
- type
- exposure_criteria
- metrics
- metrics_secondary
- stats_config
- scheduling_config
- allow_unknown_eventsbooleanDefault:
false - _create_in_folderstring
- conclusion
- conclusion_commentstringnull
- primary_metrics_ordered_uuids
- secondary_metrics_ordered_uuids
- only_count_matured_usersboolean
- update_feature_flag_paramsbooleanDefault:
false
Example request
POST /api /projects /:project_id /experiments /:id /duplicateExample response
Status 200 No response body
Create experiments end
End a running experiment without shipping a variant.
Sets end_date to now and marks the experiment as stopped. The feature flag is NOT modified — users continue to see their assigned variants and exposure events ($feature_flag_called) continue to be recorded. However, only data up to end_date is included in experiment results.
Use this when:
- You want to freeze the results window without changing which variant users see.
- A variant was already shipped manually via the feature flag UI and the experiment just needs to be marked complete.
The end_date can be adjusted after ending via PATCH if it needs to be backdated (e.g. to match when the flag was actually paused).
Other options:
- Use ship_variant to end the experiment AND roll out a single variant to 100%% of users.
- Use pause to deactivate the flag without ending the experiment (stops variant assignment but does not freeze results).
Returns 400 if the experiment is not running.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- conclusion
- conclusion_commentstringnull
- open_cleanup_prbooleanDefault:
false
Response
Example request
POST /api /projects /:project_id /experiments /:id /endExample response
Status 200
Create experiments freeze exposure
Freeze exposure on a running experiment while metrics keep flowing.
Snapshots the already-exposed users into a static cohort and narrows the
linked feature flag so only those users keep matching — new users can no
longer enter the experiment. end_date is left null so long-term metrics
(revenue/LTV/renewals/retention) keep accumulating. Enrolled users keep
their assigned variant. The serialized status becomes 'exposure_frozen'.
Returns 400 if the experiment is not running, exposure is already frozen, the experiment is group-aggregated (group flags cannot be frozen with a person cohort), or the exposed set is too large to snapshot synchronously.
Required API key scopes
experiment:writePath parameters
- idinteger
Response
Example request
POST /api /projects /:project_id /experiments /:id /freeze_exposureExample response
Status 200
Create experiments launch
Launch a draft experiment.
Validates the experiment is in draft state, activates its linked feature flag, sets start_date to the current server time, and transitions the experiment to running. Returns 400 if the experiment has already been launched or if the feature flag configuration is invalid (e.g. fewer than 2 variants).
Required API key scopes
experiment:writePath parameters
- idinteger
Response
Example request
POST /api /projects /:project_id /experiments /:id /launchExample response
Status 200
Create experiments metrics recalculation
Trigger a batch recalculation of all metrics for this experiment.
Returns 201 with the new pending recalculation, or 200 with the active one if a recalculation is
already pending or in progress for this experiment. The response payload intentionally does not
include the results array — at POST time the workflow has just been queued and no per-metric
results exist yet. Clients should poll GET metrics_recalculation/{id}/ for results as the workflow
progresses.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- triggerDefault:
manual
Response
Example request
POST /api /projects /:project_id /experiments /:id /metrics_recalculationExample response
Status 200
Status 201
Retrieve experiments metrics recalculation
Mixin for ViewSets to handle approval-gate exceptions raised from decorated serializers.
Intercepts ApprovalRequired (409) and PolicyConflict (400) raised by the @approval_gate decorator on serializer methods and converts them into the same responses the viewset path produces (see decorators._result_to_response), so both paths share one contract.
Required API key scopes
experiment:readPath parameters
- idinteger
- recalculation_idstring
Response
Example request
GET /api /projects /:project_id /experiments /:id /metrics_recalculation /:recalculation_idExample response
Status 200
Status 404 No response body
Retrieve experiments metrics recalculation latest
Mixin for ViewSets to handle approval-gate exceptions raised from decorated serializers.
Intercepts ApprovalRequired (409) and PolicyConflict (400) raised by the @approval_gate decorator on serializer methods and converts them into the same responses the viewset path produces (see decorators._result_to_response), so both paths share one contract.
Required API key scopes
experiment:readPath parameters
- idinteger
Response
Example request
GET /api /projects /:project_id /experiments /:id /metrics_recalculation /latestExample response
Status 200
Status 404 No response body
Create experiments pause
Pause a running experiment.
Deactivates the linked feature flag so it is no longer returned by the /decide endpoint. Users fall back to the application default (typically the control experience), and no new exposure events are recorded (i.e. $feature_flag_called is not fired). Returns 400 if the experiment is not running or is already paused.
Required API key scopes
experiment:writePath parameters
- idinteger
Response
Example request
POST /api /projects /:project_id /experiments /:id /pauseExample response
Status 200
Create experiments recalculate timeseries
Mixin for ViewSets to handle approval-gate exceptions raised from decorated serializers.
Intercepts ApprovalRequired (409) and PolicyConflict (400) raised by the @approval_gate decorator on serializer methods and converts them into the same responses the viewset path produces (see decorators._result_to_response), so both paths share one contract.
Required API key scopes
experiment:writePath parameters
- idinteger
Request parameters
- namestring
- descriptionstringnull
- start_datestringnull
- end_datestringnull
- feature_flag_keystring
- holdout_idintegernull
- parameters
- running_time_calculation
- excluded_variantsarraynull
- secondary_metrics
- saved_metrics_idsarraynull
- filters
- archivedbooleanDefault:
false - deletedbooleannull
- type
- exposure_criteria
- metrics
- metrics_secondary
- stats_config
- scheduling_config
- allow_unknown_eventsbooleanDefault:
false - _create_in_folderstring
- conclusion
- conclusion_commentstringnull
- primary_metrics_ordered_uuids
- secondary_metrics_ordered_uuids
- only_count_matured_usersboolean
- update_feature_flag_paramsbooleanDefault:
false
Example request
POST /api /projects /:project_id /experiments /:id /recalculate_timeseriesExample response
Status 200 No response body
Create experiments reset
Reset an experiment back to draft state.
Clears start/end dates, conclusion, and archived flag. The feature flag is left unchanged — users continue to see their assigned variants.
Previously collected events still exist but won't be included in results unless the start date is manually adjusted after re-launch.
Returns 400 if the experiment is already in draft state.
Required API key scopes
experiment:writePath parameters
- idinteger
Response
Example request
POST /api /projects /:project_id /experiments /:id /resetExample response
Status 200
Create experiments resume
Resume a paused experiment.
Reactivates the linked feature flag so it is returned by /decide again. Users are re-bucketed deterministically into the same variants they had before the pause, and exposure tracking resumes. Returns 400 if the experiment is not running or is not paused.
Required API key scopes
experiment:writePath parameters
- idinteger
Response
Example request
POST /api /projects /:project_id /experiments /:id /resume