API reference

API reference: Metadata & Lineage

This page documents the Metadata service (openapi-metadata.yaml, port 8081) and the Lineage service (openapi-lineage.yaml, port 8084). Both serve under /api/v1 and require a bearerAuth JWT. Pipeline CRUD also lives in the metadata service — see the Pipeline Engine reference page.


Connections

Connections register external systems. Stored credentials are vault-referenced; the API never returns a plaintext password.

MethodPathOperation IDPurposeAuth
GET/api/v1/connectionslistConnectionsList connectionsJWT
POST/api/v1/connectionscreateConnectionRegister a connectionJWT
GET/api/v1/connections/{id}getConnectionGet connection (no plaintext password)JWT
PUT/api/v1/connections/{id}updateConnectionUpdate connectionJWT
DELETE/api/v1/connections/{id}deleteConnectionDelete connection (fails if referenced)JWT
POST/api/v1/connections/{id}/testtestConnectionTest connectivity with stored credentialsJWT

listConnections accepts workspaceId (query, uuid). Connection.type enum: TERADATA, SNOWFLAKE, DATABRICKS, SAP_HANA, MSSQL, ORACLE, POSTGRESQL, MYSQL, KAFKA, GCS, AZURE_BLOB. testStatus: UNKNOWN | SUCCESS | FAILED. ConnectionCreate accepts encryptedPassword (vault-referenced). ConnectionTestResult fields: success, latencyMs, message, serverVersion, testedAt.

// POST /api/v1/connections  →  201 Created
// Request: ConnectionCreate
{
  "name": "teradata-prod",
  "type": "TERADATA",
  "host": "teradata.polkomtel.pl",
  "port": 1025,
  "database": "DWH",
  "username": "dataflow_svc",
  "encryptedPassword": "vault://connections/teradata-prod"
}
// POST /api/v1/connections/{id}/test  →  200 OK  (ConnectionTestResult)
{
  "success": true,
  "latencyMs": 42,
  "message": "Connection established",
  "serverVersion": "Teradata 17.20",
  "testedAt": "2025-12-15T14:30:00Z"
}

Quality

Quality rules define data-quality checks against a pipeline; results record each check execution.

MethodPathOperation IDPurposeAuth
GET/api/v1/quality/ruleslistQualityRulesList quality rulesJWT
POST/api/v1/quality/rulescreateQualityRuleCreate a quality ruleJWT
GET/api/v1/quality/rules/{id}getQualityRuleGet a quality ruleJWT
DELETE/api/v1/quality/rules/{id}deleteQualityRuleDelete a quality ruleJWT
GET/api/v1/quality/resultslistQualityResultsList check resultsJWT

listQualityRules accepts pipelineId (query, uuid). listQualityResults accepts pipelineId, ruleId (uuid), and limit (default 50). QualityRule.type enum: ROW_COUNT, NOT_NULL, UNIQUE, REFERENTIAL, CUSTOM_SQL, FRESHNESS, SCHEMA_MATCH, VALUE_RANGE, REGEX_MATCH, ACCEPTED_VALUES. severity: WARNING | ERROR | CRITICAL. onFailure: FAIL | WARN | SKIP_TARGET | QUARANTINE.

// POST /api/v1/quality/rules  →  201 Created
// Request: QualityRuleCreate
{
  "pipelineId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "name": "customer-id-not-null",
  "type": "NOT_NULL",
  "column": "CUSTOMER_ID",
  "severity": "ERROR",
  "onFailure": "QUARANTINE"
}
// GET /api/v1/quality/results?pipelineId=...&limit=50  →  200 OK
[
  {
    "id": "qr-0001",
    "ruleId": "rule-0001",
    "pipelineId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "passed": false,
    "failedRows": 17,
    "severity": "ERROR",
    "checkedAt": "2025-12-15T02:14:00Z"
  }
]

Catalog

The data catalog browses datasets discovered through connections.

MethodPathOperation IDPurposeAuth
GET/api/v1/catalog/datasetslistCatalogDatasetsBrowse the data catalogJWT
PUT/api/v1/catalog/datasets/{id}/tagsupdateDatasetTagsReplace a dataset's tag setJWT

listCatalogDatasets accepts search, connectionId (uuid), and tag. CatalogDataset.type: TABLE | VIEW | MATERIALIZED_VIEW | EXTERNAL. Each dataset includes columns[] (CatalogColumnname, dataType, nullable, isPrimaryKey, classification).

// PUT /api/v1/catalog/datasets/{id}/tags  →  200 OK
// Request: { "tags": ["billing", "pii", "gold"] }
{
  "id": "ds-0001",
  "name": "DWH.CUSTOMERS",
  "type": "TABLE",
  "tags": ["billing", "pii", "gold"],
  "columns": [
    { "name": "CUSTOMER_ID", "dataType": "BIGINT", "nullable": false, "isPrimaryKey": true, "classification": "INTERNAL" }
  ]
}

Governance

Governance manages data classifications and a queryable audit log.

MethodPathOperation IDPurposeAuth
GET/api/v1/governance/classificationslistClassificationsList data classificationsJWT
POST/api/v1/governance/classificationscreateClassificationCreate a classificationJWT
GET/api/v1/governance/audit-loggetAuditLogQuery the audit logJWT

getAuditLog accepts category, userId (uuid), from/to (date-time), and limit (default 100). DataClassification.level: PUBLIC | INTERNAL | CONFIDENTIAL | RESTRICTED. AuditLogEntry.category: PIPELINE | CONNECTION | USER | WORKSPACE | SECURITY | SYSTEM.

// POST /api/v1/governance/classifications  →  201 Created
// Request: DataClassificationCreate
{
  "name": "Subscriber PII",
  "level": "RESTRICTED",
  "description": "Personal data of Polkomtel subscribers"
}

GDPR

GDPR endpoints handle Data Subject Access Requests (DSARs, 30-day SLA), consent records, and Article 30 data mapping.

MethodPathOperation IDPurposeAuth
POST/api/v1/gdpr/dsarsubmitDsarSubmit a DSAR (30-day SLA)JWT
GET/api/v1/gdpr/dsarlistDsarsList DSARs (admin, paginated)JWT
GET/api/v1/gdpr/dsar/{id}getDsarGet DSAR status by tracking IDJWT
POST/api/v1/gdpr/dsar/{id}/startstartDsarTransition DSAR SUBMITTEDIN_PROGRESSJWT
POST/api/v1/gdpr/dsar/{id}/completecompleteDsarComplete a DSAR with a reportJWT
GET/api/v1/gdpr/dsar/remindersgetDsarRemindersDSARs past 20 days needing a reminderJWT
GET/api/v1/gdpr/dsar/overduegetOverdueDsarsDSARs past the 30-day SLAJWT
GET/api/v1/gdpr/data-mapgetDataMapGDPR Article 30 data mapping reportJWT
POST/api/v1/gdpr/consent/{subjectId}recordConsentRecord consent (Article 7)JWT
GET/api/v1/gdpr/consent/{subjectId}getConsentGet consent statusJWT
DELETE/api/v1/gdpr/consent/{subjectId}withdrawConsentWithdraw all active consentJWT
GET/api/v1/gdpr/auditgetGdprAuditTrailGDPR-specific audit trailJWT

listDsars accepts status, requestType, page (default 0), size (default 20). getDataMap accepts workspaceId (uuid). DsarRequest.requestType: ACCESS | ERASURE | RECTIFICATION; status: SUBMITTED | IN_PROGRESS | COMPLETED | REJECTED. DataMapReport includes totalColumnsScanned, piiColumnsFound, rodoRelevantColumnsFound, entries[], and classification/sensitivity breakdowns.

// POST /api/v1/gdpr/dsar  →  201 Created
// Request: DsarSubmitRequest
{
  "subjectId": "5d6e7f80-1111-2222-3333-444455556666",
  "requestType": "ERASURE",
  "subjectEmail": "subscriber@example.pl",
  "details": "Right to be forgotten request"
}
// Response: DsarSubmitResponse
{
  "trackingId": "dsar-2025-001847",
  "status": "SUBMITTED",
  "slaDueAt": "2026-01-14T14:30:00Z"
}
// GET /api/v1/gdpr/data-map?workspaceId=...  →  200 OK  (DataMapReport)
{
  "totalColumnsScanned": 4821,
  "piiColumnsFound": 312,
  "rodoRelevantColumnsFound": 287,
  "entries": [
    { "dataset": "DWH.CUSTOMERS", "column": "PESEL", "classification": "RESTRICTED", "sensitivity": "HIGH" }
  ]
}

Heads up

DSARs carry a statutory 30-day SLA. getDsarReminders surfaces requests past 20 days, and getOverdueDsars surfaces breached requests. Wire both into a scheduled job so compliance staff are alerted before the deadline.


Admin — Users

MethodPathOperation IDPurposeAuth
POST/api/v1/admin/userscreateUserCreate a user + assign to a workspaceJWT
GET/api/v1/admin/userslistUsersList users (paginated)JWT
GET/api/v1/admin/users/{id}getUserGet user incl. workspaces/preferencesJWT
PUT/api/v1/admin/users/{id}updateUserUpdate user (name, role, AD groups)JWT
DELETE/api/v1/admin/users/{id}deleteUserDeactivate user (data retained)JWT
POST/api/v1/admin/users/{id}/reactivatereactivateUserReactivate a deactivated userJWT
GET/api/v1/admin/users/{id}/workspacesgetUserWorkspacesList the user's workspace membershipsJWT
GET/api/v1/admin/users/{id}/activitygetUserActivityUser audit logJWT
POST/api/v1/admin/users/bulk-invitebulkInviteUsersBulk invite users by emailJWT

listUsers accepts workspace (uuid), role, search, active (bool), page (default 0), size (default 20). getUserActivity accepts since (date-time). The role enum, used everywhere, is ADMIN | ENGINEER | ANALYST | VIEWER. createUser returns 409 on a duplicate user.

// POST /api/v1/admin/users  →  201 Created
// Request: CreateUserRequest
{
  "email": "anna.kowalska@polkomtel.pl",
  "displayName": "Anna Kowalska",
  "role": "ENGINEER",
  "workspaceId": "9c1f0e2a-1111-2222-3333-444455556666"
}
// GET /api/v1/admin/users?page=0&size=20  →  200 OK  (UserListResponse)
{
  "items": [
    { "id": "u-1001", "email": "anna.kowalska@polkomtel.pl", "role": "ENGINEER", "active": true }
  ],
  "total": 134,
  "page": 0,
  "size": 20
}

Admin — Workspaces

MethodPathOperation IDPurposeAuth
POST/api/v1/admin/workspacescreateWorkspaceCreate a workspaceJWT
GET/api/v1/admin/workspaceslistWorkspacesList all workspacesJWT
GET/api/v1/admin/workspaces/{id}getWorkspaceGet workspace detailsJWT
PUT/api/v1/admin/workspaces/{id}updateWorkspaceUpdate a workspaceJWT
DELETE/api/v1/admin/workspaces/{id}deleteWorkspaceDelete workspace, disassociate membersJWT
GET/api/v1/admin/workspaces/{id}/membersgetWorkspaceMembersList membersJWT
POST/api/v1/admin/workspaces/{id}/membersaddWorkspaceMemberAdd a member with a roleJWT
PUT/api/v1/admin/workspaces/{id}/members/{userId}updateWorkspaceMemberRoleChange a member's roleJWT
DELETE/api/v1/admin/workspaces/{id}/members/{userId}removeWorkspaceMemberRemove a memberJWT
GET/api/v1/admin/workspaces/{id}/statsgetWorkspaceStatsResource statisticsJWT
// POST /api/v1/admin/workspaces/{id}/members  →  201 Created
// Request: AddMemberRequest
{
  "userId": "u-1001",
  "role": "ANALYST"
}

Admin — Audit log

MethodPathOperation IDPurposeAuth
GET/api/v1/admin/auditqueryAdminAuditLogQuery the admin audit log (paginated)JWT
GET/api/v1/admin/audit/statsgetAdminAuditStatsAggregate audit statisticsJWT
GET/api/v1/admin/audit/exportexportAdminAuditLogExport the audit logJWT

queryAdminAuditLog accepts userId, workspaceId (uuid), action, resourceType, since/until (date-time), page (0), size (20). getAdminAuditStats accepts workspaceId (uuid) and days (default 30). exportAdminAuditLog accepts the same filters plus format (json | csv, default json) and returns a string body of type application/json or text/csv.

// GET /api/v1/admin/audit?page=0&size=20  →  200 OK  (AuditLogResponse)
{
  "items": [
    { "action": "PIPELINE_UPDATE", "resourceType": "PIPELINE", "userId": "u-1001", "at": "2025-12-15T14:30:00Z" }
  ],
  "total": 982,
  "page": 0,
  "size": 20
}

Admin — System settings

MethodPathOperation IDPurposeAuth
GET/api/v1/admin/settingsgetSystemSettingsGet all settings (key-value)JWT
PUT/api/v1/admin/settingsupdateSystemSettingsBulk update settingsJWT
GET/api/v1/admin/settings/{key}getSystemSettingGet a single settingJWT
PUT/api/v1/admin/settings/{key}setSystemSettingSet a single settingJWT
// PUT /api/v1/admin/settings/{key}  →  200 OK
// Request: SetSettingRequest
{ "value": "30" }

Lineage Service

The Lineage service tracks dataset and column lineage, impact analysis, and ingests OpenLineage events. Dataset IDs use the namespace.name format — for example teradata.DWH.CUSTOMERS.

Lineage graph

MethodPathOperation IDPurposeAuth
GET/api/v1/lineage/datasets/{id}getDatasetLineageDataset lineage (up/downstream + jobs)JWT
GET/api/v1/lineage/graph/{datasetId}getFullLineageGraphComplete connected lineage graphJWT
GET/api/v1/lineage/columns/{id}getColumnLineageColumn lineage by FQ column IDJWT
GET/api/v1/lineage/columns/{datasetId}/{columnName}getColumnLineageForDatasetColumn lineage for a dataset columnJWT

getColumnLineage takes a fully qualified column ID such as ns.table.column.

// GET /api/v1/lineage/datasets/teradata.DWH.CUSTOMERS  →  200 OK  (LineageGraph)
{
  "datasetId": "teradata.DWH.CUSTOMERS",
  "upstream": ["teradata.STG.CUSTOMERS_RAW"],
  "downstream": ["snowflake.DWH.DIM_CUSTOMER"],
  "jobs": ["billing-daily-load"]
}

Traversal

MethodPathOperation IDPurposeAuth
GET/api/v1/lineage/upstream/{datasetId}getUpstreamLineageTrace upstream datasetsJWT
GET/api/v1/lineage/downstream/{datasetId}getDownstreamLineageTrace downstream datasetsJWT
GET/api/v1/lineage/subgraph/{datasetId}getSubgraphExtract a subgraph for visualizationJWT

getUpstreamLineage and getDownstreamLineage accept depth (default 5). getSubgraph accepts depth (default 3) and direction (UPSTREAM | DOWNSTREAM | BOTH, default BOTH).

// GET /api/v1/lineage/upstream/snowflake.DWH.DIM_CUSTOMER?depth=3  →  200 OK
[
  { "datasetId": "teradata.DWH.CUSTOMERS", "depth": 1 },
  { "datasetId": "teradata.STG.CUSTOMERS_RAW", "depth": 2 }
]

Analytics

MethodPathOperation IDPurposeAuth
GET/api/v1/lineage/impact/{id}getImpactAnalysisDownstream impact of dataset changesJWT
GET/api/v1/lineage/statsgetLineageStatsAggregate lineage graph statisticsJWT

ImpactAnalysis.riskLevel: LOW | MEDIUM | HIGH | CRITICAL; impactedDatasets[].impactType: DIRECT | INDIRECT. LineageStats fields: totalDatasets, totalEdges, totalJobs, totalColumnLinks, orphanDatasets, maxDepthUpstream, maxDepthDownstream, lineageBreaks.

// GET /api/v1/lineage/impact/teradata.DWH.CUSTOMERS  →  200 OK  (ImpactAnalysis)
{
  "datasetId": "teradata.DWH.CUSTOMERS",
  "riskLevel": "HIGH",
  "impactedDatasets": [
    { "datasetId": "snowflake.DWH.DIM_CUSTOMER", "impactType": "DIRECT" },
    { "datasetId": "snowflake.MART.CHURN_SCORE", "impactType": "INDIRECT" }
  ]
}
MethodPathOperation IDPurposeAuth
GET/api/v1/lineage/searchsearchLineageFull-text search of datasets or columnsJWT
GET/api/v1/lineage/hot-datasetsgetHotDatasetsMost-referenced datasetsJWT
GET/api/v1/lineage/pii/{datasetId}/{columnName}getPiiPropagationTrace PII column propagationJWT

searchLineage requires q and accepts type, connection, and entity (DATASET | COLUMN, default DATASET); it returns 400 when q is missing. getHotDatasets accepts limit (default 10).

// GET /api/v1/lineage/search?q=customer&entity=DATASET  →  200 OK
[
  { "datasetId": "teradata.DWH.CUSTOMERS", "name": "CUSTOMERS", "connection": "teradata-prod" }
]

OpenLineage events

MethodPathOperation IDPurposeAuth
GET/api/v1/lineage/eventsgetRecentEventsGet recent lineage eventsJWT
POST/api/v1/lineage/eventsrecordLineageEventIngest an OpenLineage run eventJWT
POST/api/v1/lineage/events/batchrecordBatchEventsBatch event ingestionJWT

getRecentEvents accepts limit (default 100). RunEvent.eventType: START | RUNNING | COMPLETE | ABORT | FAIL | OTHER; it carries run (RunFacet), job (JobFacet), and inputs[]/outputs[] (DatasetEvent with schema, dataSource, and columnLineage facets).

// POST /api/v1/lineage/events  →  201 Created
// Request: RunEvent (OpenLineage)
{
  "eventType": "COMPLETE",
  "eventTime": "2025-12-15T02:30:00Z",
  "run": { "runId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" },
  "job": { "namespace": "dataflow", "name": "billing-daily-load" },
  "inputs": [{ "namespace": "teradata", "name": "DWH.CUSTOMERS" }],
  "outputs": [{ "namespace": "snowflake", "name": "DWH.DIM_CUSTOMER" }]
}
// Response
{ "status": "RECORDED", "job": "billing-daily-load" }
// POST /api/v1/lineage/events/batch  →  201 Created
{ "status": "ACCEPTED", "accepted": 48, "total": 50 }
Previous
Pipeline Engine API