# Last passing run per environment Source: https://empirical.run/docs/api-reference/analytics/last-passing-run-per-environment /api-reference/openapi.generated.json post /api/v2/analytics/test-case-last-pass-per-env Returns the most recent passing run for a test case, grouped by environment. # Test-case analytics Source: https://empirical.run/docs/api-reference/analytics/test-case-analytics /api-reference/openapi.generated.json get /api/v2/analytics/test-cases Returns aggregated test-case metrics for the scoped project (without per-test history). # Test-case execution history (batch) Source: https://empirical.run/docs/api-reference/analytics/test-case-execution-history-batch /api-reference/openapi.generated.json post /api/v2/analytics/test-case-history/batch Returns per-test-case execution history for the requested test cases, plus echoed query metadata. # Test-count analytics Source: https://empirical.run/docs/api-reference/analytics/test-count-analytics /api-reference/openapi.generated.json get /api/v2/analytics/test-count Returns the number of distinct test cases run per day for the scoped project. # Test-run analytics Source: https://empirical.run/docs/api-reference/analytics/test-run-analytics /api-reference/openapi.generated.json get /api/v2/analytics/test-runs Returns daily test-run statistics and a period summary for the scoped project. Analytics uses path-based versioning; the current recommended version is **v2** (`/api/v2/analytics/`). The **v1** endpoints (`/api/v1/analytics/*`) are deprecated but remain available for backward compatibility. In v2, the v1 `test-cases` endpoint is split: `GET /api/v2/analytics/test-cases` returns metrics only, and `POST /api/v2/analytics/test-case-history/batch` fetches history for one or many test cases in a single request. Percentage fields (`pass_rate`, `fail_rate`, `flaky_rate`) are integers in the **0-100** range, not decimals. All endpoints support date filtering via `days` (1-90), or a custom `start_date`/`end_date` range (ISO 8601). # Get an environment status badge Source: https://empirical.run/docs/api-reference/badges/get-an-environment-status-badge /api-reference/openapi.generated.json get /api/badges/projects/{project_slug}/environments/{environment_slug} Renders an SVG status badge (passing/failing/running/etc.) for the latest test run of a project environment. Served unauthenticated for embedding in READMEs. # Create an environment Source: https://empirical.run/docs/api-reference/environments/create-an-environment /api-reference/openapi.generated.json post /api/environments Creates an environment in the scoped project. Rejected for projects managed by environments.yaml. # Delete an environment Source: https://empirical.run/docs/api-reference/environments/delete-an-environment /api-reference/openapi.generated.json delete /api/environments/{id} Deletes an environment by ID and prunes environment-specific subscriptions. The project is derived from the entity. # List environments Source: https://empirical.run/docs/api-reference/environments/list-environments /api-reference/openapi.generated.json get /api/environments/list Returns the scoped project's environments, optionally filtered by slug and disabled state. The run worker uses this to resolve env vars by slug. # Sync environments from YAML Source: https://empirical.run/docs/api-reference/environments/sync-environments-from-yaml /api-reference/openapi.generated.json post /api/environments/sync Upserts the scoped project's environments from its environments.yaml file and flags the project as YAML-managed. # Update an environment Source: https://empirical.run/docs/api-reference/environments/update-an-environment /api-reference/openapi.generated.json patch /api/environments/{id} Updates an environment by ID. The project is derived from the entity. Returns the bare updated row (no `data` envelope), matching the dashboard settings UI it serves. # Attach a failing test to a failure group Source: https://empirical.run/docs/api-reference/failure-groups/attach-a-failing-test-to-a-failure-group /api-reference/openapi.generated.json post /api/failure-groups/{id}/members Records that a run's failing test belongs to this group, refreshing the group's last-seen rollups, and returns the derived member entry. Idempotent: re-attaching an existing member refreshes its sighting (the entry's sighting_count and last_seen reflect it). An agent attach will not resurrect a membership a human detached. # Create a failure group Source: https://empirical.run/docs/api-reference/failure-groups/create-a-failure-group /api-reference/openapi.generated.json post /api/failure-groups Creates a durable failure group for a new failure mode. Labels are unique per project: if the label already exists the request fails with 409 and returns the existing group unchanged — inspect it (note its status) and either reuse it via PATCH/attach or create under a different label. # Delete a failure group Source: https://empirical.run/docs/api-reference/failure-groups/delete-a-failure-group /api-reference/openapi.generated.json delete /api/failure-groups/{id} Deletes a failure group and its members. Its edit-history revisions survive. # Get a failure group Source: https://empirical.run/docs/api-reference/failure-groups/get-a-failure-group /api-reference/openapi.generated.json get /api/failure-groups/{id} Retrieves a single failure group. Its members are served by `GET /api/failure-groups/{id}/members`. # Get a failure group's activity Source: https://empirical.run/docs/api-reference/failure-groups/get-a-failure-groups-activity /api-reference/openapi.generated.json get /api/failure-groups/{id}/activity Returns the group's activity timeline (newest first): creation, authored edits, status changes, merges, member joins, repeat sightings, and removals. Derived from the revision trail and the membership-event log. # List a failure group's members Source: https://empirical.run/docs/api-reference/failure-groups/list-a-failure-groups-members /api-reference/openapi.generated.json get /api/failure-groups/{id}/members Returns the group's members (one entry per test, newest sighting first), derived from the membership-event log: state, provenance of the latest attach, first/last sighting, sighting count and environments. # List a run's failure-group members Source: https://empirical.run/docs/api-reference/failure-groups/list-a-runs-failure-group-members /api-reference/openapi.generated.json get /api/failure-groups/members Returns one entry per failed test in the run that is attached to a failure group, with the group's content hydrated. Read from the canonical membership-event log; when several sources attached the same test, human wins over agent over machine. Dedupe on group_id for the run's distinct groups. # List failure groups Source: https://empirical.run/docs/api-reference/failure-groups/list-failure-groups /api-reference/openapi.generated.json get /api/failure-groups Returns a paginated list of failure groups for the scoped project, newest sighting first. Use this to match a failure against an existing group before creating a new one. # Merge a failure group into another Source: https://empirical.run/docs/api-reference/failure-groups/merge-a-failure-group-into-another /api-reference/openapi.generated.json post /api/failure-groups/{id}/merge Moves this group's members into the target, unions fingerprints, and deletes this group. Returns the target. # Update a failure group Source: https://empirical.run/docs/api-reference/failure-groups/update-a-failure-group /api-reference/openapi.generated.json patch /api/failure-groups/{id} Updates a group's authored fields. `fingerprint`, when present, replaces the stored one; omit it to keep it. Latest write wins. Renaming to a label another group holds fails with 409 and returns that group — if the two are the same failure mode, merge them instead. # Introduction Source: https://empirical.run/docs/api-reference/introduction Base URL and authentication for the Empirical API The Empirical API lets you trigger and inspect test runs, manage snoozes, browse test cases and environments, and pull analytics. ## Base URL All endpoints are served from: ``` https://api.empirical.run ``` ## Authentication Generate a project API key under [Settings → API keys](https://empirical.run/settings/api-keys), then send it as a Bearer token: ```bash theme={null} curl https://api.empirical.run/api/test-runs \ -H "Authorization: Bearer $EMPIRICALRUN_KEY" ``` Project API keys are scoped to their project. Keep them secret and use a separate key for each automation context so it can be rotated independently. If you are signed in with the [Empirical CLI](/docs/cli), you can call the same endpoints without handling a key locally: ```sh theme={null} empirical api api/test-runs --project ``` ## Versioning Endpoint paths may be unversioned or include a version such as `/api/v2/`. Use the path shown in this reference rather than adding a version yourself. Deprecated endpoints are described in [openapi.deprecated.json](https://api.empirical.run/openapi.deprecated.json), including their replacements where available. The current public API is available as an [OpenAPI specification](https://api.empirical.run/openapi.json). # Create a resource Source: https://empirical.run/docs/api-reference/resources/create-a-resource /api-reference/openapi.generated.json post /api/resources Creates a resource. With `url`, creates a link-type file; otherwise creates a pending upload and returns a signed `upload_url` to stream the file into R2. # Delete a resource Source: https://empirical.run/docs/api-reference/resources/delete-a-resource /api-reference/openapi.generated.json delete /api/resources/{id} Deletes a resource, removing its R2 object and stopping any active Drive watch. # Download resource content Source: https://empirical.run/docs/api-reference/resources/download-resource-content /api-reference/openapi.generated.json get /api/resources/{id}/content Streams an uploaded resource's content from R2. Authorized by the signed capability URL (HMAC in the query string), not bearer auth. # Get a resource Source: https://empirical.run/docs/api-reference/resources/get-a-resource /api-reference/openapi.generated.json get /api/resources/{id} Retrieves a single resource by ID, with a fresh download URL. # List resources Source: https://empirical.run/docs/api-reference/resources/list-resources /api-reference/openapi.generated.json get /api/resources Returns a paginated list of uploaded resources for the project. # Update a resource Source: https://empirical.run/docs/api-reference/resources/update-a-resource /api-reference/openapi.generated.json patch /api/resources/{id} Updates a resource's name/description, or confirms a pending upload with `status: "uploaded"`. # Upload resource content Source: https://empirical.run/docs/api-reference/resources/upload-resource-content /api-reference/openapi.generated.json put /api/resources/{id}/content Streams the request body into R2 for a pending resource. Authorized by the signed capability URL (HMAC in the query string), not bearer auth. # Add tests to a snooze Source: https://empirical.run/docs/api-reference/snoozes/add-tests-to-a-snooze /api-reference/openapi.generated.json post /api/snoozes/{id}/add-test-cases Adds Playwright tests to an existing snooze. # Create a snooze Source: https://empirical.run/docs/api-reference/snoozes/create-a-snooze /api-reference/openapi.generated.json post /api/snoozes Creates a snooze to temporarily suppress failures for the given Playwright tests until `snooze_until`. # Delete a snooze Source: https://empirical.run/docs/api-reference/snoozes/delete-a-snooze /api-reference/openapi.generated.json delete /api/snoozes/{id} Permanently deletes a snooze. # Get a snooze Source: https://empirical.run/docs/api-reference/snoozes/get-a-snooze /api-reference/openapi.generated.json get /api/snoozes/{id} Retrieves a single snooze by ID. # List snoozes Source: https://empirical.run/docs/api-reference/snoozes/list-snoozes /api-reference/openapi.generated.json get /api/snoozes Returns a paginated list of snoozes for the scoped project, with optional filtering by environment and status. # Update a snooze Source: https://empirical.run/docs/api-reference/snoozes/update-a-snooze /api-reference/openapi.generated.json patch /api/snoozes/{id} Updates a snooze — extend it, change its tests/description, or expire it immediately with `expire_now`. # Get a test case Source: https://empirical.run/docs/api-reference/test-cases/get-a-test-case /api-reference/openapi.generated.json get /api/v2/test-cases/{id} Retrieves a single test case by its Playwright test ID. Access is derived from the test case's project, returning 403 when the caller cannot access it. # List test case tags Source: https://empirical.run/docs/api-reference/test-cases/list-test-case-tags /api-reference/openapi.generated.json get /api/v2/test-cases/tags Returns the distinct set of tags across the scoped project's active test cases (those present at the last synced commit; all synced test cases if the project has never synced). The response is a bare `{ tags }` object (no `data` envelope) and is cached for 5 minutes via a `Cache-Control` header. # List test cases Source: https://empirical.run/docs/api-reference/test-cases/list-test-cases /api-reference/openapi.generated.json get /api/v2/test-cases Returns a paginated list of the scoped project's test cases with optional filtering, along with the project's latest test-cases sync error. # Update test case tags Source: https://empirical.run/docs/api-reference/test-cases/update-test-case-tags /api-reference/openapi.generated.json patch /api/v2/test-cases/{id} Replaces the tags on a test case and attempts to update the source file. Access is derived from the test case's project, returning 403 when the caller cannot access it. # Cancel a test run Source: https://empirical.run/docs/api-reference/test-runs/cancel-a-test-run /api-reference/openapi.generated.json post /api/test-runs/{id}/cancel Cancels an in-progress test run, recording an optional reason and the cancelling user. Returns 412 when the run is already in a terminal state. # Get a test run Source: https://empirical.run/docs/api-reference/test-runs/get-a-test-run /api-reference/openapi.generated.json get /api/test-runs/{id} Retrieves a single test run by ID, including its project and per-test summary details. Access is derived from the run's project; inaccessible or unknown runs return 404. # Get test run metadata Source: https://empirical.run/docs/api-reference/test-runs/get-test-run-metadata /api-reference/openapi.generated.json get /api/v2/test-runs/{id} Returns Postgres-backed metadata for a test run. This endpoint does not read the run ledger or compose per-test results. # List test run artifacts Source: https://empirical.run/docs/api-reference/test-runs/list-test-run-artifacts /api-reference/openapi.generated.json get /api/test-runs/{id}/artifacts Lists downloadable artifacts (traces, reports, screenshots, etc.) stored for a test run. Provide `key` for an exact lookup, or `prefix`/`suffix` to filter the listing. Returns an empty list when nothing matches. # List test runs Source: https://empirical.run/docs/api-reference/test-runs/list-test-runs /api-reference/openapi.generated.json get /api/test-runs Returns a paginated list of test runs for the scoped project, with optional filtering by id, branch, state, result, environment, and time window. Test runs transition through these states: | State | Description | | - | - | | `pending` | Run is queued behind other runs (concurrency limit reached) | | `queued` | Run is queued and will start soon | | `started` | Run is currently executing | | `ended` | Run finished executing; inspect its result counts to determine whether tests passed | | `error` | Run failed with an error | | `cancelling` | Run is being cancelled | | `cancelled` | Run was cancelled | A failed run may carry one of these error codes: | Error code | Description | | - | - | | `branch_missing` | Explicitly requested test branch does not exist | | `provider_error` | Test-code provider failed during branch resolution | | `merge_conflict` | Merge conflict detected when merging the test branch | | `dispatch_failed` | Failed to dispatch the test run to workers | | `report_not_generated` | Test report was not generated | | `run_failed_with_error` | Test run failed with an error during execution | | `worker_interrupted` | Test run worker was interrupted | | `run_timed_out` | Test run exceeded the maximum duration | | `merge_reports_failed` | Failed to merge sharded reports | | `empty_selection` | The run's selection (tags or test case ids) matched no tests | # Re-run a test run Source: https://empirical.run/docs/api-reference/test-runs/re-run-a-test-run /api-reference/openapi.generated.json post /api/test-runs/{id}/re-run Re-triggers a test run from a source run's branch, build, and overrides. Optionally re-runs only the failed tests of a completed run. # Skip a test run Source: https://empirical.run/docs/api-reference/test-runs/skip-a-test-run /api-reference/openapi.generated.json post /api/v1/test-runs/skip Marks the Empirical check run on a commit as skipped. Callers authenticate with a project API key. # Trigger a test run Source: https://empirical.run/docs/api-reference/test-runs/trigger-a-test-run /api-reference/openapi.generated.json put /api/test-runs Triggers a new end-to-end test run for the scoped project against the given environment, resolving the branch/build and dispatching the run. # CLI Source: https://empirical.run/docs/cli Install and configure the Empirical command line tool The Empirical CLI lets you - or your local coding agents - work with Empirical from the terminal. The CLI also bundles an agent skill that can be configured for common coding agents (Claude Code and Codex). ## Install In your terminal, run: ```sh theme={null} # Install the standalone binary curl -fsSL https://cli.empirical.run/install | sh # Check installed version empirical version # Authenticate as yourself empirical login ``` The installer adds `~/.empirical/bin` to your shell `PATH`. If `empirical` is not available in a new terminal, add it manually: ```sh theme={null} export PATH="$HOME/.empirical/bin:$PATH" ``` Verify the login and see the projects available to you: ```sh theme={null} empirical whoami empirical api api/projects ``` ## Agent skill The Empirical skill teaches compatible local coding agents how to use the `empirical` command. The installer suggests this as a next step after install. Run it with exactly one of `--global` or `--project`: ```sh theme={null} # Install in the global agent directories (Claude Code, plus Codex and other agents) empirical skill install --global # Install in your project at .agents/skills empirical skill install --project ``` Run `empirical skill install --help` for all options. The `SKILL.md` file is managed by the CLI: installs and upgrades overwrite it, so don't edit it directly. To customize the skill for your project, add a `CUSTOM.md` file in the same directory — the skill instructs agents to read it, and the CLI never touches it. ## Commands reference ### User auth * `empirical login` authorizes the CLI with Empirical. * `empirical logout` clears local CLI authorization. * `empirical whoami` prints the current authenticated account. ### Version and upgrade * `empirical version` prints the installed CLI version. * `empirical upgrade` upgrades to the latest published CLI version. ### Agent skill * `empirical skill install` installs the Empirical `SKILL.md` for local coding agents, overwriting any existing copy. Requires exactly one of `--global` or `--project`. ### Sessions * `empirical session ""` creates a session and sends a prompt. * `empirical session --id ""` sends a prompt to an existing session. * `empirical session -x ""` creates a session, waits for the agent response, and prints only the final assistant text. * `empirical session -x --id ""` sends to an existing session, waits for the agent response, and prints only the final assistant text. * `echo "" | empirical session --execute --id ` reads the prompt from stdin. * `empirical session list` lists recent sessions. * `empirical session status ` shows the current agent and sandbox state (with the error reason when the sandbox failed), queued messages, latest assistant response, branches, and pull requests. * `empirical session logs ` prints the session history in chronological order with RFC 3339 UTC timestamps. Add `--since