Main Client

class pybdl.client.BDL(config: BDLConfig | dict | None = None)[source]

Bases: object

Main interface for interacting with the Local Data Bank (BDL) API.

This class provides a unified entry point to all BDL API endpoints, including aggregates, attributes, data, levels, measures, subjects, units, variables, version, and years.

The access layer (default interface) returns pandas DataFrames with proper column labels and data types. The API layer (via .api) returns raw dictionaries for advanced use cases.

The pybdl.client.BDL class is the main entry point for the library. It provides two interfaces for accessing BDL data:

  1. Access Layer (default, recommended): Returns pandas DataFrames - use bdl.levels, bdl.data, etc.

  2. API Layer: Returns raw dictionaries - use bdl.api.levels, bdl.api.data, etc.

For most users, the access layer is recommended as it provides DataFrames that are immediately ready for data analysis.

Access Layer (Default Interface)

The access layer is the primary interface and returns pandas DataFrames:

from pybdl import BDL, BDLConfig

bdl = BDL(BDLConfig(api_key="your-api-key"))

# Access layer - returns DataFrames
levels_df = bdl.levels.list_levels()
variables_df = bdl.variables.list_variables()
data_df = bdl.data.get_data_by_variable(variable_id="3643", years=[2021])

# Data is ready for pandas operations
print(levels_df.head())
print(data_df.dtypes)
print(data_df.columns)

Key features of the access layer:

  • Automatic DataFrame conversion: All responses are pandas DataFrames

  • Column normalization: camelCase → snake_case (e.g., variableIdvariable_id)

  • Data type inference: Proper types (integers, floats, booleans)

  • Nested data flattening: Complex structures are normalized into tabular format

See Access Layer for comprehensive documentation on the access layer.

API Layer (Low-Level Interface)

The API layer provides direct access to raw API responses as dictionaries:

from pybdl import BDL

bdl = BDL()

# API layer - returns raw dictionaries
levels_data = bdl.api.levels.list_levels()
data_dict = bdl.api.data.get_data_by_variable(variable_id="3643", years=[2021])

# Raw API response structure
print(type(levels_data))  # list
print(type(data_dict))    # list or dict

Use the API layer when you need:

  • Raw API response structure

  • Custom response processing

  • Direct access to API metadata

  • Integration with non-pandas workflows

See API Clients for details about the API layer.

Examples

Basic Usage with Access Layer

from pybdl import BDL, BDLConfig

# Initialize client
bdl = BDL(BDLConfig(api_key="your-api-key"))

# Get administrative levels
levels = bdl.levels.list_levels()
print(f"Found {len(levels)} administrative levels")

# Get variables
variables = bdl.variables.search_variables(name="population")
print(f"Found {len(variables)} population variables")

# Get data
data = bdl.data.get_data_by_variable("3643", years=[2021], unit_level=2)
print(f"Retrieved {len(data)} data points")
print(data.head())

Using Both Interfaces

from pybdl import BDL

bdl = BDL()

# Access layer for DataFrame analysis
df = bdl.data.get_data_by_variable("3643", years=[2021])
avg_value = df['val'].mean()

# API layer for raw metadata
metadata = bdl.api.data.get_data_by_variable(
    "3643", years=[2021], return_metadata=True
)
if isinstance(metadata, tuple):
    data, meta = metadata
    print(f"Total pages: {meta.get('totalPages', 'unknown')}")

Async Usage

Both interfaces support async operations:

import asyncio
from pybdl import BDL

async def main():
    bdl = BDL()

    # Async access layer
    levels_df = await bdl.levels.alist_levels()
    variables_df = await bdl.variables.alist_variables()

    # Async API layer
    levels_data = await bdl.api.levels.alist_levels()

    return levels_df, variables_df, levels_data

asyncio.run(main())

See also