New to Kestra?
Use blueprints to kickstart your first workflows.
Build a REST API to DuckDB ETL pipeline in Kestra. Extract JSON, transform it with Python and Polars, then run analytical SQL, all in one workflow.
Build a lightweight ETL and ELT pipeline that pulls JSON from a REST API, transforms it with Python and Polars, and runs analytical SQL with DuckDB, without standing up a warehouse, a Spark cluster, or any external infrastructure. This blueprint solves the everyday data engineering problem of turning a raw API response into a clean, queryable dataset using a single declarative YAML workflow that is reproducible, observable, and scheduled.
api task (io.kestra.plugin.core.http.Request) calls a REST endpoint (the DummyJSON products API by default) and returns the JSON body.python task (io.kestra.plugin.scripts.python.Script) runs on a Docker taskRunner (io.kestra.plugin.scripts.runner.docker.Docker) with the python:slim image and a Polars dependency. It parses the API body with a jq expression, builds a Polars DataFrame, selects the brand and price columns, and writes products.csv as an outputFile.sql_query task (io.kestra.plugin.jdbc.duckdb.Query) mounts that CSV as an inputFile, runs read_csv_auto over it, aggregates average price per brand with GROUP BY and ORDER BY, and uses fetchType: STORE to persist the result set.DuckDB and Polars are excellent engines but they have no scheduler, no retry logic, and no way to chain an HTTP call to a Python step to a SQL step. Kestra fills that gap: event and schedule triggers fire the flow automatically, per-task retries handle flaky API calls, passing outputFiles between tasks gives you clear data lineage, and the whole pipeline lives in version-controlled, declarative YAML instead of glue scripts.
This blueprint calls a public API and uses no secrets. If you point it at a private API, add a secret such as {{ secret('API_TOKEN') }} and pass it as an authorization header on the api task.
sql_query task output to see average price per brand.