# Public reports and badges

Source: https://docs.qualflare.com/docs/api/public-reports · Last updated: 2026-11-03

Embed the badge, banner and social images of a published Qualflare report, and read its launches as JSON with no token: every URL, state and cache time.

The data and images of a published Qualflare report are served without a token at `https://api.qualflare.com/p/<project-identifier>/`: a README badge and banner, social images, and read-only JSON for its launches.

|                    |                                                                                                                                                                                                                                  |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Which projects** | Projects with **Public report** on ([Publishing a Report](https://docs.qualflare.com/docs/open-source/publishing)). A report is published from an Open Source workspace, and stays public if the workspace later leaves the plan |
| **Token**          | None; the URLs are public                                                                                                                                                                                                        |
| **Base URL**       | `https://api.qualflare.com/p/<project-identifier>`                                                                                                                                                                               |
| **Report page**    | `https://reports.qualflare.com/p/<project-identifier>/launches`                                                                                                                                                                  |
| **Rate limit**     | [Requests per IP address](https://docs.qualflare.com/docs/api/limits#rate-limits)                                                                                                                                                |
| **CTRF export**    | Not on public URLs: use the [Launches API](https://docs.qualflare.com/docs/api/launches#export-ctrf) with a token                                                                                                                |

## Public URLs

Each path follows the base URL, and `<n>` is a launch's number. The last column gives the browser `max-age` and the edge `s-maxage`, in seconds.

| Path                                   | Returns                                                                                                            | Cached (browser / edge)               |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------- |
| `/badge.svg`                           | The [badge](https://docs.qualflare.com/docs/api/public-reports#badge), an SVG                               | 60 / 60                               |
| `/banner.svg`                          | The [banner](https://docs.qualflare.com/docs/api/public-reports#banner), an SVG                             | 60 / 60                               |
| `/og.png`                              | The launches page's [social image](https://docs.qualflare.com/docs/api/public-reports#social-images), a PNG | 300 / 1,800                           |
| `/launches/<n>/og.png`                 | One run's social image, a PNG                                                                                      | 300 / 1,800                           |
| `/meta`                                | The project and its [newest launch](https://docs.qualflare.com/docs/api/public-reports#meta)                | 30 / 120                              |
| `/launches`                            | The project and its [launches](https://docs.qualflare.com/docs/api/public-reports#launches), newest first   | 30 / 120                              |
| `/launches/<n>`                        | One launch ([fields](https://docs.qualflare.com/docs/api/public-reports#launch-fields))                     | finished 300 / 3,600; running 10 / 30 |
| `/launches/<n>/failures`               | The launch's [failed tests](https://docs.qualflare.com/docs/api/public-reports#cases)                       | as `/launches/<n>`                    |
| `/launches/<n>/cases`                  | Every test of the launch                                                                                           | as `/launches/<n>`                    |
| `/launches/<n>/cases/retried`          | Its retried tests, most retries first                                                                              | as `/launches/<n>`                    |
| `/launches/<n>/cases/slowest`          | Its slowest tests                                                                                                  | as `/launches/<n>`                    |
| `https://api.qualflare.com/p/projects` | Every published project                                                                                            | 30 / 120                              |

## Badge

The badge shows the newest launch of the report, with the label `qualflare`.

| Value         | Color | When                                                                                         |
| ------------- | ----- | -------------------------------------------------------------------------------------------- |
| `<n> passed`  | green | The newest launch finished and nothing failed; `<n>` is all its tests, skipped ones included |
| `<n> failing` | red   | The newest launch finished with failed, error, timed-out or aborted tests, added up          |
| `running`     | gray  | The newest launch's status is `pending`: it holds pending tests and nothing failed           |
| `no tests`    | gray  | It finished with no tests                                                                    |
| `no runs`     | gray  | The report has no launch yet, or the project isn't published                                 |

The badge always loads: an unknown or private project shows `no runs`, never a broken image. GitHub shows README images through its own image proxy, which can keep an older badge for a while. To add it to a README, see [Embeddable badge](https://docs.qualflare.com/docs/open-source/publishing#embeddable-badge).

## Banner

`banner.svg` is a 1280 × 232 image with the project name (or the linked `owner/repo`), pass rate, run count, flaky-case count, last-run time and a grid of recent runs. An unknown or private project gets a plain banner. For the Markdown and the light and dark note, see [Embeddable banner](https://docs.qualflare.com/docs/open-source/publishing#embeddable-banner).

## Social images

Slack, Discord and X show `og.png` when someone shares the launches page, and `launches/<n>/og.png` for one run: 1200 × 630 PNG cards. The launches card sums up the 60 newest launches. A missing project or run gets a generic card.

## Read launches as JSON

### Launches

`/launches` returns the `project` (`slug`, `name`, `description`, and `githubUrl` when a repository is linked) and its `launches`, newest first. `limit` takes 1 or more, 25 by default, and counts anything over 100 as 100. `offset` takes 0 or more.

```bash
curl -sS \
  "https://api.qualflare.com/p/<project-identifier>/launches?limit=10"
```

```json
{
  "project": { "slug": "myapp", "name": "My App", "description": "End-to-end tests", "githubUrl": "https://github.com/my-org/myapp" },
  "launches": [
    {
      "seq": 42, "status": "failed", "framework": "playwright", "platform": "web", "os": "linux",
      "browser": null, "language": "en-US", "branch": "main", "commit": "4f1c2ab",
      "ciProvider": null, "ciBuildNumber": null, "ciPrNumber": null,
      "totalCount": 120, "passedCount": 115, "failedCount": 2, "errorCount": 0, "skippedCount": 3,
      "timeoutCount": 0, "abortedCount": 0, "flakyCount": 1, "retryCount": 4,
      "startedAt": "2026-11-02T09:14:03Z", "endedAt": "2026-11-02T09:18:41Z"
    }
  ]
}
```

### Launch fields

| Field                                                                                      | What it holds                                                                                                                |
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| `seq`                                                                                      | The launch's number in the project                                                                                           |
| `status`                                                                                   | The launch's status, such as `passed`, `failed` or `pending`                                                                 |
| `framework`, `platform`, `os`, `browser`, `language`                                       | What the upload reported; `platform` is `web`, `api`, `android`, `ios` or `desktop`                                          |
| `branch`, `commit`                                                                         | The Git branch and commit                                                                                                    |
| `ciProvider`, `ciBuildNumber`, `ciPrNumber`                                                | The CI system, its build number and the pull request number                                                                  |
| `totalCount`                                                                               | All tests, skipped ones included                                                                                             |
| `passedCount`, `failedCount`, `errorCount`, `skippedCount`, `timeoutCount`, `abortedCount` | Tests with each status                                                                                                       |
| `flakyCount`, `retryCount`                                                                 | Flaky tests, and retries added up                                                                                            |
| `startedAt`, `endedAt`                                                                     | When the first suite started and the last one ended (UTC); without suite times, when the launch was created and last updated |

`browser`, `branch`, `commit` and the three CI fields are `null` when the upload didn't send them. Public answers leave out a launch's properties, metadata, AI summary, environment, milestone, test plan and CI run URL.

### Failures and cases

* `/failures` returns `{"failures": […], "truncated": false}`: the failed, error, timed-out and aborted tests, at most 200.
* `/cases` returns `{"cases": […], "truncated": false}`: every test, at most 500, by suite and name.
* `truncated` is `true` when the list was cut.
* Each test has `suite`, `test`, `seq` (the test case's number), `status`, `durationMs`, `failure` (`null` unless it failed), `flaky`, `retries`, `priority` and `automated`. `/cases/retried` also gives `attemptStatuses`, each attempt's status in order, when the upload recorded attempts.
* `/cases/retried` and `/cases/slowest` return the same `cases` list, 6 tests by default. `limit` takes 1 or more and counts anything over 20 as 20.

### Project and latest launch

`/meta` returns the project's `slug`, `name` and `description`, its `githubUrl` when a repository is linked, and `latest`: its newest launch, or `null` while the report has no launch.

## Caching

Qualflare's edge caches these answers. A running launch is cached for 30 seconds, a finished one for up to an hour, the badge and banner for a minute. Cached pages can stay visible for up to about an hour. This applies after you unpublish too: [Turning it on](https://docs.qualflare.com/docs/open-source/publishing#turning-it-on). Every other API route sends `Cache-Control: no-store`.

## Errors

| Status | Code and message                                            | When                                                             |
| ------ | ----------------------------------------------------------- | ---------------------------------------------------------------- |
| `400`  | `common.invalid_input`: `invalid limit` or `invalid offset` | `limit` or `offset` isn't a number in range                      |
| `400`  | `common.invalid_input`: `invalid launch sequence`           | `<n>` isn't a number of 1 or more                                |
| `404`  | `project.not_found`: `project not found`                    | The project doesn't exist or isn't published, or it is suspended |
| `404`  | `launch.not_found`: `launch not found`                      | The report has no launch with that number                        |
| `429`  | `common.rate_limited`                                       | Too many requests from your IP address                           |

The badge, banner and social images answer `200` with a generic image for a missing, private or suspended project, or a bad run number. Every status: [Errors and status codes](https://docs.qualflare.com/docs/api/errors).

## Search engines

reports.qualflare.com lists each report's launches page in its sitemap and lets search engines index it; single-run pages are `noindex`.

## Related

* **Guides:** [Publishing a Report](https://docs.qualflare.com/docs/open-source/publishing) · [Setting Up CI](https://docs.qualflare.com/docs/open-source/ci-setup)
* **Reference:** [Launches API](https://docs.qualflare.com/docs/api/launches) · [Rate limits and request sizes](https://docs.qualflare.com/docs/api/limits)
* **CLI/API:** [Qualflare API](https://docs.qualflare.com/docs/api)
