Engineering

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

Endpoints

GET
GET
GET
GET
GET
GET
GET
GET
GET
GET

Retrieve engineering analytics

The team's selectable GitHub repositories, oldest source first — one entry per repository a source is configured to sync, so a source syncing several repositories appears once per repo. Populate a repo picker from this and pass a chosen entry's id back as source_id and its repo back as repo to the other endpoints. Includes repositories whose tables aren't fully synced yet.

Required API key scopes

engineering_analytics:read

Example request

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

Example response

Status 200
RESPONSE
{
"id": "string",
"repo": "string",
"prefix": "string",
"synced": true
}

Retrieve engineering analytics

The team's selectable GitHub repositories, oldest source first — one entry per repository a source is configured to sync, so a source syncing several repositories appears once per repo. Populate a repo picker from this and pass a chosen entry's id back as source_id and its repo back as repo to the other endpoints. Includes repositories whose tables aren't fully synced yet.

Required API key scopes

engineering_analytics:read

Example request

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

Example response

Status 200
RESPONSE
{
"id": "string",
"repo": "string",
"prefix": "string",
"synced": true
}

Retrieve engineering analytics team ci

One owning team's CI test activity: per-test current-vs-prior signal pairs (the before/after comparison) over the window and its equal-length prior twin. Signal = runs where an owned test failed, errored, or a retry recovered it. Counts are absolute, never rates: CI emits a span for every failure but only for passes slow enough to clear the emitter's duration threshold, so there is no execution denominator. 'suspected_regression' means no recovery was recorded in this data, not that the test never flakes.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • owner_team
    string
  • source_id
    string
  • test_limit
    integer

Response


Example request

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

Example response

Status 200
RESPONSE
{
"tests": [
{
"nodeid": "string",
"selector": "string",
"signal_count": 0,
"signal_count_prior": 0,
"last_seen_at": "2019-08-24T14:15:22Z"
}
],
"owner_team": "string",
"truncated_tests": true
}
Status 400 Missing owner_team, invalid date, test_limit, or source_id, or a window longer than 30 days.

Retrieve engineering analytics team ci

One owning team's CI test activity: per-test current-vs-prior signal pairs (the before/after comparison) over the window and its equal-length prior twin. Signal = runs where an owned test failed, errored, or a retry recovered it. Counts are absolute, never rates: CI emits a span for every failure but only for passes slow enough to clear the emitter's duration threshold, so there is no execution denominator. 'suspected_regression' means no recovery was recorded in this data, not that the test never flakes.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • owner_team
    string
  • source_id
    string
  • test_limit
    integer

Response


Example request

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

Example response

Status 200
RESPONSE
{
"tests": [
{
"nodeid": "string",
"selector": "string",
"signal_count": 0,
"signal_count_prior": 0,
"last_seen_at": "2019-08-24T14:15:22Z"
}
],
"owner_team": "string",
"truncated_tests": true
}
Status 400 Missing owner_team, invalid date, test_limit, or source_id, or a window longer than 30 days.

Retrieve engineering analytics team ci

Per-owning-team rollup of the CI test surfaces each team owns, over the same run evidence as flaky_tests and with the same meaning of flaky: flaky_test_count is owned tests one commit was seen both failing and passing in the window, regression_test_count is owned tests that failed with no such proof and still hit the blast-radius bar, plus failed/recovery/quarantined run counts. Each has an equal-length previous-window twin for honest deltas. Ownership is stamped on the spans at CI emission time from the repo's ownership map (products/*/product.yaml + CODEOWNERS); unstamped spans aggregate under the literal team 'unowned', and a re-stamped test lands under its latest owner only. Teams are organizational owners of code surfaces, never authors. Counts are absolute, never rates: CI emits a span for every failure but only for passes slow enough to clear the emitter's duration threshold, so there is no execution denominator. 'suspected_regression' means no recovery was recorded in this data, not that the test never flakes.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • limit
    integer
  • min_failed_prs
    integer
  • source_id
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"items": [
{
"owner_team": "string",
"flaky_test_count": 0,
"flaky_test_count_prior": 0,
"regression_test_count": 0,
"regression_test_count_prior": 0,
"failed_run_count": 0,
"failed_run_count_prior": 0,
"same_commit_recovery_run_count": 0,
"same_commit_recovery_run_count_prior": 0,
"quarantined_failed_run_count": 0,
"quarantined_failed_run_count_prior": 0,
"last_seen_at": "2019-08-24T14:15:22Z"
}
],
"truncated": true,
"limit": 0
}
Status 400 Invalid date, threshold, limit, or source_id, or a window longer than 30 days.

Retrieve engineering analytics team ci

Per-owning-team rollup of the CI test surfaces each team owns, over the same run evidence as flaky_tests and with the same meaning of flaky: flaky_test_count is owned tests one commit was seen both failing and passing in the window, regression_test_count is owned tests that failed with no such proof and still hit the blast-radius bar, plus failed/recovery/quarantined run counts. Each has an equal-length previous-window twin for honest deltas. Ownership is stamped on the spans at CI emission time from the repo's ownership map (products/*/product.yaml + CODEOWNERS); unstamped spans aggregate under the literal team 'unowned', and a re-stamped test lands under its latest owner only. Teams are organizational owners of code surfaces, never authors. Counts are absolute, never rates: CI emits a span for every failure but only for passes slow enough to clear the emitter's duration threshold, so there is no execution denominator. 'suspected_regression' means no recovery was recorded in this data, not that the test never flakes.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • limit
    integer
  • min_failed_prs
    integer
  • source_id
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"items": [
{
"owner_team": "string",
"flaky_test_count": 0,
"flaky_test_count_prior": 0,
"regression_test_count": 0,
"regression_test_count_prior": 0,
"failed_run_count": 0,
"failed_run_count_prior": 0,
"same_commit_recovery_run_count": 0,
"same_commit_recovery_run_count_prior": 0,
"quarantined_failed_run_count": 0,
"quarantined_failed_run_count_prior": 0,
"last_seen_at": "2019-08-24T14:15:22Z"
}
],
"truncated": true,
"limit": 0
}
Status 400 Invalid date, threshold, limit, or source_id, or a window longer than 30 days.

Retrieve engineering analytics team merge

One team's daily time-to-merge trend: the median and average open→merge seconds over the PRs the team's members merged each day (PR author login → GitHub org team membership). Team-level aggregates only, never per-member figures or cross-team rankings. Timing is the coarse open→merge (draft + review time combined); bots are excluded. Requires the GitHub source's team_members snapshot; has_membership_data is false without it.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • owner_team
    string
  • source_id
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"points": [
{
"day": "2019-08-24T14:15:22Z",
"median_seconds": 0,
"average_seconds": 0,
"merged_count": 0
}
],
"owner_team": "string",
"has_membership_data": true
}
Status 400 Missing owner_team, invalid date or source_id, or a window longer than 30 days.

Retrieve engineering analytics team merge

One team's daily time-to-merge trend: the median and average open→merge seconds over the PRs the team's members merged each day (PR author login → GitHub org team membership). Team-level aggregates only, never per-member figures or cross-team rankings. Timing is the coarse open→merge (draft + review time combined); bots are excluded. Requires the GitHub source's team_members snapshot; has_membership_data is false without it.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • owner_team
    string
  • source_id
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"points": [
{
"day": "2019-08-24T14:15:22Z",
"median_seconds": 0,
"average_seconds": 0,
"merged_count": 0
}
],
"owner_team": "string",
"has_membership_data": true
}
Status 400 Missing owner_team, invalid date or source_id, or a window longer than 30 days.

Retrieve engineering analytics workflow

Per-workflow CI health over a window (default last 24 hours, maximum 366 days): run count, success rate, p50/p95 duration, last failure time, latest-run status, and a zero-filled run history bucketed by hour/day/week to fit the window. p50/p95 are over successful runs only, so cancelled (superseded) and failed runs never bias the duration trend. Optionally scope to a single git branch via branch, or to attributed pull-request runs via run_scope=pull_request. Use this for 'is CI getting slower' and 'which workflow is the long pole'; compare two windows to get a trend.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • run_scope
    string
    One of: "all""pull_request"
  • source_id
    string

Example request

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

Example response

Status 200
RESPONSE
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"buckets": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"run_count": 0,
"completed": 0,
"successes": 0,
"failures": 0
}
],
"workflow_name": "string",
"run_count": 0,
"successful_run_count": 0,
"conclusive_run_count": 0,
"success_rate": 0,
"p50_seconds": 0,
"p95_seconds": 0,
"last_failure_at": "2019-08-24T14:15:22Z",
"latest_run_failed": true,
"latest_run_conclusion": "string",
"latest_run_id": 0,
"latest_run_attempt": 0,
"granularity": "string",
"billable_minutes": 0,
"estimated_cost_usd": 0,
"rerun_cycles": 0,
"success_rate_prev": 0,
"percentile_run_count": 0
}
Status 400 Invalid date_from, date_to, run_scope, or source_id, or a window longer than 366 days.

Retrieve engineering analytics workflow

Per-workflow CI health over a window (default last 24 hours, maximum 366 days): run count, success rate, p50/p95 duration, last failure time, latest-run status, and a zero-filled run history bucketed by hour/day/week to fit the window. p50/p95 are over successful runs only, so cancelled (superseded) and failed runs never bias the duration trend. Optionally scope to a single git branch via branch, or to attributed pull-request runs via run_scope=pull_request. Use this for 'is CI getting slower' and 'which workflow is the long pole'; compare two windows to get a trend.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • run_scope
    string
    One of: "all""pull_request"
  • source_id
    string

Example request

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

Example response

Status 200
RESPONSE
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"buckets": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"run_count": 0,
"completed": 0,
"successes": 0,
"failures": 0
}
],
"workflow_name": "string",
"run_count": 0,
"successful_run_count": 0,
"conclusive_run_count": 0,
"success_rate": 0,
"p50_seconds": 0,
"p95_seconds": 0,
"last_failure_at": "2019-08-24T14:15:22Z",
"latest_run_failed": true,
"latest_run_conclusion": "string",
"latest_run_id": 0,
"latest_run_attempt": 0,
"granularity": "string",
"billable_minutes": 0,
"estimated_cost_usd": 0,
"rerun_cycles": 0,
"success_rate_prev": 0,
"percentile_run_count": 0
}
Status 400 Invalid date_from, date_to, run_scope, or source_id, or a window longer than 366 days.

Retrieve engineering analytics workflow

Jobs of a single workflow run attempt, with per-job duration, runner tier, and estimated cost. Scoped to one run_attempt (the latest unless specified) so a re-run's attempts don't merge. Returns an empty list when the job-level source isn't synced yet.

Required API key scopes

engineering_analytics:read

Query parameters

  • repo
    string
  • run_attempt
    integer
  • run_id
    integer
  • source_id
    string

Example request

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

Example response

Status 200
RESPONSE
{
"id": 0,
"run_id": 0,
"name": "string",
"status": "string",
"conclusion": "string",
"started_at": "2019-08-24T14:15:22Z",
"completed_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"runner_provider": "string",
"runner_label": "string",
"estimated_cost_usd": 0
}
Status 400 Missing or non-integer run_id/run_attempt, or invalid source_id.

Retrieve engineering analytics workflow

Jobs of a single workflow run attempt, with per-job duration, runner tier, and estimated cost. Scoped to one run_attempt (the latest unless specified) so a re-run's attempts don't merge. Returns an empty list when the job-level source isn't synced yet.

Required API key scopes

engineering_analytics:read

Query parameters

  • repo
    string
  • run_attempt
    integer
  • run_id
    integer
  • source_id
    string

Example request

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

Example response

Status 200
RESPONSE
{
"id": 0,
"run_id": 0,
"name": "string",
"status": "string",
"conclusion": "string",
"started_at": "2019-08-24T14:15:22Z",
"completed_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"runner_provider": "string",
"runner_label": "string",
"estimated_cost_usd": 0
}
Status 400 Missing or non-integer run_id/run_attempt, or invalid source_id.

Retrieve engineering analytics workflow

A single workflow run: status, conclusion, duration, branch, attempt, and the attributed pull request. Run-level only — per-job and per-step detail are not tracked yet.

Required API key scopes

engineering_analytics:read

Query parameters

  • repo
    string
  • run_id
    integer
  • source_id
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"id": 0,
"workflow_name": "string",
"head_sha": "string",
"head_branch": "string",
"status": "string",
"conclusion": "string",
"run_started_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"run_attempt": 0,
"pr_number": 0
}
Status 400 Missing or non-integer run_id, or invalid source_id.
Status 404 No workflow run with that id in the warehouse.

Retrieve engineering analytics workflow

A single workflow run: status, conclusion, duration, branch, attempt, and the attributed pull request. Run-level only — per-job and per-step detail are not tracked yet.

Required API key scopes

engineering_analytics:read

Query parameters

  • repo
    string
  • run_id
    integer
  • source_id
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"id": 0,
"workflow_name": "string",
"head_sha": "string",
"head_branch": "string",
"status": "string",
"conclusion": "string",
"run_started_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"run_attempt": 0,
"pr_number": 0
}
Status 400 Missing or non-integer run_id, or invalid source_id.
Status 404 No workflow run with that id in the warehouse.

Retrieve engineering analytics workflow run

Compact per-run points for a single workflow over a window (date_from default -30d), newest first, for the run-activity chart: each run's start time, duration, conclusion, branch, and attributed PR. Optionally scope to a single git branch via branch, matching workflow_runs. Leaner and higher-capped than workflow_runs so the chart spans the full window even on busy workflows; truncated is true when the cap is hit, so the chart covers only the most recent runs.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • source_id
    string
  • workflow_name
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"points": [
{
"run_id": 0,
"conclusion": "string",
"run_started_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"head_branch": "string",
"pr_number": 0,
"head_sha": "string"
}
],
"truncated": true,
"limit": 0
}
Status 400 Missing workflow_name/repo, or invalid date or source_id.

Retrieve engineering analytics workflow run

Compact per-run points for a single workflow over a window (date_from default -30d), newest first, for the run-activity chart: each run's start time, duration, conclusion, branch, and attributed PR. Optionally scope to a single git branch via branch, matching workflow_runs. Leaner and higher-capped than workflow_runs so the chart spans the full window even on busy workflows; truncated is true when the cap is hit, so the chart covers only the most recent runs.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • source_id
    string
  • workflow_name
    string

Response


Example request

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

Example response

Status 200
RESPONSE
{
"points": [
{
"run_id": 0,
"conclusion": "string",
"run_started_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"head_branch": "string",
"pr_number": 0,
"head_sha": "string"
}
],
"truncated": true,
"limit": 0
}
Status 400 Missing workflow_name/repo, or invalid date or source_id.

Retrieve engineering analytics workflow runner

A workflow's estimated CI cost broken down by runner tier over a window (date_from default -30d), highest spend first. Optionally scope to a single git branch via branch. Returns an empty list when the job-level source isn't synced.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • source_id
    string
  • workflow_name
    string

Example request

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

Example response

Status 200
RESPONSE
{
"provider": "string",
"runner_label": "string",
"job_count": 0,
"billable_minutes": 0.1,
"estimated_cost_usd": 0
}
Status 400 Missing workflow_name/repo, or invalid date or source_id.

Retrieve engineering analytics workflow runner

A workflow's estimated CI cost broken down by runner tier over a window (date_from default -30d), highest spend first. Optionally scope to a single git branch via branch. Returns an empty list when the job-level source isn't synced.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • source_id
    string
  • workflow_name
    string

Example request

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

Example response

Status 200
RESPONSE
{
"provider": "string",
"runner_label": "string",
"job_count": 0,
"billable_minutes": 0.1,
"estimated_cost_usd": 0
}
Status 400 Missing workflow_name/repo, or invalid date or source_id.

Retrieve engineering analytics workflow

Runs of a single workflow within a repo over a window (date_from default -30d), newest first. Optionally scope to a single git branch via branch. Each row is run-level — per-job and per-step detail are not tracked yet. Use this as the GitHub 'workflow' page between the workflow list and a single run.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • source_id
    string
  • workflow_name
    string

Example request

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

Example response

Status 200
RESPONSE
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"id": 0,
"workflow_name": "string",
"head_sha": "string",
"head_branch": "string",
"status": "string",
"conclusion": "string",
"run_started_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"run_attempt": 0,
"pr_number": 0
}
Status 400 Missing workflow_name/repo, or invalid date or source_id.

Retrieve engineering analytics workflow

Runs of a single workflow within a repo over a window (date_from default -30d), newest first. Optionally scope to a single git branch via branch. Each row is run-level — per-job and per-step detail are not tracked yet. Use this as the GitHub 'workflow' page between the workflow list and a single run.

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • date_from
    string
  • date_to
    string
  • repo
    string
  • source_id
    string
  • workflow_name
    string

Example request

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

Example response

Status 200
RESPONSE
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"id": 0,
"workflow_name": "string",
"head_sha": "string",
"head_branch": "string",
"status": "string",
"conclusion": "string",
"run_started_at": "2019-08-24T14:15:22Z",
"updated_at": "2019-08-24T14:15:22Z",
"duration_seconds": 0,
"run_attempt": 0,
"pr_number": 0
}
Status 400 Missing workflow_name/repo, or invalid date or source_id.

Community questions