Engineering

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

Endpoints

GET
GET
GET
GET
GET
GET
POST
GET
GET
GET

Retrieve engineering analytics pr

The timeline of a single pull request: header plus ordered events (opened, CI started/finished, merged or closed). Use this to answer 'where is this PR stuck and what happened to it'. This is a partial view: review and comment events are not yet available.

Required API key scopes

engineering_analytics:read

Query parameters

  • pr_number
    integer
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pr_lifecycle
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/pr_lifecycle/

Example response

Status 200
RESPONSE
{
"pull_request": {
"author": {
"handle": "string",
"display_name": "string",
"avatar_url": "string",
"is_bot": true
},
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"id": 0,
"number": 0,
"title": "string",
"state": "open",
"is_draft": true,
"created_at": "2019-08-24T14:15:22Z",
"merged_at": "2019-08-24T14:15:22Z",
"closed_at": "2019-08-24T14:15:22Z"
},
"events": [
{
"kind": "opened",
"at": "2019-08-24T14:15:22Z",
"detail": "string",
"run_id": 0,
"ci_engine": "github_actions"
}
],
"metric_quality": "precise"
}
Status 400 Missing pr_number/repo, or invalid repo or source_id.
Status 404 No pull request with that number in the warehouse.

Retrieve engineering analytics pr

The timeline of a single pull request: header plus ordered events (opened, CI started/finished, merged or closed). Use this to answer 'where is this PR stuck and what happened to it'. This is a partial view: review and comment events are not yet available.

Required API key scopes

engineering_analytics:read

Query parameters

  • pr_number
    integer
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pr_lifecycle
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/pr_lifecycle/

Example response

Status 200
RESPONSE
{
"pull_request": {
"author": {
"handle": "string",
"display_name": "string",
"avatar_url": "string",
"is_bot": true
},
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"id": 0,
"number": 0,
"title": "string",
"state": "open",
"is_draft": true,
"created_at": "2019-08-24T14:15:22Z",
"merged_at": "2019-08-24T14:15:22Z",
"closed_at": "2019-08-24T14:15:22Z"
},
"events": [
{
"kind": "opened",
"at": "2019-08-24T14:15:22Z",
"detail": "string",
"run_id": 0,
"ci_engine": "github_actions"
}
],
"metric_quality": "precise"
}
Status 400 Missing pr_number/repo, or invalid repo or source_id.
Status 404 No pull request with that number in the warehouse.

Retrieve engineering analytics pr

Every workflow run attributed to a pull request, across all its commits (grouped by head SHA client-side), newest first. Run-level only.

Required API key scopes

engineering_analytics:read

Query parameters

  • pr_number
    integer
  • repo
    string
  • source_id
    string

Example request

GET /api/projects/:project_id/engineering_analytics/pr_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/pr_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,
"commit_pr_number": 0,
"is_merge_queue": true,
"ci_engine": "github_actions",
"native_run_id": "string",
"native_workflow_run_id": "string",
"workflow_id": 0,
"event": "string"
}
Status 400 Missing pr_number/repo, or invalid repo or source_id.

Retrieve engineering analytics pr

Every workflow run attributed to a pull request, across all its commits (grouped by head SHA client-side), newest first. Run-level only.

Required API key scopes

engineering_analytics:read

Query parameters

  • pr_number
    integer
  • repo
    string
  • source_id
    string

Example request

GET /api/projects/:project_id/engineering_analytics/pr_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/pr_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,
"commit_pr_number": 0,
"is_merge_queue": true,
"ci_engine": "github_actions",
"native_run_id": "string",
"native_workflow_run_id": "string",
"workflow_id": 0,
"event": "string"
}
Status 400 Missing pr_number/repo, or invalid repo or source_id.

Retrieve engineering analytics pull request

One merged pull request's friction as a multiple of the typical pull request, with the counts behind it: red CI by cause, re-runs that failed again, CI time per push, the wait for the first approval, merge-queue time and failed queue attempts, and rework. Covers pull requests merged in the last 30 days.

Required API key scopes

engineering_analytics:read

Query parameters

  • pr_number
    integer
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pull_request_friction
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/pull_request_friction/

Example response

Status 200
RESPONSE
{
"pull_request": {
"groups": [
{
"group": "ci",
"score": 0.1
}
],
"score": 0.1,
"flake_red_count": 0,
"master_red_count": 0,
"unknown_red_count": 0,
"own_red_count": 0,
"futile_rerun_count": 0,
"push_count": 0,
"ci_wait_seconds": [
0.1
],
"first_approval_wait_seconds": 0,
"pushes_after_approval": 0,
"queue_seconds": 0,
"kickout_count": 0
},
"available": true,
"window_days": 0
}
Status 400 Missing pr_number or repo, or invalid source_id.

Retrieve engineering analytics pull request

One merged pull request's friction as a multiple of the typical pull request, with the counts behind it: red CI by cause, re-runs that failed again, CI time per push, the wait for the first approval, merge-queue time and failed queue attempts, and rework. Covers pull requests merged in the last 30 days.

Required API key scopes

engineering_analytics:read

Query parameters

  • pr_number
    integer
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pull_request_friction
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/pull_request_friction/

Example response

Status 200
RESPONSE
{
"pull_request": {
"groups": [
{
"group": "ci",
"score": 0.1
}
],
"score": 0.1,
"flake_red_count": 0,
"master_red_count": 0,
"unknown_red_count": 0,
"own_red_count": 0,
"futile_rerun_count": 0,
"push_count": 0,
"ci_wait_seconds": [
0.1
],
"first_approval_wait_seconds": 0,
"pushes_after_approval": 0,
"queue_seconds": 0,
"kickout_count": 0
},
"available": true,
"window_days": 0
}
Status 400 Missing pr_number or repo, or invalid source_id.

Retrieve engineering analytics pull request

Pull requests as timelines of what each waited on from ready for review to merge or now: review, CI, red checks by what turned them green, and the merge queue. Scope to one author or one GitHub team (open PRs plus PRs merged in the window, date_from default -30d), or to one pull request with pr_number and repo.

Required API key scopes

engineering_analytics:read

Query parameters

  • author
    string
  • date_from
    string
  • date_to
    string
  • github_team
    string
  • pr_number
    integer
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pull_request_timelines
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/pull_request_timelines/

Example response

Status 200
RESPONSE
{
"items": [
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"pushes": [
{
"head_sha": "string",
"pushed_at": "2019-08-24T14:15:22Z"
}
],
"segments": [
{
"kind": "draft",
"started_at": "2019-08-24T14:15:22Z",
"ended_at": "2019-08-24T14:15:22Z"
}
],
"number": 0,
"title": "string",
"author": {
"handle": "string",
"display_name": "string",
"avatar_url": "string",
"is_bot": true
},
"state": "open",
"is_draft": true,
"created_at": "2019-08-24T14:15:22Z",
"started_at": "2019-08-24T14:15:22Z",
"merged_at": "2019-08-24T14:15:22Z",
"estimated_cost_usd": 0,
"billable_minutes": 0
}
],
"red_seconds_per_merged_pr": [
{
"kind": "draft",
"seconds_per_merged_pr": 0.1
}
],
"scope_kind": "author",
"scope": "string",
"has_membership_data": true,
"review_data_available": true,
"jobs_available": true,
"merge_queue_state_available": true,
"generated_at": "2019-08-24T14:15:22Z",
"merged_pr_count": 0,
"truncated": true,
"limit": 0
}
Status 400 Not exactly one of author, github_team or pr_number, pr_number without repo, or invalid date or source_id.
Status 503 The complete result exceeds the request's warehouse query budget.

Retrieve engineering analytics pull request

Pull requests as timelines of what each waited on from ready for review to merge or now: review, CI, red checks by what turned them green, and the merge queue. Scope to one author or one GitHub team (open PRs plus PRs merged in the window, date_from default -30d), or to one pull request with pr_number and repo.

Required API key scopes

engineering_analytics:read

Query parameters

  • author
    string
  • date_from
    string
  • date_to
    string
  • github_team
    string
  • pr_number
    integer
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pull_request_timelines
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/pull_request_timelines/

Example response

Status 200
RESPONSE
{
"items": [
{
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"pushes": [
{
"head_sha": "string",
"pushed_at": "2019-08-24T14:15:22Z"
}
],
"segments": [
{
"kind": "draft",
"started_at": "2019-08-24T14:15:22Z",
"ended_at": "2019-08-24T14:15:22Z"
}
],
"number": 0,
"title": "string",
"author": {
"handle": "string",
"display_name": "string",
"avatar_url": "string",
"is_bot": true
},
"state": "open",
"is_draft": true,
"created_at": "2019-08-24T14:15:22Z",
"started_at": "2019-08-24T14:15:22Z",
"merged_at": "2019-08-24T14:15:22Z",
"estimated_cost_usd": 0,
"billable_minutes": 0
}
],
"red_seconds_per_merged_pr": [
{
"kind": "draft",
"seconds_per_merged_pr": 0.1
}
],
"scope_kind": "author",
"scope": "string",
"has_membership_data": true,
"review_data_available": true,
"jobs_available": true,
"merge_queue_state_available": true,
"generated_at": "2019-08-24T14:15:22Z",
"merged_pr_count": 0,
"truncated": true,
"limit": 0
}
Status 400 Not exactly one of author, github_team or pr_number, pr_number without repo, or invalid date or source_id.
Status 503 The complete result exceeds the request's warehouse query budget.

Retrieve engineering analytics pull

Open pull requests plus any merged or closed since date_from (default -30d), newest first, each with its head-SHA CI rollup. Pass state to list one state only. The list is paged by limit and offset; when more match, truncated is true and the ci_cards counts can exceed it. open_to_merge_seconds is coarse: it fuses draft and ready-for-review time; CI counts can lag until late completions settle. Cost and billable minutes can lag new CI by up to 5 minutes.

Required API key scopes

engineering_analytics:read

Query parameters

  • author
    string
  • date_from
    string
  • date_to
    string
  • limit
    integer
  • offset
    integer
  • repo
    string
  • source_id
    string
  • state
    string
    One of: "closed""merged""open"

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pull_requests
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/pull_requests/

Example response

Status 200
RESPONSE
{
"items": [
{
"author": {
"handle": "string",
"display_name": "string",
"avatar_url": "string",
"is_bot": true
},
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"ci": {
"runs": 0,
"passing": 0,
"failing": 0,
"pending": 0,
"inconclusive": 0,
"failing_workflows": [
"string"
]
},
"push_history": [
{
"head_sha": "string",
"started_at": "2019-08-24T14:15:22Z",
"wall_seconds": 0,
"failed": true,
"pending": true
}
],
"number": 0,
"title": "string",
"state": "open",
"is_draft": true,
"created_at": "2019-08-24T14:15:22Z",
"merged_at": "2019-08-24T14:15:22Z",
"open_to_merge_seconds": 0,
"ready_to_merge_seconds": 0,
"labels": [
"string"
],
"pushes": 0,
"rerun_cycles": 0,
"estimated_cost_usd": 0,
"billable_minutes": 0
}
],
"truncated": true,
"limit": 0
}
Status 400 Invalid date_from, date_to, state, limit, offset, or source_id.

Retrieve engineering analytics pull

Open pull requests plus any merged or closed since date_from (default -30d), newest first, each with its head-SHA CI rollup. Pass state to list one state only. The list is paged by limit and offset; when more match, truncated is true and the ci_cards counts can exceed it. open_to_merge_seconds is coarse: it fuses draft and ready-for-review time; CI counts can lag until late completions settle. Cost and billable minutes can lag new CI by up to 5 minutes.

Required API key scopes

engineering_analytics:read

Query parameters

  • author
    string
  • date_from
    string
  • date_to
    string
  • limit
    integer
  • offset
    integer
  • repo
    string
  • source_id
    string
  • state
    string
    One of: "closed""merged""open"

Response


Example request

GET /api/projects/:project_id/engineering_analytics/pull_requests
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/pull_requests/

Example response

Status 200
RESPONSE
{
"items": [
{
"author": {
"handle": "string",
"display_name": "string",
"avatar_url": "string",
"is_bot": true
},
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"ci": {
"runs": 0,
"passing": 0,
"failing": 0,
"pending": 0,
"inconclusive": 0,
"failing_workflows": [
"string"
]
},
"push_history": [
{
"head_sha": "string",
"started_at": "2019-08-24T14:15:22Z",
"wall_seconds": 0,
"failed": true,
"pending": true
}
],
"number": 0,
"title": "string",
"state": "open",
"is_draft": true,
"created_at": "2019-08-24T14:15:22Z",
"merged_at": "2019-08-24T14:15:22Z",
"open_to_merge_seconds": 0,
"ready_to_merge_seconds": 0,
"labels": [
"string"
],
"pushes": 0,
"rerun_cycles": 0,
"estimated_cost_usd": 0,
"billable_minutes": 0
}
],
"truncated": true,
"limit": 0
}
Status 400 Invalid date_from, date_to, state, limit, offset, or source_id.

Retrieve engineering analytics

The repository's checked-in .test_quarantine.json: flaky tests temporarily quarantined with a hard expiry, classified by urgency (overdue, in grace, expiring soon, active). available is false when the repo has no quarantine file: that is not an error. Parsing is fail-open: malformed entries are reported in parse_errors while well-formed ones are kept.

Required API key scopes

engineering_analytics:read

Query parameters

  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/quarantine
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/quarantine/

Example response

Status 200
RESPONSE
{
"entries": [
{
"id": "string",
"runner": "string",
"reason": "string",
"owner": "string",
"issue": "string",
"added": "2019-08-24",
"expires": "2019-08-24",
"mode": "run",
"lifecycle": "active",
"days_until_expiry": 0,
"selector_kind": "product"
}
],
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"available": true,
"parse_errors": [
"string"
],
"parse_warnings": [
"string"
],
"source_url": "string",
"generated_at": "2019-08-24T14:15:22Z"
}
Status 400 Invalid repo or source_id.

Retrieve engineering analytics

The repository's checked-in .test_quarantine.json: flaky tests temporarily quarantined with a hard expiry, classified by urgency (overdue, in grace, expiring soon, active). available is false when the repo has no quarantine file: that is not an error. Parsing is fail-open: malformed entries are reported in parse_errors while well-formed ones are kept.

Required API key scopes

engineering_analytics:read

Query parameters

  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/quarantine
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/quarantine/

Example response

Status 200
RESPONSE
{
"entries": [
{
"id": "string",
"runner": "string",
"reason": "string",
"owner": "string",
"issue": "string",
"added": "2019-08-24",
"expires": "2019-08-24",
"mode": "run",
"lifecycle": "active",
"days_until_expiry": 0,
"selector_kind": "product"
}
],
"repo": {
"provider": "string",
"owner": "string",
"name": "string"
},
"available": true,
"parse_errors": [
"string"
],
"parse_warnings": [
"string"
],
"source_url": "string",
"generated_at": "2019-08-24T14:15:22Z"
}
Status 400 Invalid repo or source_id.

Create engineering analytics quarantine

Opens a pull request that edits the repository's checked-in .test_quarantine.json and, for a new quarantine, opens a tracking issue that the PR links but does not close. The file stays the source of truth that CI enforces; this never bypasses it. A quarantine only affects CI runs that start after the PR merges.

Required API key scopes

engineering_analytics:write

Request parameters

  • operation
  • selector
    string
  • runner
  • repo
    string | null
  • reason
    string
  • owner
    string
  • issue
    string
  • expires
    string | null
  • mode

Response


Example request

POST /api/projects/:project_id/engineering_analytics/quarantine/request
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/engineering_analytics/quarantine/request/\
-d operation=undefined,\
-d selector="string"

Example response

Status 201 The opened pull request, plus the tracking issue for a new quarantine.
RESPONSE
{
"pr_url": "string",
"issue_url": "string",
"branch": "string"
}
Status 400 Invalid input, or the write could not be completed (no GitHub App installed on the repo's org, a malformed quarantine file, or a GitHub failure). The detail message is safe to show.

Create engineering analytics quarantine

Opens a pull request that edits the repository's checked-in .test_quarantine.json and, for a new quarantine, opens a tracking issue that the PR links but does not close. The file stays the source of truth that CI enforces; this never bypasses it. A quarantine only affects CI runs that start after the PR merges.

Required API key scopes

engineering_analytics:write

Request parameters

  • operation
  • selector
    string
  • runner
  • repo
    string | null
  • reason
    string
  • owner
    string
  • issue
    string
  • expires
    string | null
  • mode

Response


Example request

POST /api/projects/:project_id/engineering_analytics/quarantine/request
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/engineering_analytics/quarantine/request/\
-d operation=undefined,\
-d selector="string"

Example response

Status 201 The opened pull request, plus the tracking issue for a new quarantine.
RESPONSE
{
"pr_url": "string",
"issue_url": "string",
"branch": "string"
}
Status 400 Invalid input, or the write could not be completed (no GitHub App installed on the repo's org, a malformed quarantine file, or a GitHub failure). The detail message is safe to show.

Retrieve engineering analytics repo

Repo-level headline aggregates over a window (default -30d): run count, conclusive-run success rate, re-run cycles, merged-PR count (bots included), reverting-PR count and revert share (merges whose title names a revert, over all merges), median PR open-to-merge (bots and drafts excluded; coarse: draft and ready time fused), median time-to-green, billable minutes + estimated cost (with the merge-queue slice of billable minutes broken out), and merge-queue landing stats (queue-landed merges, first-gate-to-merge median and p90, gate attempts, failed-gate share): each with its equal-length previous-window twin so a caller can render honest deltas. Also carries the detected default branch and its completed-run history series (skippable via include_series=false). Cost figures are null until the job-level source is synced.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • include_series
    boolean
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/repo_overview
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/repo_overview/

Example response

Status 200
RESPONSE
{
"cost_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"estimated_cost_usd": 0,
"merges": 0,
"cost_per_merge_usd": 0
}
],
"time_to_green_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"p50_seconds": 0
}
],
"success_rate_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"success_rate": 0
}
],
"open_to_merge_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"p50_seconds": 0
}
],
"delivery_pipeline": {
"stages": [
{
"stage": "open_to_gate",
"median_seconds": 0,
"p90_seconds": 0,
"pr_count": 0
}
],
"merged_pr_count": 0
},
"ready_to_merge_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"p50_seconds": 0
}
],
"revert_share_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"merged_pr_count": 0,
"reverting_pr_count": 0,
"revert_share": 0
}
],
"run_count": 0,
"run_count_prev": 0,
"success_rate": 0,
"success_rate_prev": 0,
"rerun_cycles": 0,
"rerun_cycles_prev": 0,
"merged_pr_count": 0,
"merged_pr_count_prev": 0,
"reverting_pr_count": 0,
"reverting_pr_count_prev": 0,
"revert_share": 0,
"revert_share_prev": 0,
"median_open_to_merge_seconds": 0,
"median_open_to_merge_seconds_prev": 0,
"median_ready_to_merge_seconds": 0,
"median_ready_to_merge_seconds_prev": 0,
"billable_minutes": 0,
"billable_minutes_prev": 0,
"estimated_cost_usd": 0,
"estimated_cost_usd_prev": 0,
"cost_per_merge_usd": 0,
"cost_per_merge_usd_prev": 0,
"merge_queue_billable_minutes": 0,
"merge_queue_billable_minutes_prev": 0,
"depot_ci_billable_minutes": 0,
"depot_ci_billable_minutes_prev": 0,
"merge_queue_merged_pr_count": 0,
"merge_queue_merged_pr_count_prev": 0,
"merge_queue_median_first_gate_to_merge_seconds": 0,
"merge_queue_median_first_gate_to_merge_seconds_prev": 0,
"merge_queue_p90_first_gate_to_merge_seconds": 0,
"merge_queue_p90_first_gate_to_merge_seconds_prev": 0,
"merge_queue_p95_first_gate_to_merge_seconds": 0,
"merge_queue_p95_first_gate_to_merge_seconds_prev": 0,
"merge_queue_p99_first_gate_to_merge_seconds": 0,
"merge_queue_p99_first_gate_to_merge_seconds_prev": 0,
"merge_queue_avg_attempts_per_merge": 0,
"merge_queue_avg_attempts_per_merge_prev": 0,
"merge_queue_multi_attempt_merge_share": 0,
"merge_queue_multi_attempt_merge_share_prev": 0,
"merge_queue_failed_gate_merge_share": 0,
"merge_queue_failed_gate_merge_share_prev": 0,
"merge_queue_trunk_available": true,
"merge_queue_failed_or_cancelled_share": 0,
"merge_queue_failed_or_cancelled_share_prev": 0,
"merge_queue_skip_the_line_count": 0,
"merge_queue_skip_the_line_count_prev": 0,
"median_time_to_green_seconds": 0,
"median_time_to_green_seconds_prev": 0,
"jobs_available": true,
"default_branch": "string",
"cost_series_granularity": "string",
"time_to_green_series_granularity": "string",
"success_rate_series_granularity": "string",
"open_to_merge_series_granularity": "string",
"ready_to_merge_series_granularity": "string",
"revert_share_series_granularity": "string"
}
Status 400 Invalid date_from, date_to, or source_id, or a window over 366 days.

Retrieve engineering analytics repo

Repo-level headline aggregates over a window (default -30d): run count, conclusive-run success rate, re-run cycles, merged-PR count (bots included), reverting-PR count and revert share (merges whose title names a revert, over all merges), median PR open-to-merge (bots and drafts excluded; coarse: draft and ready time fused), median time-to-green, billable minutes + estimated cost (with the merge-queue slice of billable minutes broken out), and merge-queue landing stats (queue-landed merges, first-gate-to-merge median and p90, gate attempts, failed-gate share): each with its equal-length previous-window twin so a caller can render honest deltas. Also carries the detected default branch and its completed-run history series (skippable via include_series=false). Cost figures are null until the job-level source is synced.

Required API key scopes

engineering_analytics:read

Query parameters

  • date_from
    string
  • date_to
    string
  • include_series
    boolean
  • repo
    string
  • source_id
    string

Response


Example request

GET /api/projects/:project_id/engineering_analytics/repo_overview
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/repo_overview/

Example response

Status 200
RESPONSE
{
"cost_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"estimated_cost_usd": 0,
"merges": 0,
"cost_per_merge_usd": 0
}
],
"time_to_green_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"p50_seconds": 0
}
],
"success_rate_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"success_rate": 0
}
],
"open_to_merge_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"p50_seconds": 0
}
],
"delivery_pipeline": {
"stages": [
{
"stage": "open_to_gate",
"median_seconds": 0,
"p90_seconds": 0,
"pr_count": 0
}
],
"merged_pr_count": 0
},
"ready_to_merge_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"p50_seconds": 0
}
],
"revert_share_series": [
{
"bucket_start": "2019-08-24T14:15:22Z",
"merged_pr_count": 0,
"reverting_pr_count": 0,
"revert_share": 0
}
],
"run_count": 0,
"run_count_prev": 0,
"success_rate": 0,
"success_rate_prev": 0,
"rerun_cycles": 0,
"rerun_cycles_prev": 0,
"merged_pr_count": 0,
"merged_pr_count_prev": 0,
"reverting_pr_count": 0,
"reverting_pr_count_prev": 0,
"revert_share": 0,
"revert_share_prev": 0,
"median_open_to_merge_seconds": 0,
"median_open_to_merge_seconds_prev": 0,
"median_ready_to_merge_seconds": 0,
"median_ready_to_merge_seconds_prev": 0,
"billable_minutes": 0,
"billable_minutes_prev": 0,
"estimated_cost_usd": 0,
"estimated_cost_usd_prev": 0,
"cost_per_merge_usd": 0,
"cost_per_merge_usd_prev": 0,
"merge_queue_billable_minutes": 0,
"merge_queue_billable_minutes_prev": 0,
"depot_ci_billable_minutes": 0,
"depot_ci_billable_minutes_prev": 0,
"merge_queue_merged_pr_count": 0,
"merge_queue_merged_pr_count_prev": 0,
"merge_queue_median_first_gate_to_merge_seconds": 0,
"merge_queue_median_first_gate_to_merge_seconds_prev": 0,
"merge_queue_p90_first_gate_to_merge_seconds": 0,
"merge_queue_p90_first_gate_to_merge_seconds_prev": 0,
"merge_queue_p95_first_gate_to_merge_seconds": 0,
"merge_queue_p95_first_gate_to_merge_seconds_prev": 0,
"merge_queue_p99_first_gate_to_merge_seconds": 0,
"merge_queue_p99_first_gate_to_merge_seconds_prev": 0,
"merge_queue_avg_attempts_per_merge": 0,
"merge_queue_avg_attempts_per_merge_prev": 0,
"merge_queue_multi_attempt_merge_share": 0,
"merge_queue_multi_attempt_merge_share_prev": 0,
"merge_queue_failed_gate_merge_share": 0,
"merge_queue_failed_gate_merge_share_prev": 0,
"merge_queue_trunk_available": true,
"merge_queue_failed_or_cancelled_share": 0,
"merge_queue_failed_or_cancelled_share_prev": 0,
"merge_queue_skip_the_line_count": 0,
"merge_queue_skip_the_line_count_prev": 0,
"median_time_to_green_seconds": 0,
"median_time_to_green_seconds_prev": 0,
"jobs_available": true,
"default_branch": "string",
"cost_series_granularity": "string",
"time_to_green_series_granularity": "string",
"success_rate_series_granularity": "string",
"open_to_merge_series_granularity": "string",
"ready_to_merge_series_granularity": "string",
"revert_share_series_granularity": "string"
}
Status 400 Invalid date_from, date_to, or source_id, or a window over 366 days.

Retrieve engineering analytics repo run

Default-branch health as compact chart points over a window (default -30d), newest first, for the repo-hub run-activity chart. All of a commit's workflow runs are collapsed into ONE point per commit (head SHA): its earliest workflow start, wall-clock duration until the last workflow settled (null while any is still running), and an overall conclusion that is 'failure' if any workflow decisively failed, else 'success' when at least one passed, else 'neutral'. branch overrides the detected default branch. truncated is true when more commits matched than the cap, so the chart covers only the most recent commits.

Required API key scopes

engineering_analytics:read

Query parameters

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

Response


Example request

GET /api/projects/:project_id/engineering_analytics/repo_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/repo_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",
"ci_engine": "github_actions"
}
],
"truncated": true,
"limit": 0
}
Status 400 Invalid date_from, date_to, or source_id, or a window over 366 days.

Retrieve engineering analytics repo run

Default-branch health as compact chart points over a window (default -30d), newest first, for the repo-hub run-activity chart. All of a commit's workflow runs are collapsed into ONE point per commit (head SHA): its earliest workflow start, wall-clock duration until the last workflow settled (null while any is still running), and an overall conclusion that is 'failure' if any workflow decisively failed, else 'success' when at least one passed, else 'neutral'. branch overrides the detected default branch. truncated is true when more commits matched than the cap, so the chart covers only the most recent commits.

Required API key scopes

engineering_analytics:read

Query parameters

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

Response


Example request

GET /api/projects/:project_id/engineering_analytics/repo_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/repo_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",
"ci_engine": "github_actions"
}
],
"truncated": true,
"limit": 0
}
Status 400 Invalid date_from, date_to, or source_id, or a window over 366 days.

Retrieve engineering analytics resolve

Resolve a git branch to the pull request(s) it belongs to: the cross-product link seam so another product (the LLM analytics UI) can turn a git branch into a PR detail link. Matches the PR's head ref, open PRs first then most recently updated. Pass timestamp (the trace's capture time) to prefer the PR that was active at that moment when a branch name has been reused across PRs. branch is required. Returns a possibly-empty, possibly-multi list: an empty list is a valid 200 (the caller renders a plain chip).

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • repo
    string
  • source_id
    string
  • timestamp
    string

Example request

GET /api/projects/:project_id/engineering_analytics/resolve_branch
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/resolve_branch/

Example response

Status 200
RESPONSE
{
"repo": "string",
"number": 0,
"title": "string",
"state": "string"
}
Status 400 Branch missing/empty, or invalid repo/timestamp/source_id.

Retrieve engineering analytics resolve

Resolve a git branch to the pull request(s) it belongs to: the cross-product link seam so another product (the LLM analytics UI) can turn a git branch into a PR detail link. Matches the PR's head ref, open PRs first then most recently updated. Pass timestamp (the trace's capture time) to prefer the PR that was active at that moment when a branch name has been reused across PRs. branch is required. Returns a possibly-empty, possibly-multi list: an empty list is a valid 200 (the caller renders a plain chip).

Required API key scopes

engineering_analytics:read

Query parameters

  • branch
    string
  • repo
    string
  • source_id
    string
  • timestamp
    string

Example request

GET /api/projects/:project_id/engineering_analytics/resolve_branch
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/resolve_branch/

Example response

Status 200
RESPONSE
{
"repo": "string",
"number": 0,
"title": "string",
"state": "string"
}
Status 400 Branch missing/empty, or invalid repo/timestamp/source_id.