The hands-off way: loading Jedox into any warehouse with dlt

· Jedox

A declarative, Python-native pipeline that pulls Jedox cubes, dimensions and logs and loads them into DuckDB, Snowflake, BigQuery or a Fabric landing zone - schema and pagination handled for you.

In getting Jedox data into Microsoft Fabric (and any other server) I walked through the manual routes - the OData Hub, the OLAP HTTP API, and the Integrator. This post is about the option I reach for when I want a real, repeatable pipeline without hand-rolling one: dlt (data load tool), the open-source Python library for extract-and-load.

The idea is declarative. You describe the source - base URL, auth, which resources - and dlt does the unglamorous parts: pagination, schema inference, type coercion, state, and loading into one of a dozen destinations. There's a verified Jedox source that wraps Jedox's own APIs, so you don't even write the request code.

1. Get a token

dlt's Jedox source authenticates with a Personal Access Token (bearer), not a username/password. Create one in the Jedox Cloud Console at https://console.cloud.jedox.com/settings under Personal Access Tokens, then drop it into .dlt/secrets.toml:

[sources.jedox_source]
token = "your_personal_access_token_here"

Keeping the token in secrets.toml (or an env var / vault) is the whole point - it never touches your code.

2. Install

uv add "dlt[hub]"      # or: pip install "dlt[duckdb]"

3. The pipeline

This is the source-and-pipeline scaffold straight from the dlt Jedox docs - a @dlt.source that points at a Jedox API with bearer auth, lists the resources you want, and a pipeline that runs them into a destination:

import dlt
from dlt.sources.rest_api import RESTAPIConfig, rest_api_resources

@dlt.source
def jedox_source(token=dlt.secrets.value):
    config: RESTAPIConfig = {
        "client": {
            "base_url": "https://logs.{instance}.cloud.jedox.com/logs",
            "auth": {"type": "bearer", "token": token},
        },
        "resources": [
            {"name": "logs", "endpoint": {"path": "logs", "data_selector": "rows"}},
            {"name": "olap_server", "endpoint": {"path": "api"}},
        ],
    }
    yield from rest_api_resources(config)

def get_data() -> None:
    pipeline = dlt.pipeline(
        pipeline_name="jedox_pipeline",
        destination="duckdb",            # swap for snowflake / bigquery / postgres / filesystem
        dataset_name="jedox_data",
    )
    load_info = pipeline.run(jedox_source())
    print(load_info)

get_data()

Run it:

uv run python jedox_pipeline.py
uv run dlthub show          # opens a dashboard of what was loaded

4. What you can actually load

The Jedox source exposes five resources, each wrapping a different Jedox API:

So for "load my P&L cube into the warehouse," the resource you care about is integrator_odata pointed at your database's OData Flat API; the others are there for metadata and audit.

5. Pick a destination - one line

The reason dlt is worth the dependency: the same pipeline lands in whatever you're feeding, by changing one argument.

pipeline = dlt.pipeline(
    pipeline_name="jedox_pipeline",
    destination="snowflake",     # duckdb | postgres | bigquery | snowflake | redshift | databricks | filesystem
    dataset_name="jedox_data",
)

dlt supports DuckDB (the default, great for local dev), PostgreSQL, BigQuery, Snowflake, Redshift, Databricks, and Filesystem (S3 / GCS / Azure). That last one is your bridge into Microsoft Fabric: write Parquet to ADLS / OneLake with destination="filesystem", then shortcut or load it into a Lakehouse - exactly the Pattern B landing from the main post, but with dlt managing the files and schema.

6. Query what landed

data = dlt.pipeline("jedox_pipeline").dataset()
df = data.logs.df()          # any resource -> pandas DataFrame
print(df.head())
SELECT * FROM jedox_data.logs LIMIT 10;

dlt, Integrator, or raw requests?

They're not rivals so much as different altitudes:

Use raw requests first to understand the shape of your data. When you want it loading reliably into a warehouse, move to dlt. And when the pipeline should belong to Jedox itself, build it in the Integrator.

Back to all posts