Experiments

For instructions on how to authenticate to use this endpoint, see API overview.

Endpoints

POST
POST
POST
POST
POST
GET
POST
POST
POST
POST
GET
GET
POST
GET

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:write

Path parameters

  • id
    integer

Request parameters

  • name
    string
  • description
    stringnull
  • start_date
    stringnull
  • end_date
    stringnull
  • feature_flag_key
    string
  • holdout_id
    integernull
  • parameters
  • running_time_calculation
  • excluded_variants
    arraynull
  • secondary_metrics
  • saved_metrics_ids
    arraynull
  • filters
  • archived
    boolean
    Default: false
  • deleted
    booleannull
  • type
  • exposure_criteria
  • metrics
  • metrics_secondary
  • stats_config
  • scheduling_config
  • allow_unknown_events
    boolean
    Default: false
  • _create_in_folder
    string
  • conclusion
  • conclusion_comment
    stringnull
  • repository
    stringnull
  • primary_metrics_ordered_uuids
  • secondary_metrics_ordered_uuids
  • only_count_matured_users
    boolean
  • update_feature_flag_params
    boolean
    Default: false
  • version
    integernull
  • original_experiment
    objectnull

Example request

POST /api/projects/:project_id/experiments/:id/recalculate_timeseries
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/recalculate_timeseries/\
-d name="string",\
-d feature_flag_key="string"

Example response

Status 200 No response body

Create experiments reset

Reset an experiment back to draft state.

Clears start/end dates, conclusion, archived flag, and any flag-cleanup task pointer. 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:write

Path parameters

  • id
    integer

Response


Example request

POST /api/projects/:project_id/experiments/:id/reset
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/reset/

Example response

Status 200
RESPONSE
{
"id": 0,
"name": "string",
"description": "string",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"feature_flag_key": "string",
"feature_flag": {
"id": 0,
"team_id": 0,
"name": "string",
"key": "string",
"filters": {},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": [
{
"properties": [
{
"key": "string",
"type": "cohort",
"cohort_name": "string",
"group_type_index": 0,
"value": null,
"operator": "exact"
}
],
"rollout_percentage": 0.1,
"variant": "string",
"aggregation_group_type_index": 0
}
],
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"user_access_level": "string"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": {
"minimum_detectable_effect": null,
"variant_notes": null
},
"running_time_calculation": {
"exposure_estimate_config": null,
"minimum_detectable_effect": null,
"recommended_running_time": null,
"recommended_sample_size": null
},
"excluded_variants": [
"string"
],
"secondary_metrics": null,
"saved_metrics": [
{
"id": 0,
"experiment": 0,
"saved_metric": 0,
"metadata": null,
"created_at": "2019-08-24T14:15:22Z",
"query": null,
"name": "string"
}
],
"saved_metrics_ids": [
null
],
"filters": null,
"archived": false,
"deleted": true,
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": {
"exposure_config": null,
"filterTestAccounts": null,
"multiple_variant_handling": null
},
"metrics": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"metrics_secondary": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"stats_config": null,
"scheduling_config": null,
"allow_unknown_events": false,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"flag_cleanup_task_id": "72bdc9e1-c8bb-44f1-8473-a75871329c84",
"repository": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"only_count_matured_users": true,
"update_feature_flag_params": false,
"version": 0,
"original_experiment": {},
"status": "draft",
"is_legacy": true,
"can_freeze_exposure": true,
"resolved_exposure_event": "string",
"user_access_level": "string"
}

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:write

Path parameters

  • id
    integer

Response


Example request

POST /api/projects/:project_id/experiments/:id/resume
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/resume/

Example response

Status 200
RESPONSE
{
"id": 0,
"name": "string",
"description": "string",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"feature_flag_key": "string",
"feature_flag": {
"id": 0,
"team_id": 0,
"name": "string",
"key": "string",
"filters": {},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": [
{
"properties": [
{
"key": "string",
"type": "cohort",
"cohort_name": "string",
"group_type_index": 0,
"value": null,
"operator": "exact"
}
],
"rollout_percentage": 0.1,
"variant": "string",
"aggregation_group_type_index": 0
}
],
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"user_access_level": "string"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": {
"minimum_detectable_effect": null,
"variant_notes": null
},
"running_time_calculation": {
"exposure_estimate_config": null,
"minimum_detectable_effect": null,
"recommended_running_time": null,
"recommended_sample_size": null
},
"excluded_variants": [
"string"
],
"secondary_metrics": null,
"saved_metrics": [
{
"id": 0,
"experiment": 0,
"saved_metric": 0,
"metadata": null,
"created_at": "2019-08-24T14:15:22Z",
"query": null,
"name": "string"
}
],
"saved_metrics_ids": [
null
],
"filters": null,
"archived": false,
"deleted": true,
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": {
"exposure_config": null,
"filterTestAccounts": null,
"multiple_variant_handling": null
},
"metrics": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"metrics_secondary": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"stats_config": null,
"scheduling_config": null,
"allow_unknown_events": false,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"flag_cleanup_task_id": "72bdc9e1-c8bb-44f1-8473-a75871329c84",
"repository": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"only_count_matured_users": true,
"update_feature_flag_params": false,
"version": 0,
"original_experiment": {},
"status": "draft",
"is_legacy": true,
"can_freeze_exposure": true,
"resolved_exposure_event": "string",
"user_access_level": "string"
}

Create experiments session buckets

Session recordings of this experiment matching a bucket.

Answers the questions a recordings query can't express on its own — "fired any of these metrics", "fired none of them", "was exposed but never completed the funnel in this session" — by returning a bounded, most-recent-first list of session IDs to pass back as a recordings query's session_ids. POST because the metric list doesn't fit a query string; the endpoint only reads.

Session-scoped and goal-free: the set describes what happened in each session, while the experiment analysis counts per person over the whole run window. A session can be in the drop-off bucket while the same person converts in a later one.

Required API key scopes

experiment:readsession_recording:read

Path parameters

  • id
    integer

Request parameters

  • bucket
  • metric_uuids
    array
  • variant
    stringnull
  • limit
    integer
    Default: 100

Response


Example request

POST /api/projects/:project_id/experiments/:id/session_buckets
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/session_buckets/\
-d bucket=undefined

Example response

Status 200
RESPONSE
{
"session_ids": [
"string"
],
"truncated": true,
"considered_metrics": [
{
"metric_uuid": "string",
"metric_name": "string"
}
],
"excluded_metrics": [
{
"metric_uuid": "string",
"metric_name": "string",
"reason": "string"
}
],
"date_from": "2019-08-24T14:15:22Z",
"date_to": "2019-08-24T14:15:22Z",
"filter_test_accounts": true,
"used_exposure_fallback": true
}

Create experiments ship variant

Ship a variant and (optionally) end the experiment.

Updates the feature flag so the selected variant gets 100% of the variant distribution. By default, existing release conditions on the flag are preserved untouched — the variant is served only to users who already match them. Pass release_to_everyone: true to also prepend a catch-all release condition that rolls the variant out to 100% of users (overrides any existing release conditions on the flag).

Can be called on both running and stopped experiments. If the experiment is still running, it will also be ended (end_date set and status marked as stopped). If the experiment has already ended, only the flag is rewritten - this supports the "end first, ship later" workflow.

If an approval policy requires review before changes on the flag take effect, the API returns 409 with a change_request_id. The experiment is NOT ended until the change request is approved and the user retries.

Returns 400 if the experiment is in draft state, the variant_key is not found on the flag, or the experiment has no linked feature flag.

Required API key scopes

experiment:write

Path parameters

  • id
    integer

Request parameters

  • conclusion
  • conclusion_comment
    stringnull
  • open_cleanup_pr
    boolean
    Default: false
  • repository
    stringnull
  • set_repository_as_team_default
    boolean
    Default: false
  • variant_key
    string
  • release_to_everyone
    boolean
    Default: false

Response


Example request

POST /api/projects/:project_id/experiments/:id/ship_variant
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/ship_variant/\
-d variant_key="string"

Example response

Status 200
RESPONSE
{
"id": 0,
"name": "string",
"description": "string",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"feature_flag_key": "string",
"feature_flag": {
"id": 0,
"team_id": 0,
"name": "string",
"key": "string",
"filters": {},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": [
{
"properties": [
{
"key": "string",
"type": "cohort",
"cohort_name": "string",
"group_type_index": 0,
"value": null,
"operator": "exact"
}
],
"rollout_percentage": 0.1,
"variant": "string",
"aggregation_group_type_index": 0
}
],
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"user_access_level": "string"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": {
"minimum_detectable_effect": null,
"variant_notes": null
},
"running_time_calculation": {
"exposure_estimate_config": null,
"minimum_detectable_effect": null,
"recommended_running_time": null,
"recommended_sample_size": null
},
"excluded_variants": [
"string"
],
"secondary_metrics": null,
"saved_metrics": [
{
"id": 0,
"experiment": 0,
"saved_metric": 0,
"metadata": null,
"created_at": "2019-08-24T14:15:22Z",
"query": null,
"name": "string"
}
],
"saved_metrics_ids": [
null
],
"filters": null,
"archived": false,
"deleted": true,
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": {
"exposure_config": null,
"filterTestAccounts": null,
"multiple_variant_handling": null
},
"metrics": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"metrics_secondary": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"stats_config": null,
"scheduling_config": null,
"allow_unknown_events": false,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"flag_cleanup_task_id": "72bdc9e1-c8bb-44f1-8473-a75871329c84",
"repository": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"only_count_matured_users": true,
"update_feature_flag_params": false,
"version": 0,
"original_experiment": {},
"status": "draft",
"is_legacy": true,
"can_freeze_exposure": true,
"resolved_exposure_event": "string",
"user_access_level": "string"
}

Retrieve experiments timeseries results

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:read

Path parameters

  • id
    integer

Query parameters

  • fingerprint
    string
  • metric_uuid
    string

Example request

GET /api/projects/:project_id/experiments/:id/timeseries_results
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/timeseries_results/

Example response

Status 200 No response body

Create experiments unarchive

Unarchive an archived experiment.

Restores the experiment to the default list view. Returns 400 if the experiment is not currently archived.

Required API key scopes

experiment:write

Path parameters

  • id
    integer

Response


Example request

POST /api/projects/:project_id/experiments/:id/unarchive
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/unarchive/

Example response

Status 200
RESPONSE
{
"id": 0,
"name": "string",
"description": "string",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"feature_flag_key": "string",
"feature_flag": {
"id": 0,
"team_id": 0,
"name": "string",
"key": "string",
"filters": {},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": [
{
"properties": [
{
"key": "string",
"type": "cohort",
"cohort_name": "string",
"group_type_index": 0,
"value": null,
"operator": "exact"
}
],
"rollout_percentage": 0.1,
"variant": "string",
"aggregation_group_type_index": 0
}
],
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"user_access_level": "string"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": {
"minimum_detectable_effect": null,
"variant_notes": null
},
"running_time_calculation": {
"exposure_estimate_config": null,
"minimum_detectable_effect": null,
"recommended_running_time": null,
"recommended_sample_size": null
},
"excluded_variants": [
"string"
],
"secondary_metrics": null,
"saved_metrics": [
{
"id": 0,
"experiment": 0,
"saved_metric": 0,
"metadata": null,
"created_at": "2019-08-24T14:15:22Z",
"query": null,
"name": "string"
}
],
"saved_metrics_ids": [
null
],
"filters": null,
"archived": false,
"deleted": true,
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": {
"exposure_config": null,
"filterTestAccounts": null,
"multiple_variant_handling": null
},
"metrics": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"metrics_secondary": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"stats_config": null,
"scheduling_config": null,
"allow_unknown_events": false,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"flag_cleanup_task_id": "72bdc9e1-c8bb-44f1-8473-a75871329c84",
"repository": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"only_count_matured_users": true,
"update_feature_flag_params": false,
"version": 0,
"original_experiment": {},
"status": "draft",
"is_legacy": true,
"can_freeze_exposure": true,
"resolved_exposure_event": "string",
"user_access_level": "string"
}

Create experiments unfreeze exposure

Reopen enrollment on an exposure-frozen experiment.

Removes the snapshot-cohort condition and freeze markers from every release group, restoring the flag's original targeting: new users can enroll again and already-enrolled users keep their assigned variant. The snapshot cohort is soft-deleted. The serialized status returns to 'running'.

Returns 400 if the experiment is not running or its exposure is not frozen.

Required API key scopes

experiment:write

Path parameters

  • id
    integer

Response


Example request

POST /api/projects/:project_id/experiments/:id/unfreeze_exposure
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/:id/unfreeze_exposure/

Example response

Status 200
RESPONSE
{
"id": 0,
"name": "string",
"description": "string",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"feature_flag_key": "string",
"feature_flag": {
"id": 0,
"team_id": 0,
"name": "string",
"key": "string",
"filters": {},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": [
{
"properties": [
{
"key": "string",
"type": "cohort",
"cohort_name": "string",
"group_type_index": 0,
"value": null,
"operator": "exact"
}
],
"rollout_percentage": 0.1,
"variant": "string",
"aggregation_group_type_index": 0
}
],
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"user_access_level": "string"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": {
"minimum_detectable_effect": null,
"variant_notes": null
},
"running_time_calculation": {
"exposure_estimate_config": null,
"minimum_detectable_effect": null,
"recommended_running_time": null,
"recommended_sample_size": null
},
"excluded_variants": [
"string"
],
"secondary_metrics": null,
"saved_metrics": [
{
"id": 0,
"experiment": 0,
"saved_metric": 0,
"metadata": null,
"created_at": "2019-08-24T14:15:22Z",
"query": null,
"name": "string"
}
],
"saved_metrics_ids": [
null
],
"filters": null,
"archived": false,
"deleted": true,
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": {
"exposure_config": null,
"filterTestAccounts": null,
"multiple_variant_handling": null
},
"metrics": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"metrics_secondary": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"stats_config": null,
"scheduling_config": null,
"allow_unknown_events": false,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"flag_cleanup_task_id": "72bdc9e1-c8bb-44f1-8473-a75871329c84",
"repository": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"only_count_matured_users": true,
"update_feature_flag_params": false,
"version": 0,
"original_experiment": {},
"status": "draft",
"is_legacy": true,
"can_freeze_exposure": true,
"resolved_exposure_event": "string",
"user_access_level": "string"
}

Create experiments calculate running time

Estimate the recommended sample size and running time for an experiment.

Pure statistical calculation — does not read or write any experiment. Pass the metric type, a minimum detectable effect, and either a baseline value or raw baseline statistics. When exposure_rate_per_day is provided, the response also includes the estimated running time in days.

Required API key scopes

experiment:read

Request parameters

  • metric_type
  • minimum_detectable_effect
    number
  • number_of_variants
    integer
    Default: 2
  • exposure_rate_per_day
    numbernull
  • baseline_value
    numbernull
  • variance
    numbernull
  • baseline_stats

Response


Example request

POST /api/projects/:project_id/experiments/calculate_running_time
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/calculate_running_time/\
-d metric_type=undefined,\
-d minimum_detectable_effect="number"

Example response

Status 200
RESPONSE
{
"baseline_value": 0,
"variance": 0,
"recommended_sample_size": 0,
"recommended_running_time_days": 0
}

Create experiments create from prompt

Create an experiment that compares N versions of an LLM prompt using a metric template.

The user picks 2+ versions of an existing LLMPrompt and 1+ metric templates (cost / latency / eval_pass_rate). The endpoint builds the matching variants (control + test-N, each named after its prompt version) and attaches one metric per selected template, each scoped to the prompt's $ai_prompt_name. Resulting experiment is in draft state.

Required API key scopes

experiment:writellm_prompt:read

Request parameters

  • prompt_name
    string
  • versions
    array
  • templates
    Click to open
    array
  • name
    string
  • feature_flag_key
    string
  • description
    string

Response


Example request

POST /api/projects/:project_id/experiments/create_from_prompt
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/create_from_prompt/\
-d prompt_name="string",\
-d versions="array",\
-d templates="array"

Example response

Status 200
RESPONSE
{
"id": 0,
"name": "string",
"description": "string",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"feature_flag_key": "string",
"feature_flag": {
"id": 0,
"team_id": 0,
"name": "string",
"key": "string",
"filters": {},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": [
{
"properties": [
{
"key": "string",
"type": "cohort",
"cohort_name": "string",
"group_type_index": 0,
"value": null,
"operator": "exact"
}
],
"rollout_percentage": 0.1,
"variant": "string",
"aggregation_group_type_index": 0
}
],
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"user_access_level": "string"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": {
"minimum_detectable_effect": null,
"variant_notes": null
},
"running_time_calculation": {
"exposure_estimate_config": null,
"minimum_detectable_effect": null,
"recommended_running_time": null,
"recommended_sample_size": null
},
"excluded_variants": [
"string"
],
"secondary_metrics": null,
"saved_metrics": [
{
"id": 0,
"experiment": 0,
"saved_metric": 0,
"metadata": null,
"created_at": "2019-08-24T14:15:22Z",
"query": null,
"name": "string"
}
],
"saved_metrics_ids": [
null
],
"filters": null,
"archived": false,
"deleted": true,
"created_by": {
"id": 0,
"uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
"distinct_id": "string",
"first_name": "string",
"last_name": "string",
"email": "user@example.com",
"is_email_verified": true,
"hedgehog_config": {},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": {
"exposure_config": null,
"filterTestAccounts": null,
"multiple_variant_handling": null
},
"metrics": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"metrics_secondary": [
{
"completion_event": null,
"conversion_window": null,
"denominator": null,
"denominator_outlier_handling": null,
"goal": null,
"ignore_zeros": null,
"kind": "ExperimentMetric",
"lower_bound_percentile": null,
"metric_type": "funnel",
"name": null,
"numerator": null,
"numerator_outlier_handling": null,
"retention_window_end": null,
"retention_window_start": null,
"retention_window_unit": null,
"series": null,
"source": null,
"start_event": null,
"start_handling": null,
"threshold": null,
"upper_bound_percentile": null,
"uuid": null
}
],
"stats_config": null,
"scheduling_config": null,
"allow_unknown_events": false,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"flag_cleanup_task_id": "72bdc9e1-c8bb-44f1-8473-a75871329c84",
"repository": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"only_count_matured_users": true,
"update_feature_flag_params": false,
"version": 0,
"original_experiment": {},
"status": "draft",
"is_legacy": true,
"can_freeze_exposure": true,
"resolved_exposure_event": "string",
"user_access_level": "string"
}

Retrieve experiments prompt templates

List the LLM metric templates that can be passed to create_from_prompt.

Required API key scopes

experiment:read

Example request

GET /api/projects/:project_id/experiments/prompt_templates
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/prompt_templates/

Example response

Status 200

Retrieve experiments session context

Resolve which experiments (and variants) a session recording saw. Variants come from the session's $feature_flag_called events and stamped $feature/<key> event properties — flag evaluation, which may differ from an experiment's exposure criteria.

Required API key scopes

experiment:readsession_recording:read

Query parameters

  • session_id
    string

Response


Example request

GET /api/projects/:project_id/experiments/session_context
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/session_context/

Example response

Status 200
RESPONSE
{
"session_id": "string",
"results": [
{
"experiment_id": 0,
"experiment_name": "string",
"flag_key": "string",
"variant": "string",
"variants_seen": [
"string"
],
"multiple_variants": true,
"first_exposure_timestamp": "2019-08-24T14:15:22Z",
"experiment_start_date": "2019-08-24T14:15:22Z",
"experiment_end_date": "2019-08-24T14:15:22Z",
"metrics_in_session": [
{
"metric_uuid": "string",
"metric_name": "string",
"event_count": 0,
"first_timestamp": "2019-08-24T14:15:22Z",
"timestamps": [
"2019-08-24T14:15:22Z"
],
"sources": [
{
"source_role": "source",
"source_name": "string",
"source_index": 0,
"source_total": 0,
"event_count": 0,
"first_timestamp": "2019-08-24T14:15:22Z",
"timestamps": [
"2019-08-24T14:15:22Z"
]
}
]
}
]
}
]
}

Create experiments session contexts

Resolve experiment context for a batch of session recordings.

Batch variant of session_context, used to prefetch the replay player's experiments box for a whole recordings list in one request. POST because the id list doesn't fit a query string; the endpoint only reads. Already-computed sessions are served from (and cold ones written to) the same short-lived per-viewer cache the single-session endpoint uses, so opening any prefetched recording renders its context instantly. Sessions whose recording metadata doesn't exist yet are omitted from the response, as are recordings the caller can't access and sessions beyond the batch's recording-day budget (each distinct recording day costs its own set of ClickHouse scans, so only the most recent days are computed per request).

Required API key scopes

experiment:readsession_recording:read

Request parameters

  • session_ids
    array

Response


Example request

POST /api/projects/:project_id/experiments/session_contexts
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/session_contexts/\
-d session_ids="array"

Example response

Status 200
RESPONSE
{
"results": [
{
"session_id": "string",
"results": [
{
"experiment_id": 0,
"experiment_name": "string",
"flag_key": "string",
"variant": "string",
"variants_seen": [
"string"
],
"multiple_variants": true,
"first_exposure_timestamp": "2019-08-24T14:15:22Z",
"experiment_start_date": "2019-08-24T14:15:22Z",
"experiment_end_date": "2019-08-24T14:15:22Z",
"metrics_in_session": [
{
"metric_uuid": "string",
"metric_name": "string",
"event_count": 0,
"first_timestamp": "2019-08-24T14:15:22Z",
"timestamps": [
"2019-08-24T14:15:22Z"
],
"sources": [
{
"source_role": "source",
"source_name": "string",
"source_index": 0,
"source_total": 0,
"event_count": 0,
"first_timestamp": "2019-08-24T14:15:22Z",
"timestamps": [
"2019-08-24T14:15:22Z"
]
}
]
}
]
}
]
}
]
}

Retrieve experiments stats

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:read

Example request

GET /api/projects/:project_id/experiments/stats
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/experiments/stats/

Example response

Status 200 No response body

Community questions