Insights

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

Endpoints

POST
POST
POST
POST
POST
GET
GET
POST

Create insights bulk set test account filter

Turn 'filter out internal and test users' on or off for every existing insight in the project. Requires project admin, matching the settings UI that fronts it. The setting of the same name only decides the default for new insights; this applies it to the insights that already exist. Only insights that store a query are changed; insights still holding legacy filters are counted in legacy and left as they are. Insights with nowhere to put the toggle, such as SQL insights, are left alone, as are insights the requester cannot edit. Dashboards follow their insights unless the dashboard sets its own override. Insights are updated in batches, so a failure part way through leaves the finished batches applied. Retrying is safe and picks up the rest.

Required API key scopes

insight:write

Query parameters

  • format
    string
    One of: "csv""json"

Request parameters

  • enabled
    boolean

Response


Example request

POST /api/projects/:project_id/insights/bulk_set_test_account_filter
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/insights/bulk_set_test_account_filter/\
-d enabled="boolean"

Example response

Status 200
RESPONSE
{
"updated": 0,
"unchanged": 0,
"unsupported": 0,
"skipped": 0,
"legacy": 0
}

Create insights bulk update tags

Bulk update tags on multiple objects.

PAT access: this action has no required_scopes= on the decorator — inheriting viewsets must add "bulk_update_tags" to their scope_object_write_actions list to accept personal API keys. Without that opt-in, APIScopePermission rejects PAT requests with "This action does not support personal API key access". Done per-viewset so granting <scope>:write for one resource doesn't leak access to sibling resources that share this mixin.

Accepts:

  • {"ids": [...], "action": "add"|"remove"|"set", "tags": ["tag1", "tag2"]}

Actions:

  • "add": Add tags to existing tags on each object
  • "remove": Remove specific tags from each object
  • "set": Replace all tags on each object with the provided list

Query parameters

  • format
    string
    One of: "csv""json"

Request parameters

  • ids
    array
  • action
  • tags
    array

Response


Example request

POST /api/projects/:project_id/insights/bulk_update_tags
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/insights/bulk_update_tags/\
-d ids="array",\
-d action=undefined,\
-d tags="array"

Example response

Status 200
RESPONSE
{
"updated": [
{
"id": 0,
"tags": [
"string"
]
}
],
"skipped": [
{
"id": 0,
"reason": "string"
}
]
}

Create insights cancel

Query parameters

  • format
    string
    One of: "csv""json"

Request parameters

  • name
    string | null
  • derived_name
    string | null
  • query
  • order
    integer | null
  • deleted
    boolean
  • dashboards
    array
  • description
    string | null
  • tags
    array
  • favorited
    boolean
  • _create_in_folder
    string

Example request

POST /api/projects/:project_id/insights/cancel
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/insights/cancel/\
-d name="string"

Example response

Status 200 No response body

Create insights data checks

Check the events behind an insight for the common ways they mislead: internal and test users, local development traffic, bots and crawlers, and events sent twice. Works for trends, funnels, stickiness and lifecycle insights whose series are events. The checks apply the insight's own filters, and read the newest days of its date range, up to 7. The bot and duplicate checks read a sample of those days. For a token, the internal users check matches the emails of the organization's members only with the organization_member:read scope, and its verified domains only with organization:read. It names the emails it finds only with person:read. Nothing is stored. This route runs the query it is sent, so it needs query access as well as insight access. To check a saved insight by its id, send a GET request to insights/{id}/data_checks/.

Required API key scopes

insight:readquery:read

Query parameters

  • format
    string
    One of: "csv""json"

Request parameters

  • query
  • client_query_id
    string
  • depth
    Default: quick

Response


Example request

POST /api/projects/:project_id/insights/data_checks
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/insights/data_checks/\
-d query=undefined

Example response

Status 200 The result of every check.
RESPONSE
{
"status": "passed",
"checks": [
{
"key": "internal_users",
"level": "passed",
"skip_reason": "too_many_events",
"method": "counted",
"events": 0,
"share": 0,
"scaled": true,
"action": "filter_internal_users",
"top_events": [
"string"
],
"top_hosts": [
"string"
],
"distinct_hosts": 0,
"top_bots": [
"string"
],
"distinct_bots": 0,
"removed_by_filter": 0,
"missed_by_filter": 0,
"top_emails": [
"string"
],
"distinct_emails": 0,
"filter_to_add": {
"key": "string",
"type": "string",
"operator": "string",
"value": [
"string"
]
}
}
],
"coverage": {
"date_from": "2019-08-24",
"date_to": "2019-08-24",
"days_in_range": 0,
"checked_date_from": "2019-08-24",
"checked_date_to": "2019-08-24",
"days_checked": 0,
"filters_test_accounts": true,
"events_checked": 0,
"sample": {
"rate": 0.1,
"events": 0,
"distinct_ids": 0
}
}
}

Create insights generate metadata

Generate an AI-suggested name and description for an insight based on its query configuration.

Required API key scopes

insight:write

Query parameters

  • format
    string
    One of: "csv""json"

Request parameters

  • name
    string | null
  • derived_name
    string | null
  • query
  • order
    integer | null
  • deleted
    boolean
  • dashboards
    array
  • description
    string | null
  • tags
    array
  • favorited
    boolean
  • _create_in_folder
    string

Example request

POST /api/projects/:project_id/insights/generate_metadata
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/insights/generate_metadata/\
-d name="string"

Example response

Status 200 No response body

Retrieve insights my last viewed

Returns basic details about the last 5 insights viewed by this user. Most recently viewed first.

Query parameters

  • format
    string
    One of: "csv""json"

Example request

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

Example response

Status 200 No response body


Create insights viewed

Record that the current user has just viewed one or more insights. Submitted ids that do not belong to the current project or that point at deleted insights are silently dropped, as are views from impersonated staff-support sessions. Returns 201 on success regardless of how many ids were retained.

Required API key scopes

insight:read

Query parameters

  • format
    string
    One of: "csv""json"

Request parameters

  • insight_ids
    array

Example request

POST /api/projects/:project_id/insights/viewed
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/insights/viewed/\
-d insight_ids="array"

Example response

Status 201 Views recorded.