Skip to main content

Trigger ETL Pipeline via REST API

Zynexa Semantic Layer Architecture

Zynexa exposes an async REST API to trigger ingester, dbt, and full pipeline runs without SSH access. Jobs run in the background — fire the trigger, get a jobId, and poll for status.

Prerequisites
  • PIPELINE_ENABLED=true in .env.production
  • Lakehouse DB running (docker compose --profile lakehouse up -d lakehouse-db)

See Pipeline Orchestration for all configuration variables.


Quick Start​

# On the target server, use localhost (Zynexa listens on port 3000)
BASE=http://localhost:3000

# Or from a remote machine, use the server IP
# BASE=http://{IP_ADDRESS}:3000

# 1. Trigger full pipeline (ingester + dbt)
curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{"pipeline": "full"}' | jq .

# 2. Poll for completion
curl -s "$BASE/api/data-analytics/pipeline/trigger?jobId=<jobId>" | jq .
Testing on the server

SSH into the server and use http://localhost:3000 directly — no DNS or reverse proxy needed. This is the simplest way to verify the pipeline API is working.


Trigger Request​

POST /api/data-analytics/pipeline/trigger

Request Body​

FieldTypeRequiredDefaultDescription
pipelinestringYes—"ingester", "dbt", or "full"
commandstringNo"daily"dbt command: "daily", "run", "build", "test", "deps", "elementary"
enableOpenlineagebooleanNoServer defaultOverride ENABLE_OPENLINEAGE for this run
enableElementarybooleanNoServer defaultOverride ENABLE_ELEMENTARY for this run

Pipeline Types​

TypeWhat it runsTypical duration
ingesterDLT ingester → Bronze (~46 tables)2–5 min
dbtdbt deps → build → elementary5–15 min
fullIngester first, then dbt (sequential)10–20 min

dbt Commands​

CommandWhat it does
dailydbt deps → dbt build → dbt run --select elementary (default)
rundbt run only (skip tests)
builddbt build (models + tests)
testdbt test only
depsdbt deps only (install packages)
elementaryElementary report generation only

Response​

The API returns immediately with HTTP 202 Accepted:

{
"success": true,
"output": "Pipeline \"dbt\" started in background.",
"exitCode": -1,
"jobId": "dbt-1710460800000-abc123",
"status": "running"
}

Response Fields​

FieldDescription
successtrue when the trigger was accepted, false when the API itself failed
jobIdUnique ID for polling
status"running" → "completed" or "failed"
exitCodeContainer exit code (-1 while running, 0 = clean, non-zero = pipeline errors)
outputLast 10 KB of container stdout+stderr
success vs exitCode
  • success = whether the trigger command itself worked (container ran to completion)
  • exitCode = pipeline-level result (missing tables, test failures → non-zero)

A job with status: "completed" and exitCode: 1 means the trigger worked but dbt had errors. Check logs for details.


Poll for Status​

GET /api/data-analytics/pipeline/trigger?jobId=<jobId>

Completed Successfully​

{
"success": true,
"exitCode": 0,
"jobId": "dbt-1710460800000-abc123",
"status": "completed",
"output": "...Finished running 271 models, 197 tests...\nDone. PASS=271 WARN=5 ERROR=0..."
}

Completed with Pipeline Errors​

{
"success": true,
"exitCode": 1,
"jobId": "dbt-1710460800000-abc123",
"status": "completed",
"output": "...ERROR=5 (missing bronze tables)..."
}

List All Jobs​

GET /api/data-analytics/pipeline/trigger

Returns all active and recently completed jobs (cleaned up after 1 hour).


Example Payloads​

All examples use BASE=http://localhost:3000 (run from the target server). Replace with http://{IP_ADDRESS}:3000 for remote access.

Run Ingester Only​

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{"pipeline": "ingester"}' | jq .

dbt Daily — All Features Enabled (Default)​

Runs dbt with OpenLineage (Marquez lineage) and Elementary reports using server defaults:

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{
"pipeline": "dbt",
"command": "daily"
}' | jq .

dbt Daily — Without OpenLineage (No Marquez)​

Skip lineage emission — uses plain dbt instead of dbt-ol:

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{
"pipeline": "dbt",
"command": "daily",
"enableOpenlineage": false
}' | jq .

dbt Daily — Without Elementary​

Skip the Elementary report generation step:

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{
"pipeline": "dbt",
"command": "daily",
"enableElementary": false
}' | jq .

dbt Daily — Minimal (No Marquez, No Elementary)​

Fastest run — plain dbt build only, no lineage, no reports:

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{
"pipeline": "dbt",
"command": "daily",
"enableOpenlineage": false,
"enableElementary": false
}' | jq .

dbt Daily — With OpenLineage, Without Elementary​

Track lineage in Marquez but skip the Elementary report:

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{
"pipeline": "dbt",
"command": "daily",
"enableOpenlineage": true,
"enableElementary": false
}' | jq .

Full Pipeline (Ingester → dbt)​

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{"pipeline": "full", "command": "daily"}' | jq .

dbt Build Only (Models + Tests, No Elementary)​

curl -s -X POST "$BASE/api/data-analytics/pipeline/trigger" \
-H "Content-Type: application/json" \
-d '{"pipeline": "dbt", "command": "build"}' | jq .

Poll Until Done (bash)​

JOB_ID="dbt-1710460800000-abc123"

while true; do
RESULT=$(curl -s "$BASE/api/data-analytics/pipeline/trigger?jobId=$JOB_ID")
STATUS=$(echo "$RESULT" | jq -r '.status')
echo "Status: $STATUS"

if [[ "$STATUS" != "running" ]]; then
echo "$RESULT" | jq .
break
fi
sleep 10
done

Toggle Summary​

PayloadOpenLineageElementaryUse Case
{} (defaults)Server defaultServer defaultNormal daily run
"enableOpenlineage": falseOffServer defaultSkip Marquez lineage
"enableElementary": falseServer defaultOffSkip report generation
Both falseOffOffFastest — plain dbt only
"enableOpenlineage": true, "enableElementary": falseOnOffLineage only, no report

Error Responses​

HTTP StatusMeaning
202Job accepted and running in background
400Invalid pipeline type or dbt command
403PIPELINE_ENABLED=false — pipeline API disabled
404Job ID not found
409Container already running (ingester or dbt)
500Server error

See Also​