How to Create a Custom Data Provider Extension for OpenBB: Complete Implementation Guide
To create a custom data provider extension for OpenBB, implement the Provider abstract base class from openbb_core, define an entry-point in your pyproject.toml under the openbb_provider_extension group, and install the package to enable automatic discovery by the ExtensionLoader.
The OpenBB Platform enables developers to integrate proprietary or specialized data sources through its extensible provider architecture. By building a custom data provider extension for OpenBB, you can expose external APIs to the OpenBB SDK, CLI, and notebook environment with full credential management and standardized output handling. This guide walks through the complete implementation using the actual source patterns found in the OpenBB-finance/OpenBB repository.
Understanding the Extension Architecture
OpenBB loads provider extensions dynamically at runtime using Python entry-points. The architecture relies on three core components that work together to discover, validate, and instantiate provider objects.
The Provider Abstract Base Class
Every custom provider must inherit from Provider, defined in openbb_core/provider/abstract/provider.py. This abstract class enforces a consistent interface that the platform expects, including standardized attributes for name, version, and credentials. When you subclass Provider, you implement data-fetching methods that return raw data dictionaries, which the platform later transforms into OBBject instances.
The ExtensionLoader Discovery Mechanism
The ExtensionLoader class in openbb_core/app/extension_loader.py acts as a singleton that scans for installed packages at startup. It specifically looks for entry-points registered under the group openbb_provider_extension (accessed via OpenBBGroups.provider.value). The loader imports each entry point and filters for objects that are instances of Provider, storing them in the provider_objects dictionary for runtime access by the CLI and SDK.
Scaffold the Provider Package
Create a standard Python package structure with a dedicated module for your provider implementation:
my_custom_provider/
├─ my_custom_provider/
│ ├─ __init__.py
│ └─ provider.py
├─ pyproject.toml
└─ README.md
The provider.py file will contain your concrete Provider subclass, while pyproject.toml handles the entry-point registration that makes the extension discoverable.
Implement the Provider Subclass
Create your provider implementation by subclassing the abstract base class and defining the required attributes.
# my_custom_provider/provider.py
from openbb_core.provider.abstract.provider import Provider
from typing import Any, Dict
class MyCustomProvider(Provider):
"""Example provider that fetches data from a fictional API."""
name = "my_custom_provider"
version = "0.1.0"
credentials = ["MY_API_KEY"]
def __init__(self, **kwargs: Any):
"""Initialize with credentials passed via kwargs."""
super().__init__(**kwargs)
self.api_key = kwargs.get("MY_API_KEY")
def fetch(self, ticker: str, start: str, end: str) -> Dict[str, Any]:
"""Core method returning raw data for a ticker."""
# Use self.api_key to query the external API
return {
"ticker": ticker,
"prices": [], # Your price data here
"metadata": {"source": "my_custom_provider"},
}
Required Attributes and Methods
Every provider implementation must define:
name: String identifier used throughout the SDK (e.g.,obb.provider.name.fetch())version: Semantic version string for documentation and compatibility trackingcredentials: List of strings naming required environment variables or settings keysfetch(): Primary data retrieval method that returns a dictionary parsable into anOBBject
Handling Credentials
The credentials list declares which API keys or tokens the provider requires. When OpenBB initializes, it checks the system settings JSON or environment variables for these values. Missing credentials trigger an error at startup, ensuring users configure access before attempting data retrieval.
Register the Entry-Point
Declare your provider in pyproject.toml to enable discovery by the ExtensionLoader:
[project]
name = "my_custom_provider"
version = "0.1.0"
description = "A custom data provider for OpenBB"
requires-python = ">=3.9"
[project.entry-points."openbb_provider_extension"]
my_custom_provider = "my_custom_provider.provider:MyCustomProvider"
The key openbb_provider_extension must match exactly what the loader expects (OpenBBGroups.provider.value). This registration maps the entry-point name to the import path of your Provider subclass.
Install and Verify
Install your package in editable mode for development:
pip install -e ./my_custom_provider
Verify the loader recognizes your provider by inspecting the provider_objects dictionary:
from openbb_core.app.extension_loader import ExtensionLoader
loader = ExtensionLoader()
print(loader.provider_objects.keys())
# Expected: dict_keys(['my_custom_provider', ...])
Configuration and Credentials
If your provider requires credentials, configure them via environment variables:
export MY_API_KEY="your-actual-key"
Alternatively, add them to the system settings JSON file used by OpenBB:
{
"my_custom_provider": {
"MY_API_KEY": "your-actual-key"
}
}
Add an OBBject Accessor (Optional)
To enable pandas-like accessor syntax (obb.my_custom_provider), create an extension using the Extension class from openbb_core/app/model/extension.py:
# my_custom_provider/obbject_extension.py
from openbb_core.app.model.extension import Extension
my_ext = Extension(
name="my_custom_provider",
description="Accessor for MyCustomProvider",
on_command_output=False,
)
@my_ext.obbject_accessor
def my_custom_provider(obb):
"""Return provider-bound OBBject."""
return obb.provider("my_custom_provider")
Register this under the openbb_obbject_extension entry-point group in pyproject.toml if you want automatic loading alongside your provider.
Summary
- Subclass
Provider: Inherit fromopenbb_core/provider/abstract/provider.pyand implement required attributes (name,version,credentials) and data methods (fetch). - Define Entry-Point: Register under
openbb_provider_extensioninpyproject.tomlto enable discovery byExtensionLoader. - Handle Credentials: Declare required keys in the
credentialslist and supply values via environment variables or system settings. - Verify Installation: Check
ExtensionLoader().provider_objectsto confirm your provider loads correctly at runtime. - Optional Accessor: Use the
Extensionclass to add pandas-like accessors for enhanced SDK usability.
Frequently Asked Questions
What methods must a custom OpenBB provider implement?
At minimum, you must implement the fetch() method to return raw data as a dictionary. You may optionally implement additional methods like search() depending on your data source capabilities. The Provider abstract base class requires name, version, and credentials class attributes, along with an __init__ method that accepts credential kwargs.
How does OpenBB discover installed provider extensions?
The ExtensionLoader singleton in openbb_core/app/extension_loader.py scans for Python entry-points under the group openbb_provider_extension at startup. It imports each entry point and validates that the object is an instance of the Provider abstract class before adding it to the provider_objects dictionary used by the SDK and CLI.
Where should API credentials be stored for a custom provider?
Store credentials as environment variables matching the strings listed in your provider's credentials attribute, or place them in the OpenBB system settings JSON file under the provider's name key. OpenBB validates these at initialization and raises errors if required credentials are missing, preventing runtime authentication failures.
Can a custom provider expose data through the OpenBB CLI?
Yes. Once registered and installed, your provider becomes available throughout the OpenBB ecosystem, including the CLI (ob fetch my_custom_provider ...), Python SDK (obb.provider.my_custom_provider.fetch()), and Jupyter notebooks. The standardized Provider interface ensures seamless integration with existing OpenBB commands and output formatting.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →