# Break down CI wall-clock time (/api/time/get-time)

`GET /api/time`

Phase decomposition: job/attempt level splits wall-clock into the frozen phase enum with a per-step breakdown; run level adds a timing-inferred critical path, parallelism efficiency, and the blocking job; repo level aggregates p50/p95 per phase per runner label. Scoped to the caller's orgs by membership.

Base URL: `https://runners.starsling.dev`

## Authentication

Requires a bearer token (`Authorization: Bearer`).

## Parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `org` | query | string | yes | GitHub organization login. Required — timings are always org-scoped. e.g. `acme` |
| `level` | query | string | yes | Granularity of the breakdown — it selects which id you pass. `job`, `attempt`, `run`, `repo`; e.g. `attempt` |
| `job_id` | query | string | no | Target job, for level=job or level=attempt. e.g. `88886665361` |
| `run_id` | query | string | no | Target run, for level=run. e.g. `2990884649` |
| `attempt` | query | string \| integer | no | Pin a run to one attempt. Defaults to the latest. 1–4294967295; e.g. `2` |
| `repo` | query | string | no | Target repository, for level=repo, as owner/name. e.g. `acme/api` |
| `window` | query | string | no | Relative lookback, e.g. 30d. Mutually exclusive with month and from/to. e.g. `30d` |
| `month` | query | string | no | A whole calendar month, YYYY-MM. e.g. `2026-06` |
| `from` | query | string | no | Start of the range, inclusive. Required with `to`. e.g. `2026-06-01` |
| `to` | query | string | no | End of the range, exclusive. Required with `from`. e.g. `2026-07-01` |

## Responses

| Status | Description |
| --- | --- |
| `200` | Wall-clock split into runner-lifecycle phases. The shape follows `level`; `meta.truncated` names anything the facts store could not account for. |
| `400` | The id the `level` requires is missing (`job_id` for job/attempt, `run_id` for run, `repo` for repo), or the window flags conflict. |
| `401` | No credential, or a GitHub grant too old to read org membership — re-run `sling login`. |
| `403` | You are not a member of the org named in `?org=`. |
| `404` | No such job, run, or repo in that org. A target in an org you can't see answers the same way — existence is never confirmed across a tenant boundary. |
| `422` | A query parameter failed schema validation — most often an unrecognised `level`. `details` names the offending field. |
| `500` | The control plane failed, or the CI facts store is not configured for this deployment. |

### `200` body

- **Variant 1** — object
  - `level` — string, required. e.g. `attempt`
    - **Variant 1** — string
    - **Variant 2** — string
  - `id` — string, required. e.g. `att_88886665361.1`
  - `run_id` — string, required. e.g. `2990884649`
  - `job_id` — string, required. e.g. `88886665361`
  - `attempt` — number, required. e.g. `1`
  - `job_name` — string, required. e.g. `typecheck`
  - `wall_clock_ms` — number, required. e.g. `89000`
  - `phases` — array<object>, required
    - array of object
  - `steps` — array<object>, required
    - array of object
  - `meta` — object, required
    - `source` — string, required. `logs`, `steps`; e.g. `steps`
    - `truncated` — array<object>, required
- **Variant 2** — object
  - `level` — string, required. `run`
  - `run_id` — string, required. e.g. `2990884649`
  - `wall_clock_ms` — number, required. e.g. `420000`
  - `wait_time_ms` — number, required. e.g. `18000`
  - `critical_path` — array<object>, required
    - array of object
  - `parallelism_efficiency` — number, required. e.g. `0.62`
  - `blocking_job` — object | null, required. e.g. `null`
    - `job_id` — string, required. e.g. `88886665361`
    - `job_name` — string, required. e.g. `typecheck`
    - `ms` — number, required. e.g. `89000`
  - `meta` — object, required
    - `source` — string, required. `logs`, `steps`; e.g. `steps`
    - `truncated` — array<object>, required
- **Variant 3** — object
  - `level` — string, required. `repo`
  - `repo` — string, required. e.g. `acme/api`
  - `window` — object, required
    - `from` — string, required
    - `to` — string, required
  - `phases` — array<object>, required
    - array of object
  - `meta` — object, required
    - `source` — string, required. `logs`, `steps`; e.g. `steps`
    - `truncated` — array<object>, required

### Example

```json
{
  "level": "attempt",
  "id": "att_88886665361.1",
  "run_id": "2990884649",
  "job_id": "88886665361",
  "attempt": 1,
  "job_name": "typecheck",
  "wall_clock_ms": 89000,
  "phases": [
    {
      "key": "queue_wait",
      "ms": 16000,
      "pct": 18
    },
    {
      "key": "provision",
      "ms": 9000,
      "pct": 10.1,
      "detail": {
        "instance_type": "c7a.2xlarge"
      }
    },
    {
      "key": "steps",
      "ms": 61000,
      "pct": 68.5
    },
    {
      "key": "teardown",
      "ms": 3000,
      "pct": 3.4
    }
  ],
  "steps": [
    {
      "key": "Set up job",
      "ms": 2000,
      "conclusion": "success"
    },
    {
      "key": "Run e2e tests",
      "ms": 59000,
      "conclusion": "failure"
    }
  ],
  "meta": {
    "source": "steps",
    "truncated": [
      {
        "key": "image_pull",
        "reason": "bundled into provision — no v1 facts source"
      }
    ]
  }
}
```