Skip to main content
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).
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.

Base URL

Quickstart

1

Get a token

Create a personal or account token in Elementary and send it as a bearer token. See Authentication.
2

Discover your environments

Each returned id is an env_id you use in every other endpoint.
3

List assets

Follow next_cursor until has_more is false — see Pagination.

What you can read

Every list endpoint supports a full scan and keyset pagination. Assets, columns, and tests also expose incremental feeds — see 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 — 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 — the current run per sub-test. Full snapshot; no incremental feed. Join to tests on test_id.
  • GET /tests/{test_id}/executions — history for one test (default last 30 days). Not an environment-wide dump.
Table / relation name is a join to 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 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):
  • 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 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 on asset_id.
  • dimension is an extensible enum (see below).

Aggregate health score for a set of assets

GET /asset-health-scores/aggregate 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.
  • 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. 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).
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.