---
title: "Build History"
description: "See every release and patch run against your apps, whether it succeeded or why it failed, and how long it took"
---

Build history records every `shorebird release` and `shorebird patch` run against your apps: whether it succeeded, why it failed if it did, and how long each stage of the build took. Use it to answer questions such as how often patches failed in CI last month and why, or whether your iOS builds are getting slower, without keeping CI logs around.

Build history is available on the Enterprise plan. The Shorebird CLI records runs for every plan, so an organization that moves to Enterprise sees its earlier runs too, for as long as they’re kept. Runs are recorded by Shorebird 1.6.139 and newer.

## What a run records

The CLI sends one record per platform when a run ends, so `shorebird release android ios` makes two records that share a run ID. Each record has:

* **Command and platform**: `release` or `patch`, and `android`, `ios`, and so on.
* **Outcome**: `succeeded` or `failed`, and for a failed run, a [reason](#failure-reasons).
* **Release and patch**: the release the run made or patched, and the patch it made, if it got that far. A failed release can leave a draft release.
* **When and how long**: when the run started building this platform, and how long that platform took.
* **Timing breakdown**: how long each stage took, such as the Flutter build, the Gradle or Xcode build, Shorebird’s link step and, for a release, the upload.
* **Build facts**: for an iOS or macOS patch, its link percentage; whether it changed assets or native code, and whether it used `--allow-asset-diffs` or `--allow-native-diffs`; whether it ran on CI, and which provider; and the Shorebird, Flutter and Xcode versions and operating system it ran with.
* **Build flags**: the names of the `--dart-define` values the run passed, including those from `--dart-define-from-file`, with a SHA-256 hash of each value, and a hash of `--target`. Never the values or paths themselves. The hashes aren’t salted, so anyone who can read your build history can check a guess, such as `prod` or `lib/main_prod.dart`, against them.
* **Dry run**: whether it was a `--dry-run`, so checks you run on pull requests show apart from real releases and patches.
* **Who ran it**: the teammate, API key or service account the CLI signed in as.

A run record never holds logs, file paths, command lines, environment variables, dart-define values, machine or user names, or source code. The only error text it can hold is why Shorebird couldn’t read an iOS or macOS patch’s link details, when that happens: one line of about 200 characters at most, with everything from the first file path on replaced by `<path>`. [What Shorebird Collects](/system/what-shorebird-collects/#build-history) lists the same fields from the CLI’s side.

A run is recorded only once Shorebird has confirmed the app and, for a patch, found the release being patched. So runs that stop earlier, such as when you aren’t signed in, the checked-in `shorebird.yaml` is missing or the release doesn’t exist, aren’t recorded. Neither are runs you stop with Ctrl-C or that end because the CLI crashed. The CLI waits at most 5 seconds to send a record, and a record it can’t send in that time is dropped; the run’s result doesn’t change.

### Failure reasons

* `link_percentage`: the patch linked less of its code than your `--min-link-percentage` allows.
* `asset_diffs`, `native_diffs`, `build_flag_diffs`: the patch changed assets, native code or build flags since the release, and the run stopped there, either on its own (when the CLI can’t prompt, such as in CI, without the matching `--allow-*` flag) or because someone answered no when asked to continue.
* `build_failed`: the Flutter, Gradle or Xcode build failed.
* `release_incompatible`: the release can’t be patched on this platform: it has no build or isn’t active there, it was built with a Flutter version that’s too old, or your enterprise [requires patch signing](/enterprise/patch-signing/) and it wasn’t signed. For `shorebird release`, the existing release was built with a different Flutter version.
* `server_rejected`: Shorebird’s API refused a request, such as creating the release or patch.
* `upload_failed`: uploading the release or patch failed.
* `canceled`: someone declined a confirmation other than the asset, native code and build flag prompts above.
* `other`: a failure the CLI doesn’t sort into one of the reasons above.

## See build history in the console

In the [Shorebird console](https://console.shorebird.dev), open an app and choose its **Build history** tab. It lists the app’s runs newest first, with when each ran, the command, platform, release or patch, outcome or failure reason, duration and who ran it. Filter it by month, command and outcome; it offers the last 12 months, the current one first.

Above the list, totals for the month show how many runs there were, how many failed and why, and the median and 90th-percentile duration. Open a run to see its timing breakdown and, for an iOS or macOS patch, its link percentage.

Each release’s page has a **Build history** link that lists every run that made or patched that release, whatever the month. Patch runs in that list name their patch number.

## Read build history with the API

`GET /api/v1/organizations/{organizationId}/runs` returns the organization’s run records, newest first, a page at a time. The organization ID is the number after `/orgs/` in the console’s address bar. Members of the organization can read it, and so can a [service account](/account/service-accounts/) with the Viewer role or above, so a scheduled job can pull records into your own dashboards. Organizations without the Enterprise plan get `403`.

These query parameters narrow the results:

* `startDate` and `endDate`: ISO 8601 timestamps with a time zone, such as `2026-10-01T00:00:00Z`.
* `appId`: only runs for that app.
* `command`: `release` or `patch`.
* `outcome`: `succeeded` or `failed`.
* `releaseId`: runs that made or patched that release.
* `patchId`: runs that made that patch.
* `dryRun`: `true` for only `--dry-run` runs, `false` to leave them out.

For example, to list last month’s failed patches in an app:

```
shorebird api -X GET organizations/$ORG_ID/runs \
  -f appId=$APP_ID -f command=patch -f outcome=failed \
  -f startDate=2026-10-01T00:00:00Z -f endDate=2026-10-31T23:59:59Z
```

See [Calling the API](/account/api/) for authentication, and [Common patterns](/account/api/#common-patterns) for paging.

## How long runs are kept

Run records are kept for 13 months, so you can compare a month with the same month a year earlier. Deleting an app deletes its run records. When an app moves to another organization, the runs recorded before the move stay with the organization they were recorded in.
