API Reference¶
havn exposes a REST API via FastAPI at http://localhost:3000. All endpoints are prefixed with /api/. When authentication is enabled (havn serve --auth), include an Authorization: Bearer <token> header.
Authentication¶
POST /api/auth/login¶
Authenticate and receive a token.
{"username": "admin", "password": "your-password"}
Returns: {"token": "...", "username": "admin"}
GET /api/auth/me¶
Get the current authenticated user. Returns username, role, and display name.
GET /api/auth/status¶
Check if auth is enabled and whether initial setup is needed.
Returns: {"auth_enabled": true, "needs_setup": false}
POST /api/auth/setup¶
Create the first admin user. Only works when no users exist.
{"username": "admin", "password": "password", "role": "admin"}
User Management¶
Requires admin role.
GET /api/users¶
List all users (no passwords returned).
POST /api/users¶
Create a new user.
{"username": "analyst", "password": "pass", "role": "viewer", "display_name": "Data Analyst"}
PUT /api/users/{username}¶
Update user role, password, or display name.
{"role": "editor", "display_name": "Senior Analyst"}
DELETE /api/users/{username}¶
Delete a user and revoke all their tokens.
Secrets¶
Requires admin role.
GET /api/secrets¶
List secrets (keys and masked values).
POST /api/secrets¶
Set or update a secret.
{"key": "DB_PASSWORD", "value": "new_value"}
DELETE /api/secrets/{key}¶
Delete a secret from .env.
Files¶
GET /api/files¶
List project files as a tree structure.
GET /api/files/{path}¶
Read a file's content. Returns {path, content, language}.
PUT /api/files/{path}¶
Save or create a file. Allowed extensions: .sql, .py, .yml, .yaml, .dpnb, .sqlfluff.
{"content": "SELECT 1"}
DELETE /api/files/{path}¶
Delete a file. Optional ?drop_object=true to also drop the corresponding database object.
Query¶
POST /api/query¶
Execute an ad-hoc SQL query with a role-based timeout (admin 300s, editor 120s, viewer 60s by default).
{"sql": "SELECT * FROM gold.summary WHERE region = $region", "params": {"region": "US"}, "limit": 1000, "offset": 0}
params binds named $name placeholders as DuckDB prepared-statement values (no string interpolation, so values cannot inject SQL). Numbers and booleans are bound typed; strings can be cast in SQL ($day::DATE).
Returns: {columns, column_types, rows, truncated, offset, limit}
Also intercepts masking SQL commands: SHOW MASKING POLICIES, CREATE MASKING POLICY ON ..., DROP MASKING POLICY <id>.
POST /api/query/explain¶
Return the DuckDB EXPLAIN plan (structured + raw text). Accepts the same sql and params fields.
POST /api/query/export-csv¶
Stream full query results as a CSV download (no row limit). Accepts the same sql and params fields.
Tables¶
GET /api/tables¶
List warehouse tables and views. Optional ?schema=gold filter.
Returns: [{schema, name, type}]
GET /api/tables/{schema}/{table}¶
Describe a table's columns.
Returns: {schema, name, columns: [{name, type, nullable}]}
GET /api/tables/{schema}/{table}/sample¶
Get sample rows with pagination.
Query params: ?limit=100&offset=0
Returns: {schema, table, columns, rows, limit, offset}
GET /api/tables/{schema}/{table}/profile¶
Get column-level statistics: null counts, distinct counts, min/max, averages, sample values.
GET /api/autocomplete¶
Get table and column names for query editor autocomplete.
Models¶
GET /api/models¶
List all SQL transform models with metadata.
Returns: [{name, schema, full_name, materialized, depends_on, path, content_hash}]
POST /api/transform¶
Run the SQL transformation pipeline.
{"targets": null, "force": false}
POST /api/models/create¶
Create a new SQL model file.
{"name": "my_model", "schema_name": "silver", "materialized": "table", "sql": "SELECT 1"}
POST /api/check¶
Validate models, run assertions, and run contracts.
POST /api/diff¶
Compare SQL output against materialized tables.
{"targets": null, "target_schema": null, "full": false}
GET /api/models/{model_name}/notebook-view¶
Get a notebook-style view combining SQL source, sample data, lineage, and dependencies.
DAG¶
GET /api/dag¶
Get the model dependency DAG (nodes and edges).
GET /api/dag/full¶
Get the full DAG including seeds, sources, ingest scripts, and exposures.
Lineage¶
GET /api/lineage/{model_name}¶
Get column-level lineage for a model. Returns {model, columns, depends_on}.
GET /api/lineage¶
Get column-level lineage for all models.
GET /api/impact/{model_name}¶
Analyze downstream impact. Optional ?column=name for column-level analysis.
Pipeline¶
POST /api/run¶
Run an ingest or export script.
{"script_path": "ingest/customers.py"}
POST /api/stream/{stream_name}/start¶
Start a pipeline in a background thread. Returns immediately with
{"status": "started", "stream_name": "..."} or {"status": "already_running"}.
This is the preferred entry point; the legacy single-shot
POST /api/stream/{name} still works for short pipelines.
Optional query parameter: ?force=true.
GET /api/stream/events¶
Server-sent events for the currently running pipeline. Emits:
start, step_start, model_start, model_end, complete, error.
Events are pushed via a server-side threading.Condition, so listeners do
not poll. Heartbeat (: keepalive) every 15 seconds when idle.
GET /api/stream/active¶
Snapshot of the current pipeline state: { running, operation,
operation_label, stream_name, started_at, total_events, finished, status,
duration_seconds }. Stale runs older than 10 minutes are auto-cleared.
POST /api/stream/cancel¶
Request cancellation of the running pipeline. Workers check the cancel flag between steps; in-flight queries are not interrupted by default.
GET /api/streams¶
List configured streams with steps and schedules.
GET /api/history¶
Get run history. Optional ?limit=50.
GET /api/scheduler¶
Get scheduler status and scheduled streams.
Connectors¶
GET /api/connectors/available¶
List all available connector types with parameters.
GET /api/connectors¶
List connectors configured in the project.
POST /api/connectors/test¶
Test a connector without setup.
{"connector_type": "postgres", "config": {"host": "...", "database": "..."}}
POST /api/connectors/discover¶
Discover available resources for a connector.
{"connector_type": "postgres", "config": {"host": "..."}}
POST /api/connectors/setup¶
Full connector setup: test, generate script, update config.
{
"connector_type": "postgres",
"connection_name": "prod_db",
"config": {"host": "...", "database": "..."},
"tables": ["users", "orders"],
"target_schema": "landing",
"schedule": "0 6 * * *"
}
POST /api/connectors/regenerate/{connection_name}¶
Regenerate the ingest script for an existing connector.
POST /api/connectors/sync/{connection_name}¶
Run sync for a configured connector.
DELETE /api/connectors/{connection_name}¶
Remove a connector (script and config).
GET /api/connectors/health¶
Get last sync status for each connector.
POST /api/webhook/{webhook_name}¶
Receive webhook data and store in landing.<name>_inbox.
Authentication: requires a shared secret. Set
HAVN_WEBHOOK_SECRET_<NAME> (per-webhook) or HAVN_WEBHOOK_SECRET (global)
and pass it as the X-Havn-Webhook-Secret header. To run open for local
development set HAVN_WEBHOOK_OPEN=true. Payloads are capped at 5 MB.
CDC¶
GET /api/cdc¶
Get CDC state for all tracked connectors.
GET /api/cdc/{connector_name}¶
Get CDC state for a specific connector.
POST /api/cdc/{connector_name}/reset¶
Reset CDC watermarks for a connector.
Data Quality¶
GET /api/freshness¶
Check model freshness. Optional ?max_hours=24.
GET /api/profiles¶
Get profile stats for all models.
GET /api/profiles/{model_name}¶
Get profile stats for a specific model.
GET /api/assertions¶
Get recent assertion results. Optional ?limit=100.
GET /api/assertions/{model_name}¶
Get assertion results for a specific model.
GET /api/alerts¶
Get alert history. Optional ?limit=50.
POST /api/alerts/test¶
Send a test alert.
{"channel": "slack", "slack_webhook_url": "https://hooks.slack.com/..."}
GET /api/contracts¶
List all discovered contracts.
POST /api/contracts/run¶
Run all data contracts.
GET /api/contracts/history¶
Get contract evaluation history.
Masking¶
GET /api/masking/policies¶
List all masking policies.
POST /api/masking/policies¶
Create a new masking policy.
{
"schema_name": "gold",
"table_name": "customers",
"column_name": "email",
"method": "hash",
"exempted_roles": ["admin"]
}
GET /api/masking/policies/{policy_id}¶
Get a specific masking policy.
PUT /api/masking/policies/{policy_id}¶
Update a masking policy.
DELETE /api/masking/policies/{policy_id}¶
Delete a masking policy.
Backup¶
POST /api/backup¶
Create a verified backup with SHA-256 checksum. Optional body:
{"no_verify": false, "note": "before deploy", "keep": 10}
Returns: {path, size_bytes, sha256, timestamp}
GET /api/backups¶
List all tracked backups from the manifest.
POST /api/backup/verify¶
Verify a backup file's integrity against its stored checksum.
{"path": "_backups/warehouse_20260407_120000.duckdb"}
POST /api/backup/restore¶
Restore the warehouse from a backup.
{"path": "_backups/warehouse_20260407_120000.duckdb"}
POST /api/backup/cleanup¶
Remove old backups, keeping the most recent N.
{"keep": 5}
Catalog¶
GET /api/seeds¶
List all seed CSV files.
POST /api/seeds¶
Load all seeds. Body: {"force": false, "schema_name": "seeds"}
GET /api/sources¶
List declared sources from sources.yml.
GET /api/sources/freshness¶
Check source freshness against SLAs.
GET /api/exposures¶
List declared exposures.
GET /api/environment¶
Get current and available environments.
PUT /api/environment/{env_name}¶
Switch the active environment.
GET /api/overview¶
Get platform overview: schemas, tables, rows, recent runs, connectors.
Versioning¶
GET /api/versions¶
List all warehouse versions.
POST /api/versions¶
Create a new version snapshot.
GET /api/versions/{version_id}¶
Get version details.
GET /api/versions/{from_version}/diff¶
Diff two versions. Optional ?to_version=... (defaults to current state).
POST /api/versions/{version_id}/restore¶
Restore tables from a version.
GET /api/versions/timeline/{table_name}¶
Get version history for a specific table.
Documentation¶
GET /api/docs/markdown¶
Generate markdown documentation for the project.
GET /api/docs/structured¶
Generate structured documentation for the UI.
Lint¶
POST /api/lint¶
Lint SQL files. Body: {"fix": false}
Git¶
GET /api/git/status¶
Get git status: branch, dirty flag, changed files, last commit.
Wiki¶
GET /api/wiki¶
List all wiki pages with slugs, titles, and categories.
GET /api/wiki/{slug}¶
Get a wiki page by slug. Returns title, content (markdown), and category.
Collaboration¶
WebSocket /ws/collaborate¶
Real-time collaboration WebSocket for concurrent file editing.
Notebooks¶
Various notebook endpoints¶
Notebook endpoints handle listing, reading, executing cells, and saving .dpnb files. See the FastAPI auto-generated docs at /docs for the full notebook API.