Experiments

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

Endpoints

POST
POST
GET

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"
]
}
]
}
]
}
]
}
]
}

Create experiments setup context

Facts about this project that decide how to configure a new experiment.

Returns the team's experiment defaults, which SDKs call feature flags, traffic on a target surface, the baseline of a candidate metric, how recent experiments were set up, and the most reused shared metrics. Each section has its own status, so a slow or failed read leaves the others valid. POST because the inputs describe a plan rather than a resource; the endpoint only reads.

Required API key scopes

experiment:readexperiment_saved_metric:readquery:read

Request parameters

  • target_event
    string | null
  • target_url_contains
    string | null
  • target_properties
  • metric_event
    string | null
  • metric_properties
  • previous_experiments_limit
    integer
    Default: 10
  • shared_metrics_limit
    integer
    Default: 10

Response


Example request

POST /api/projects/:project_id/experiments/setup_context
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/setup_context/\
-d target_event="string"

Example response

Status 200
RESPONSE
{
"team_defaults": {
"status": "ok",
"data": {
"stats_method": "string",
"confidence_level": 0,
"minimum_detectable_effect": 0,
"product_default_minimum_detectable_effect": 0,
"product_default_stats_method": "string",
"product_default_confidence_level": 0.1,
"only_count_matured_users": true,
"cuped_enabled": true,
"sequential_testing_enabled": true,
"flags_persistence_default": true,
"test_account_filter_count": 0,
"new_experiments_filter_test_accounts": true,
"default_exposure_event": "string"
}
},
"sdk_profile": {
"status": "ok",
"data": {
"window_days": 0,
"source_event": "string",
"computed_at": "2019-08-24T14:15:22Z",
"libs": [
{
"lib": "string",
"category": "web",
"calls": 0,
"distinct_ids": 0,
"device_id_share": 0.1,
"locally_evaluated_share": 0,
"anonymous_share": 0
}
],
"libs_truncated": true,
"flags_seen": 0,
"flags_evaluated_on_server_and_web": 0,
"evaluated_on_server_and_web": true,
"libs_on_any_event": [
{
"lib": "string",
"category": "web",
"events": 0,
"distinct_ids": 0
}
],
"libs_on_any_event_truncated": true
}
},
"target_surface": {
"status": "ok",
"data": {
"window_days": 0,
"source_event": "string",
"target_url_contains": "string",
"target_properties": [
{
"key": "string",
"label": null,
"operator": "exact",
"type": "event",
"value": null
}
],
"computed_at": "2019-08-24T14:15:22Z",
"test_accounts_filtered": true,
"unique_persons": 0,
"exposures_per_day_estimate": 0.1,
"libs": [
{
"lib": "string",
"category": "web",
"unique_persons": 0,
"anonymous_share": 0,
"device_id_share": 0.1
}
],
"libs_truncated": true,
"anonymous_share": 0,
"device_id_share": 0
}
},
"candidate_metric": {
"status": "ok",
"data": {
"window_days": 0,
"source_event": "string",
"metric_properties": [
{
"key": "string",
"label": null,
"operator": "exact",
"type": "event",
"value": null
}
],
"target_event": "string",
"computed_at": "2019-08-24T14:15:22Z",
"test_accounts_filtered": true,
"persons_reached": 0,
"persons_converted": 0,
"conversion_rate": 0,
"funnel_baseline_stats": {
"number_of_samples": 0,
"sum": 0.1,
"step_counts": [
0.1
]
},
"mean_count_baseline_stats": {
"number_of_samples": 0,
"sum": 0.1,
"sum_squares": 0.1
},
"note": "string",
"event_volume": 0,
"unique_persons": 0
}
},
"previous_experiments": {
"status": "ok",
"data": {
"experiments": [
{
"id": 0,
"name": "string",
"state": "draft",
"created_at": "2019-08-24T14:15:22Z",
"start_date": "2019-08-24T14:15:22Z",
"end_date": "2019-08-24T14:15:22Z",
"conclusion": "string",
"feature_flag_key": "string",
"variant_count": 0,
"split_even": true,
"serving_single_variant": "string",
"rollout_percentage": 0,
"multiple_variant_handling": "exclude",
"multiple_variant_handling_set": true,
"ensure_experience_continuity": true,
"bucketing_identifier": "string",
"evaluation_runtime": "string",
"group_aggregation": true,
"custom_exposure_event": "string",
"custom_exposure_action_id": 0,
"exposure_property_filters": [
{
"key": "string",
"label": null,
"operator": "exact",
"type": "event",
"value": null
}
],
"activation_event": "string",
"activation_action_id": 0,
"filter_test_accounts": true,
"primary_metric_count": 0,
"secondary_metric_count": 0,
"shared_metric_count": 0,
"primary_metric_types": [
"string"
],
"primary_metric_events": [
"string"
],
"primary_metric_action_ids": [
0
],
"minimum_detectable_effect": 0,
"stats_method": "string",
"has_holdout": true,
"outcome": {
"metric_type": "string",
"metric_samples": 0,
"analyzed_exposures": 0,
"control_baseline_value": 0,
"any_variant_significant": true,
"result_completed_at": "2019-08-24T14:15:22Z",
"result_data_through": "2019-08-24T14:15:22Z"
}
}
],
"summary": {
"total": 0,
"launched": 0,
"launched_without_results": 0,
"launched_with_unknown_analyzed_exposures": 0,
"launched_with_zero_analyzed_exposures": 0,
"launched_with_under_100_analyzed_exposures": 0,
"using_device_id_bucketing": 0,
"using_persistence": 0,
"using_custom_exposure": 0,
"using_exposure_property_filters": 0,
"using_activation": 0,
"using_uneven_split": 0,
"serving_single_variant": 0
}
}
},
"shared_metrics": {
"status": "ok",
"data": {
"metric_event": "string",
"metric_event_match_truncated": true,
"metrics": [
{
"id": 0,
"name": "string",
"metric_type": "string",
"events": [
"string"
],
"action_ids": [
0
],
"used_as_primary": 0,
"used_as_secondary": 0,
"last_used_at": "2019-08-24T14:15:22Z",
"matches_metric_event": true,
"metric_event_roles": [
"string"
]
}
]
}
}
}

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