Every Endpoint of the CoreModels Databricks Integration, With Real Payloads
Reference articles usually show the happy path and gesture at the rest. This one is the full inventory: every HTTP route the CoreModels Databricks Unity Catalog connector answers on, the role each one enforces, the request and response bodies as they actually are, and — where a verb lives on one surface but not the other — an explicit statement of that fact rather than a diagram that implies otherwise.
Every Endpoint of the CoreModels Databricks Integration, With Real Payloads
Reference articles usually show the happy path and gesture at the rest. This one is the full inventory: every HTTP route the CoreModels Databricks Unity Catalog connector answers on, the role each one enforces, the request and response bodies as they actually are, and — where a verb lives on one surface but not the other — an explicit statement of that fact rather than a diagram that implies otherwise.
There are two surfaces by design. The interactive surface under graph/integrations/...
authenticates with your normal CoreModels login token and carries every verb. The
machine-to-machine surface under /v1/... accepts CoreModels user API keys — the kind you
put in CI secrets — and deliberately carries only audit and badge. Base URL is written as
https://coremodels.example.com; the vendor key is databricks; {projectId} is the
32-character hex id of the governing project.
Any JSON route with an unrecognized vendor key answers success: false with
Unknown vendor '<key>'. Registered: <comma-joined keys>. — useful, because the registered
list doubles as discovery when you can't remember a key. (The badge routes, which must return
an image, render a gray unknown vendor badge instead.)
Discovery — GET graph/integrations/vendors (any authenticated user)
GET https://coremodels.example.com/graph/integrations/vendors
Authorization: Bearer $TOKEN
Lists every registered connector. The Databricks entry:
{ "key": "databricks", "displayName": "Databricks Unity Catalog",
"capabilities": "Import, Audit, Generate",
"artifacts": {
"information_schema": "required — JSON rows of system.information_schema COLUMNS × TABLES (documented query)",
"keys": "optional — flattened PK/FK constraint rows (documented query)",
"lineage": "optional — system.access.table_lineage rows; becomes Depends-On lineage"
} }
All three capabilities are real for this connector, so every section below has substance — including Generate. (Some connectors are Import + Audit only and ship no generator; Databricks is not one of them.)
Import — POST graph/integrations/databricks/import/{projectId} — Admin
The one verb that writes governed meaning, and it writes additively: existing governed nodes are never mutated or deleted; re-imports skip what is already governed and only vendor bookkeeping is refreshed. The body maps artifact names to raw contents — each value is the JSON text of one extract:
POST https://coremodels.example.com/graph/integrations/databricks/import/{projectId}
Authorization: Bearer $TOKEN
Content-Type: application/json
{ "artifacts": { "information_schema": "<information_schema.json contents>",
"keys": "<keys.json contents>",
"lineage": "<lineage.json contents>" },
"spaces": [] }
spaces is optional; empty means the project's main space. Omitting artifacts entirely
earns the exact error Body must include 'artifacts': { "<name>": "<content>" } (e.g. manifest for dbt). — the example names dbt because the message is shared across all
connectors. The response reports counts (datasetsAdded, datasetsSkippedExisting, fieldsAdded,
lineageEdgesAdded, lineageEdgesSkipped, nodesEnriched), a snapshotStored flag (the
parsed estate snapshot that powers re-audit), plus lossiness and errors arrays. Lossiness
is a success channel: the import proceeded, and this is what it approximated or dropped.
Audit — POST graph/integrations/databricks/audit/{projectId} — Viewer
Read-only, always. recordHistory (default false) is the one piece of opt-in bookkeeping:
set it to record this run in the rolling audit trail.
POST https://coremodels.example.com/graph/integrations/databricks/audit/{projectId}
Authorization: Bearer $TOKEN
Content-Type: application/json
{ "artifacts": { "information_schema": "<information_schema.json contents>" },
"recordHistory": true }
The response is the full audit report:
{
"success": true,
"vendor": "databricks", "projectName": "main",
"errorCount": 0, // the CI-gate signal: > 0 means governed meaning was violated
"warningCount": 2, "infoCount": 3,
"codes": { "key-column-undeclared": 2, "table-no-comment": 3 },
"driftedObjects": [], // vendor identities of drifted objects
"fingerprint": "9f2c4a1b0e77d3aa", // content hash of the artifacts
"metrics": { "Datasets (estate)": "18",
"Datasets governed": "18 / 18",
"Fields governed": "150 / 150",
"Governed nodes with canonical mappings": "0 / 168 (0%)",
"Last import": "2026-08-02T14:21:07.3310000+00:00" },
"findings": [ { "section": "Conformance", "severity": "Warning",
"code": "key-column-undeclared", "subject": "main.sales.orders.customer_id",
"message": "…", "detail": null } ],
"markdown": "…the PR-comment-ready report…",
"historyRecorded": true,
"lossiness": []
}
Sections are Coverage, Drift, and Conformance; severities are Error, Warning,
Info. The Databricks-specific conformance codes are table-no-comment (Info) and
key-column-undeclared (Warning); the coverage and drift codes are shared across all
connectors.
metrics is the headline summary the Markdown report renders as a table: how many datasets
the extract contained, how many of them resolve to governed Types, the same ratio for fields,
and the canonical-mapping coverage — how many vendor-governed nodes also carry a mapping to a
non-vendor standard, which is the number to watch if you are grounding agents or exporting to
another format. Last import appears once an import has been recorded.
Re-audit — POST graph/integrations/databricks/reaudit/{projectId} — Viewer
The audit above asks "do these fresh artifacts still conform to the governed model?" The re-audit asks the reverse: "the governed model changed — does the last-known estate still conform?" It needs no artifacts because it runs against the snapshot stored at import time:
POST https://coremodels.example.com/graph/integrations/databricks/reaudit/{projectId}
Authorization: Bearer $TOKEN
Content-Type: application/json
{}
The body optionally takes projectName (the vendor-side project to re-audit; null means the
latest stored snapshot), spaces, and notifySlack (default false), which posts the run to
the project's configured Slack channel when it carries errors or warnings. The response has
the same report shape as audit, with
one behavioral difference: a re-audit run is always recorded in the history — there is no
recordHistory flag to forget. If the import ever reported snapshotStored: false (the
snapshot exceeded the storage cap of roughly 1.5 MB), there is nothing stored to re-audit
against, and fresh-artifact audits are the fallback.
History — GET graph/integrations/databricks/history/{projectId} — Viewer
GET https://coremodels.example.com/graph/integrations/databricks/history/{projectId}
Authorization: Bearer $TOKEN
Returns the rolling audit trail, newest first, grouped by vendor-side project:
{ "success": true, "vendor": "databricks",
"projects": [ { "projectName": "main",
"runs": [ { "at": "2026-08-03T09:12:44.6183920+00:00", "trigger": "ci",
"errorCount": 0, "warningCount": 2, "infoCount": 3,
"codes": { "key-column-undeclared": 2, "table-no-comment": 3 },
"fingerprint": "9f2c4a1b0e77d3aa" } ] } ] }
trigger records how the run happened, and the values are lowercase: audit (an interactive
audit called with recordHistory), ci (the machine-to-machine audit), reaudit, and
scheduled (the server-side heartbeat, where a deployment enables it). Run records are
deliberately compact — counts, per-code totals, fingerprint — because the trail answers "is
this estate drifting over time?" while a live audit answers "what exactly is wrong now?"
Badge — GET graph/integrations/databricks/badge/{projectId} — Viewer
Returns image/svg+xml: a self-contained shields-style badge labeled databricks audit,
rendered from the latest recorded run. Green (#4c1) means clean, yellow (#dfb317) means
warnings only, red (#e05d44) means errors, gray (#9f9f9f) means no recorded runs.
Generate — POST graph/integrations/databricks/generate/{projectId} — Viewer
Read-only in the graph sense: it reads governed meaning and emits vendor artifacts for you to review and apply.
POST https://coremodels.example.com/graph/integrations/databricks/generate/{projectId}
Authorization: Bearer $TOKEN
Content-Type: application/json
{ "typeNames": [] }
typeNames restricts generation to named types; empty means everything eligible. (The body
also accepts targetVersion and extra for connectors with dialect choices; the Databricks
generator currently has a single dialect, so typeNames is the option that matters.) The
response:
{ "success": true,
"artifacts": [ { "name": "coremodels_delta_tables.sql", "kind": "sql",
"content": "-- Generated by CoreModels — governed Delta table definitions.\n…" } ],
"lossiness": [ { "kind": "StructuralDrop", "path": "orders_view",
"explanation": "Views are derived objects; DDL generation covers tables only." } ],
"errors": [] }
One artifact comes back: CREATE TABLE IF NOT EXISTS … USING DELTA statements with
NOT NULL from governed checks, one informational PRIMARY KEY constraint per table,
FOREIGN KEY … REFERENCES from governed references, and taxonomy allowed values carried on
column COMMENTs. Views are skipped with declared lossiness, as the sample shows. If nothing
is eligible, generation fails honestly with No eligible tables found to generate DDL for.
Status — GET graph/integrations/databricks/status/{projectId} — Viewer
GET https://coremodels.example.com/graph/integrations/databricks/status/{projectId}
Authorization: Bearer $TOKEN
Answers "has this project imported a Databricks estate, and what does it look like now?":
imported (boolean), state (the last-import bookkeeping), and governedDatasets — how many
Unity Catalog identities currently resolve to governed Types.
The state record for this connector carries the vendor key, the vendor-side project name
(your catalog), importedAt as an ISO-8601 timestamp, a compact counts string
(fieldsAdded=…, lineageAdded=…, lineageSkipped=…, nodesEnriched=…), the artifact
fingerprint, and the parser's facts — for Databricks, the table and view totals. The
tool-version and artifact-version slots stay empty here by nature: a Unity Catalog SQL extract
carries no generating tool version, unlike, say, a build manifest that stamps one.
Reconcile — POST graph/integrations/reconcile/{projectId} — Admin
Not vendor-scoped in the route, but part of the surface you will reach for once a lakehouse is
governed from two sides — the Unity Catalog metadata on one, whatever transformation tool
materializes into it on the other. It finds datasets that two imported estates describe as the
same physical relation, matched on database.schema.table, and links each pair with reciprocal
sameAs mappings:
POST https://coremodels.example.com/graph/integrations/reconcile/{projectId}
Authorization: Bearer $TOKEN
Content-Type: application/json
{ "vendorA": "databricks", "vendorB": "dbt" }
The response reports linksWritten, the matched pairs (both vendor ids, the physical name,
the count of matched fields), and unmatchedA / unmatchedB so you can see what did not line
up. It is idempotent — re-running after the next import refreshes the links rather than
duplicating them.
Sync plans — POST graph/integrations/databricks/sync/propose/{projectId} — Viewer
The newest part of the surface. Propose takes the same artifacts body as audit and
classifies the fresh extract three-way — against the estate snapshot stored at import and the
per-node governed sync bases — into a reviewable, replayable plan, returned inline. It is
read-only against governed meaning; its only writes are bookkeeping (the stored plan plus a
ledger entry, superseding earlier proposals). Two Viewer reads complete it:
GET graph/integrations/sync/plan/{projectId}/{planId} fetches a stored plan, and
GET graph/integrations/sync/ledger/{projectId} (optionally ?vendor=databricks) lists the
compact plan history per vendor-side project, newest first.
The machine-to-machine surface (/v1)
Two routes, both Viewer role, both taking user API keys — everything CI needs and nothing it doesn't:
POST https://coremodels.example.com/v1/{projectId}/integrations/databricks/audit
Authorization: Bearer $TOKEN
Content-Type: application/json
{ "artifacts": { "information_schema": "<information_schema.json contents>" },
"recordHistory": true }
Same request body as the interactive audit; the response is wrapped in the standard
ApiResponse envelope, so the report fields live under data — the CI gate reads
data.errorCount, and data.markdown is the report for your job summary. Runs recorded from
this surface carry trigger ci. The second route is the same badge as above:
GET https://coremodels.example.com/v1/{projectId}/integrations/databricks/badge
Authorization: Bearer $TOKEN
And the honest boundary: reaudit, history, import, generate, status, reconcile,
and the sync-plan routes live on the interactive surface only. If your automation needs re-audit on a schedule, that is what the
server-side scheduled re-audit (a deployment configuration, off by default) is for — it runs
against stored snapshots and records into the same history the routes above read.
Role summary
| Route | Role |
|---|---|
GET graph/integrations/vendors | any authenticated |
POST …/databricks/import/{projectId} | Admin |
POST …/databricks/audit/{projectId} | Viewer |
POST …/databricks/reaudit/{projectId} | Viewer |
GET …/databricks/history/{projectId} | Viewer |
GET …/databricks/badge/{projectId} | Viewer |
POST …/databricks/generate/{projectId} | Viewer |
GET …/databricks/status/{projectId} | Viewer |
POST graph/integrations/reconcile/{projectId} | Admin |
POST …/databricks/sync/propose/{projectId} | Viewer |
GET graph/integrations/sync/plan/{projectId}/{planId} | Viewer |
GET graph/integrations/sync/ledger/{projectId} | Viewer |
POST v1/{projectId}/integrations/databricks/audit | Viewer (API key) |
GET v1/{projectId}/integrations/databricks/badge | Viewer (API key) |
Import and reconcile are the only verbs that need Admin, because they are the only two that write governed meaning to the graph. Everything else — including generate, which writes files for you rather than nodes for the graph — runs at Viewer.
For worked end-to-end examples of these calls, see the Databricks quickstart in the CoreModels documentation.