Experiments-3

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

Endpoints

POST
POST
GET
GET
GET
GET

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
  • project_id
    string

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": {
"property1": null,
"property2": null
},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"has_encrypted_payloads": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": null,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": null,
"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": true,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": null,
"metrics": null,
"metrics_secondary": null,
"stats_config": null,
"scheduling_config": null,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"exposure_preaggregation_enabled": true,
"status": "draft",
"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
  • project_id
    string

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": {
"property1": null,
"property2": null
},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"has_encrypted_payloads": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": null,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": null,
"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": true,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": null,
"metrics": null,
"metrics_secondary": null,
"stats_config": null,
"scheduling_config": null,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"exposure_preaggregation_enabled": true,
"status": "draft",
"user_access_level": "string"
}

Create experiments ship variant

Ship a variant to 100% of users and (optionally) end the experiment.

Rewrites the feature flag so that the selected variant is served to everyone. Existing release conditions (flag groups) are preserved so the change can be rolled back by deleting the auto-added release condition in the feature flag UI.

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
  • project_id
    string

Request parameters

  • conclusion
  • conclusion_comment
    string
  • variant_key
    string

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": {
"property1": null,
"property2": null
},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"has_encrypted_payloads": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": null,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": null,
"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": true,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": null,
"metrics": null,
"metrics_secondary": null,
"stats_config": null,
"scheduling_config": null,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"exposure_preaggregation_enabled": true,
"status": "draft",
"user_access_level": "string"
}

Create experiments ship variant

Ship a variant to 100% of users and (optionally) end the experiment.

Rewrites the feature flag so that the selected variant is served to everyone. Existing release conditions (flag groups) are preserved so the change can be rolled back by deleting the auto-added release condition in the feature flag UI.

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
  • project_id
    string

Request parameters

  • conclusion
  • conclusion_comment
    string
  • variant_key
    string

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": {
"property1": null,
"property2": null
},
"deleted": true,
"active": true,
"ensure_experience_continuity": true,
"has_encrypted_payloads": true,
"version": -2147483648,
"evaluation_runtime": "server",
"bucketing_identifier": "distinct_id",
"evaluation_contexts": [
"string"
]
},
"holdout": {
"id": 0,
"name": "string",
"description": "string",
"filters": null,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z"
},
"holdout_id": 0,
"exposure_cohort": 0,
"parameters": null,
"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": true,
"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": {
"property1": null,
"property2": null
},
"role_at_organization": "engineering"
},
"created_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"type": "web",
"exposure_criteria": null,
"metrics": null,
"metrics_secondary": null,
"stats_config": null,
"scheduling_config": null,
"_create_in_folder": "string",
"conclusion": "won",
"conclusion_comment": "string",
"primary_metrics_ordered_uuids": null,
"secondary_metrics_ordered_uuids": null,
"exposure_preaggregation_enabled": true,
"status": "draft",
"user_access_level": "string"
}

Retrieve experiments timeseries results

Mixin for ViewSets to handle ApprovalRequired exceptions from decorated serializers.

This mixin intercepts ApprovalRequired exceptions raised by the @approval_gate decorator on serializer methods and converts them into proper HTTP 409 Conflict responses with change request details.

Required API key scopes

experiment:read

Path parameters

  • id
    integer
  • project_id
    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

Retrieve experiments timeseries results

Mixin for ViewSets to handle ApprovalRequired exceptions from decorated serializers.

This mixin intercepts ApprovalRequired exceptions raised by the @approval_gate decorator on serializer methods and converts them into proper HTTP 409 Conflict responses with change request details.

Required API key scopes

experiment:read

Path parameters

  • id
    integer
  • project_id
    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

Retrieve experiments eligible feature flags

Returns a paginated list of feature flags eligible for use in experiments.

Eligible flags must:

  • Be multivariate with at least 2 variants
  • Have "control" as the first variant key

Query parameters:

  • search: Filter by flag key or name (case insensitive)
  • limit: Number of results per page (default: 20)
  • offset: Pagination offset (default: 0)
  • active: Filter by active status ("true" or "false")
  • created_by_id: Filter by creator user ID
  • order: Sort order field
  • evaluation_runtime: Filter by evaluation runtime
  • has_evaluation_contexts: Filter by presence of evaluation contexts ("true" or "false")

Required API key scopes

feature_flag:read

Path parameters

  • project_id
    string

Example request

GET /api/projects/:project_id/experiments/eligible_feature_flags
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/eligible_feature_flags/

Example response

Status 200 No response body

Retrieve experiments eligible feature flags

Returns a paginated list of feature flags eligible for use in experiments.

Eligible flags must:

  • Be multivariate with at least 2 variants
  • Have "control" as the first variant key

Query parameters:

  • search: Filter by flag key or name (case insensitive)
  • limit: Number of results per page (default: 20)
  • offset: Pagination offset (default: 0)
  • active: Filter by active status ("true" or "false")
  • created_by_id: Filter by creator user ID
  • order: Sort order field
  • evaluation_runtime: Filter by evaluation runtime
  • has_evaluation_contexts: Filter by presence of evaluation contexts ("true" or "false")

Required API key scopes

feature_flag:read

Path parameters

  • project_id
    string

Example request

GET /api/projects/:project_id/experiments/eligible_feature_flags
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/eligible_feature_flags/

Example response

Status 200 No response body

Retrieve experiments requires flag implementation

Mixin for ViewSets to handle ApprovalRequired exceptions from decorated serializers.

This mixin intercepts ApprovalRequired exceptions raised by the @approval_gate decorator on serializer methods and converts them into proper HTTP 409 Conflict responses with change request details.

Required API key scopes

experiment:read

Path parameters

  • project_id
    string

Example request

GET /api/projects/:project_id/experiments/requires_flag_implementation
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/requires_flag_implementation/

Example response

Status 200 No response body

Retrieve experiments requires flag implementation

Mixin for ViewSets to handle ApprovalRequired exceptions from decorated serializers.

This mixin intercepts ApprovalRequired exceptions raised by the @approval_gate decorator on serializer methods and converts them into proper HTTP 409 Conflict responses with change request details.

Required API key scopes

experiment:read

Path parameters

  • project_id
    string

Example request

GET /api/projects/:project_id/experiments/requires_flag_implementation
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/requires_flag_implementation/

Example response

Status 200 No response body

Retrieve experiments stats

Mixin for ViewSets to handle ApprovalRequired exceptions from decorated serializers.

This mixin intercepts ApprovalRequired exceptions raised by the @approval_gate decorator on serializer methods and converts them into proper HTTP 409 Conflict responses with change request details.

Required API key scopes

experiment:read

Path parameters

  • project_id
    string

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

Retrieve experiments stats

Mixin for ViewSets to handle ApprovalRequired exceptions from decorated serializers.

This mixin intercepts ApprovalRequired exceptions raised by the @approval_gate decorator on serializer methods and converts them into proper HTTP 409 Conflict responses with change request details.

Required API key scopes

experiment:read

Path parameters

  • project_id
    string

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

Questions about this page? or post a community question.