> ## Documentation Index
> Fetch the complete documentation index at: https://docs.elementary-data.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction

> Read Elementary's assets, columns, lineage, and tests over a REST API.

The **Elementary Public API** is a REST interface for programmatically reading
the assets, columns, lineage, and tests Elementary tracks for one
environment. Use it to sync your data catalog, lineage, and test results into
your own systems (a warehouse, a BI tool, a data catalog, an internal service).

<Warning>
  This API is in **active development (beta)** and is **not intended for
  production use**. The interface can change — including **breaking changes** —
  while we co-design it with early adopters, and availability, stability, and
  support are not guaranteed. Endpoints live under `/public/beta`; wait for a
  stable `v1` before depending on it in production. See
  [Versioning](/api/versioning).
</Warning>

## Base URL

```
https://prod.api.elementary-data.com/public/beta
```

## Quickstart

<Steps>
  <Step title="Get a token">
    Create a personal or account token in Elementary and send it as a bearer token.
    See [Authentication](/api/authentication).
  </Step>

  <Step title="Discover your environments">
    ```bash theme={null}
    curl -H "Authorization: Bearer $ELEMENTARY_TOKEN" \
      "https://prod.api.elementary-data.com/public/beta/environments"
    ```

    Each returned `id` is an `env_id` you use in every other endpoint.
  </Step>

  <Step title="List assets">
    ```bash theme={null}
    curl -H "Authorization: Bearer $ELEMENTARY_TOKEN" \
      "https://prod.api.elementary-data.com/public/beta/$ENV_ID/assets?limit=500"
    ```

    Follow `next_cursor` until `has_more` is `false` — see [Pagination](/api/pagination).
  </Step>
</Steps>

## What you can read

| Resource | Endpoint | Notes |
| - | - | - |
| Environments | `GET /environments` | Account-scoped discovery |
| Assets | `GET /{env_id}/assets` | Every asset, common fields + `kind` |
| Table assets | `GET /{env_id}/assets/tables` | Table assets + warehouse-specific fields |
| BI assets | `GET /{env_id}/assets/bi` | BI assets + BI-specific fields |
| Columns | `GET /{env_id}/columns` | Columns of assets |
| Asset lineage | `GET /{env_id}/asset-lineage` | Asset-to-asset edges |
| Column lineage | `GET /{env_id}/column-lineage` | Column-to-column edges |
| Tests | `GET /{env_id}/tests` | Test definitions |
| Latest test executions | `GET /{env_id}/latest-test-executions` | Current run per sub-test |
| Test execution history | `GET /{env_id}/tests/{test_id}/executions` | History for one test |
| Asset health scores | `GET /{env_id}/asset-health-scores` | Current health score per table asset |
| Aggregate health score | `GET /{env_id}/asset-health-scores/aggregate` | One health score for a filtered set of tables |

Every list endpoint supports a full scan and keyset pagination. Assets,
columns, and tests also expose incremental feeds — see
[Incremental sync](/api/incremental-sync). Latest test executions and asset
health scores are full snapshots; per-test history is a time window.

## Assets: one base endpoint, plus typed endpoints

Elementary tracks assets of several kinds — warehouse tables and views, BI
dashboards and explores, semantic models, and more. They share a common set of
fields but each kind also has its own attributes, so the API splits them:

* **`GET /assets`** returns **every** asset of every kind with the **common
  fields** (`id`, `name`, `source_type`, `tags`, `owners`, timestamps, …) plus a
  `kind` discriminator. This is the complete list of lineage nodes: every asset
  id referenced by asset lineage or column lineage appears here, so you can
  resolve any edge endpoint to a node.
* **`GET /assets/tables`** and **`GET /assets/bi`** return the same assets
  narrowed to a single kind, with that kind's extra fields fully populated —
  warehouse coordinates (`db_name`, `schema_name`, `table_name`,
  `materialization`) for tables, and `bi_platform` / `bi_type` / `url` for BI
  assets. Kind-specific filters live here too (e.g. `db_names` on
  `/assets/tables`, `bi_platforms` on `/assets/bi`).
* All three accept a **`path`** filter to select a folder: it matches assets
  whose `path` equals the value or is nested under it (`models/marts` matches
  `models/marts/orders.sql` but not `models/marts_legacy/orders.sql`). A
  trailing `/` is ignored; repeat the parameter to combine folders.

**Why the split?** A single asset shape would leave most fields null on any given
row (a BI dashboard has no `db_name`; a table has no `bi_platform`). Keeping the
common fields on `/assets` gives you a clean node list for building the lineage
graph, while the typed endpoints give each kind a tight, fully-populated shape.
A typical flow: page `/assets` to build the graph, then enrich the kinds you
care about via the typed endpoints — use the `kind` field to decide which one.

The full endpoint and schema reference is generated from the API and lives under
**API Reference**.

## Tests

Three datasets, one table each — definitions, current status, and per-test
history are not merged into a single response:

* **[`GET /tests`](/api/reference/tests/list-tests)** — the test definition
  (name, type, asset, severity, config, owners/tags). Incremental
  `synced_since` / `deleted_since`. A new run does not bump `Test.synced_at`.
* **[`GET /latest-test-executions`](/api/reference/latest-test-executions/list-latest-test-executions)** —
  the current run per sub-test. Full snapshot; no incremental feed.
  Join to tests on `test_id`.
* **[`GET /tests/{test_id}/executions`](/api/reference/test-executions/list-test-executions)** —
  history for one test (default last 30 days). Not an environment-wide dump.

Table / relation name is a join to [table assets](/api/reference/assets/list-table-assets)
on `asset_id`, not a field on the test. Metric numbers behind a freshness/volume
verdict are not in this cut.

## Asset health scores

**[`GET /asset-health-scores`](/api/reference/asset-health-scores/list-asset-health-scores)**
returns the current data health score of every monitored table asset, the same number
shown in the Elementary data health dashboard when looking at a single asset.
Use it to feed scorecards or nightly quality reports.

Each item has a `total` score and one entry per quality `dimension`
(`completeness`, `uniqueness`, `freshness`, `validity`, `accuracy`,
`consistency`):

```json theme={null}
{
  "asset_id": "model.analytics.orders",
  "total": { "score": 0.91, "test_count": 12, "bucket_at": "2026-09-14T08:00:00" },
  "dimensions": [
    { "dimension": "freshness", "score": 0.99, "test_count": 3, "bucket_at": "2026-09-14T08:00:00" }
  ]
}
```

* Scores are in the range `0`–`1`. `total` is the weighted combination of the
  dimensions using the environment's configured weights.
* Scores are computed from test results in the **last 7 days**, in hourly
  buckets; `bucket_at` is the start of the most recent bucket with results.
  Dimensions with no results in that window are omitted, and assets with no
  results at all are not returned.
* Only [table assets](/api/reference/assets/list-table-assets) have health
  scores. `GET /asset-health-scores/{asset_id}` returns `404` for a BI asset or
  an id that is not a synced table.
* Full snapshot, replaced in place — re-read it; there is no incremental feed.
  The only filter is `asset_ids`. Join to
  [assets](/api/reference/assets/list-assets) on `asset_id`.
* `dimension` is an extensible enum (see below).

### Aggregate health score for a set of assets

**[`GET /asset-health-scores/aggregate`](/api/reference/asset-health-scores/aggregate-asset-health-scores)**
returns a single health score for a group of table assets — for example a dbt
folder, a schema, or everything with a tag — the same number the Elementary
data health dashboard shows when you filter it to that group. It is computed
over the matching assets' test results together, **not** as an average of
their per-asset scores.

```bash theme={null}
curl -G "https://prod.api.elementary-data.com/public/beta/$ENV_ID/asset-health-scores/aggregate" \
  -H "Authorization: Bearer $ELEMENTARY_TOKEN" \
  --data-urlencode "path=models/marts" \
  --data-urlencode "tags=finance"
```

```json theme={null}
{
  "matched_count": 40,
  "total": { "score": 0.91, "test_count": 12, "bucket_at": "2026-09-14T08:00:00" },
  "dimensions": [
    { "dimension": "freshness", "score": 0.99, "test_count": 3, "bucket_at": "2026-09-14T08:00:00" }
  ]
}
```

* `matched_count` is the number of table assets you can view that match the
  filters, including those with no test results in the window.
* Filters select [table assets](/api/reference/assets/list-table-assets). The
  supported filters are `ids`, `source_types`, `tags`, `db_names`,
  `schema_names`, `materializations`, and `path`. Values within one parameter
  are OR-ed; different parameters are AND-ed. With no filters, the call covers
  every table asset in the environment that you can view.
* `total` and `dimensions` are computed only from matching tables that have test
  results in the window; tables without results count toward `matched_count`
  but not toward the score.
* Every `ids` value must be a table asset; if any is a BI asset or unknown, the
  request fails with `400` and the error message lists the invalid ids.
* `path` selects a folder: it matches assets whose `path` equals the value or is
  nested under it (`models/marts` matches `models/marts/orders.sql` but not
  `models/marts_legacy/orders.sql`). A trailing `/` is ignored, and `.sql` is
  not stripped. Repeat it to combine folders. The same
  `path` filter is also available on `GET /assets`, `/assets/tables`, and
  `/assets/bi`.
* Same scoring as above: scores are in the range `0`–`1`, computed from test
  results in a fixed **last 7 days** window, and dimensions with no results are
  omitted.
* If no matching asset has test results in the window, the response is still
  `200` with a zero score and the `matched_count` (`0` for an empty folder):
  `{"matched_count": 0, "total": {"score": 0, "test_count": 0, "bucket_at": null}, "dimensions": []}`.

## Forward compatibility

Some string fields are **extensible enums**: they carry a value from a small,
known set today (e.g. `kind`, `source_type`, `data_platform`, `materialization`,
`bi_platform`, `bi_type`, `warehouse_type`, `last_sync_status`, `test_type`,
`definition_type`, `status`, `dimension`), but that set
grows as Elementary adds integrations and asset types. In the schema these
fields are typed as plain strings with an `Extensible enum.` note and their
currently-known values listed under `examples` — they are **not** a closed
enum.

To stay compatible as the API evolves, build your integration so that:

* **Unknown values never break you.** Treat any value you don't recognize as a
  safe fallback (for `kind`, use `other`) rather than failing. New values can
  appear in a normal, non-breaking release.
* **New fields are ignored, not rejected.** We may add fields to a response;
  don't configure your parser to reject unknown properties.
* **You iterate on `has_more`, not item counts** (see [Pagination](/api/pagination)).

Our side of the contract: we add enum values and fields additively without a
version bump, and never silently change the meaning of an existing value.
**Removing or renaming** a field or a known value is a breaking change and would
ship under a new API version, not under `beta`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.