---
title: "List flaky tests with optional field expansion."
method: GET
path: "/api/v1/flaky/tests"
tags: ["Flaky"]
---

# List flaky tests with optional field expansion.

`GET /api/v1/flaky/tests`

## Request

- Base URL: `https://platform.buildpulse.io`
- URL: `https://platform.buildpulse.io/api/v1/flaky/tests`
- Auth: one of:
  - API key in header `Authorization`
  - HTTP bearer

Returns flaky tests for the named repository. Exactly one of
`repository` (name) or `repository_id` (legacy numeric ID from
the Rails API era) must be supplied; omitting both returns
`400`.

### Optional fields

By default the response is a minimal shape: `id`, `name`,
`suite`, `class`, `file`. Pass `include=field1,field2,…` to
expand any of:

- `disruptiveness_ratio`
- `nondeterministic_negative_result_count`
- `nondeterminism_first_recorded_at`
- `recent_nondeterministic_commit_oid`
- `recent_nondeterministic_negative_result`
- `recent_nondeterministic_positive_result`
- `tags`
- `quarantine_date`
- `quarantined_by`
- `quarantine_type`
- `time_consumed`
- `pass_rate`
- `avg_duration_ms`

Unknown fields are silently dropped.

### Quarantine

**This endpoint returns quarantined tests by default.** Pass
`quarantine=false` to get non-quarantined flaky tests instead.
The two modes are mutually exclusive — a test is either
quarantined or it isn't — and together they cover every flaky
test on the repository.

| Request | Returns |
| --- | --- |
| `?repository=widgets` | Quarantined tests (**default**) |
| `?repository=widgets&quarantine=false` | Non-quarantined tests, within the reporting window |

Only the literal value `false` selects the non-quarantined view;
any other value (including `0`) is treated as `true`, matching
the legacy API. `quarantined` is accepted as an alias for
`quarantine`.

### Reporting window

The **non-quarantined** view only returns tests that were
disruptive within your plan's reporting period (default 14
days). This bounds the response to currently-relevant flakes
rather than every flake ever recorded.

The **quarantined** view is deliberately *not* windowed: a test
quarantined a year ago is still quarantined, so it is still
returned.

### Per-occurrence history

Each returned `id` is a test (disruptor) ID that can be passed
to `GET /api/tests/{id}/results` to fetch that test's recent
disruption events (build URL, commit, failure message,
timestamp) — the typical pattern for scripted triage reports:
list the inventory here, then fetch history per test.

## Query parameters

- `repository` string
- `repository_id` string
- `limit` integer
- `after` string
- `include` string
- `quarantine` 'true' | 'false'
- `quarantined` 'true' | 'false'
- `sort` 'disruptivenessRatio' | 'recency'
- `q` string

## Response `200`

Paginated flaky tests.

- FlakyTestsResponse
  - `count` integer, required
  - `tests` FlakyTest[], required
    - `id` string, required
    - `name` string, required
    - `suite` string, required
    - `class` string, required
    - `file` string, required
    - `disruptiveness_ratio` number, float: Only present when `include` lists `disruptiveness_ratio`.
    - `disruption_count` integer: Only present when `include` lists `nondeterministic_negative_result_count`.
    - `first_disruption_at` string, date-time: Only present when `include` lists `nondeterminism_first_recorded_at`.
    - `recent_disruption_commit_oid` string: Only present when `include` lists `recent_nondeterministic_commit_oid`.
    - `recent_nondeterministic_negative_result` Result
      - `recorded_at` string, date-time, required
      - `build_url` string, uri, required
      - `message` string, nullable, required: Failure message (negative result) or always `null` (positive result, to match legacy behavior).
    - `recent_nondeterministic_positive_result` Result
      - `recorded_at` string, date-time, required
      - `build_url` string, uri, required
      - `message` string, nullable, required: Failure message (negative result) or always `null` (positive result, to match legacy behavior).
    - `tags` string[]
    - `quarantine_date` string, date-time, nullable
    - `quarantined_by` string, nullable
    - `quarantine_type` string, nullable
    - `time_consumed` integer
    - `pass_rate` number, float: Fraction of runs in which this test passed (0.0–1.0). Only present when `include` lists `pass_rate`.
    - `avg_duration_ms` number, float: Average per-attempt duration in milliseconds across all recorded runs of this test. Only present when `include` lists `avg_duration_ms`.
  - `metadata` Metadata, required
    - `after` string, nullable, required: Opaque cursor for the next page; `null` if there is no next page.
    - `limit` integer, required

## Other responses

- `400`: Cursor failed to decode.
- `401`: Missing, malformed, or invalid token; or — for legacy 40-hex tokens only — the organization has no active plan (`marketplacePurchases.unitCount > 0`). The new `bp_<64-hex>` path has no plan gate, so a 401 there means the token shape was wrong, the hash didn't match, or the token has expired. Response body is empty (matches legacy Rails).
- `402`: The organization is over its plan's monthly test-result limit and data-read access is restricted (staged-overage stage `soft` or `hard`). At `soft` the data is locked but safe — ingestion keeps recording. At `hard` ingestion is also paused (raw retained ~30 days) and an upgrade resumes processing. Read `GET /api/v1/usage` for the current stage and usage, and visit `upgradeUrl` to restore access. Only returned for organizations positively identified as over the enforced limit while enforcement is enabled.
- `404`: Resource not found.

---

[API](https://skmtc.dev/buildpulse/apis/buildpulse-platform-api.md) · [All operations](https://skmtc.dev/buildpulse/apis/buildpulse-platform-api/llms.txt) · [OpenAPI document](https://skmtc.dev/buildpulse/apis/buildpulse-platform-api/revisions/2e68b4b2df6a?raw)
