How to Add Custom API Endpoints to the OpenBB REST API: A Complete Developer Guide

You can add custom API endpoints to the OpenBB REST API by creating a FastAPI APIRouter, packaging it as an OpenBB extension with an entry-point in pyproject.toml, and letting the ExtensionLoader automatically inject it into the main FastAPI application on startup.

The OpenBB REST API provides a powerful interface for financial data access, built on FastAPI and dynamically assembled from modular components. If you need to expose proprietary analytics, internal data sources, or specialized calculations, you can extend the platform by adding custom API endpoints that integrate seamlessly with the existing authentication and documentation systems.

How the OpenBB REST API Assembles Its Routes

Understanding the internal assembly process helps clarify where your custom code fits. The platform follows a three-stage initialization pattern defined in the core source code.

First, in openbb_core/api/rest_api.py, a global FastAPI instance (app) is instantiated and configured with middleware and exception handlers. Then the ExtensionLoader (defined in openbb_core/app/extension_loader.py) scans Python entry-points registered under the openbb.extension group, validating each discovered object using isinstance(entry, APIRouter). Finally, the AppLoader.add_routers method (in openbb_core/api/app_loader.py) receives the collected routers and mounts them onto the main app instance using FastAPI's include_router method.

Your custom endpoints become active when you provide a valid APIRouter through this extension mechanism.

Step 1: Create a FastAPI APIRouter with Custom Endpoints

Start by defining your routes using FastAPI's APIRouter class. This follows the same pattern used by built-in OpenBB providers, such as the Fama-French implementation in openbb_famafrench/famafrench_router.py.

Create a new Python module for your extension, for example my_custom_api/router.py:


# my_custom_api/router.py

from fastapi import APIRouter, HTTPException, Query

router = APIRouter(
    prefix="/myapi",          # URL prefix for all routes in this router

    tags=["My Custom API"],   # Tag appears in the OpenAPI docs

)

@router.get("/hello")
def hello(name: str = Query("world", description="Name to greet")):
    """Simple hello endpoint."""
    return {"message": f"Hello, {name}!"}

@router.post("/echo")
def echo(payload: dict):
    """Echo back the posted JSON payload."""
    if not payload:
        raise HTTPException(status_code=400, detail="Empty payload")
    return {"echo": payload}

The prefix parameter ensures all your endpoints are grouped under a common path, while tags organizes them in the interactive Swagger documentation.

Step 2: Expose the Router Through an OpenBB Extension

To make the platform aware of your router, you must expose it through the extension interface. The ExtensionLoader expects either the router object itself or a callable that returns it.

Create my_custom_api/__init__.py:


# my_custom_api/__init__.py

from fastapi import APIRouter
from .router import router as custom_router

def get_router() -> APIRouter:
    """OpenBB expects a callable that returns an APIRouter."""
    return custom_router

The loader specifically checks for APIRouter instances using isinstance(entry, APIRouter) when processing core_objects from each extension. Returning the router from a function ensures lazy loading and allows for any necessary initialization logic before the router is mounted.

Step 3: Register the Extension via pyproject.toml Entry-Points

The final step is registering your package as an OpenBB extension. This is done by declaring an entry-point in your project's pyproject.toml under the openbb.extension group.

Add the following to your pyproject.toml:

[tool.poetry.plugins."openbb.extension"]
my_custom_api = "my_custom_api"

If you are using setuptools instead of Poetry, use this format in setup.cfg:

[options.entry_points]
openbb.extension =
    my_custom_api = my_custom_api

When OpenBB starts, the ExtensionLoader scans these entry-points, imports the specified modules, and extracts any APIRouter objects to pass to AppLoader.add_routers.

Step 4: Verify Your Custom Endpoints Are Active

After installing your extension package (pip install -e . for local development), start the OpenBB platform:

python -m openbb_core.api.rest_api

Once the server is running, verify your integration:

  1. Check the Swagger UI: Navigate to http://localhost:8000/docs. You should see a "My Custom API" section containing your /myapi/hello and /myapi/echo endpoints.

  2. Test via cURL:


# Test the GET endpoint

curl "http://localhost:8000/myapi/hello?name=OpenBB"

# Expected output: {"message":"Hello, OpenBB!"}

# Test the POST endpoint

curl -X POST "http://localhost:8000/myapi/echo" \
     -H "Content-Type: application/json" \
     -d '{"ticker":"AAPL","field":"close"}'

# Expected output: {"echo":{"ticker":"AAPL","field":"close"}}

Successful responses confirm that AppLoader.add_routers has correctly mounted your router and that the ExtensionLoader properly discovered your entry-point.

Understanding the Extension Loading Mechanism

The seamless integration of custom endpoints relies on three core components working in sequence.

Rest API Initialization: The openbb_core/api/rest_api.py file creates the global FastAPI instance and immediately delegates router registration to AppLoader.add_routers, passing a collection of routers discovered through the extension system.

Extension Discovery: The ExtensionLoader class in openbb_core/app/extension_loader.py resolves entry-points by scanning the openbb.extension group, loading each module, and yielding any APIRouter objects as part of core_objects. This is where your custom code becomes part of the platform.

Router Mounting: Finally, AppLoader.add_routers in openbb_core/api/app_loader.py iterates over the supplied routers and calls include_router for each one, effectively mounting your custom endpoints under the specified prefixes.

Key Files in the Extension Architecture

File Role
openbb_core/api/rest_api.py Creates the main FastAPI app and adds routers via AppLoader
openbb_core/api/app_loader.py Helper that injects routers into the app (add_routers)
openbb_core/app/extension_loader.py Loads installed extensions from openbb.extension entry-points
openbb_core/app/router.py Holds the internal Router class that aggregates all extension routers
my_custom_api/router.py (your file) Defines the custom FastAPI endpoints
my_custom_api/__init__.py (your file) Exposes the router to the ExtensionLoader
pyproject.toml (your project) Declares the entry-point so OpenBB discovers the extension

Summary

Adding custom API endpoints to the OpenBB REST API leverages the platform's FastAPI foundation and extension entry-point system to dynamically integrate your code. The process requires creating a standard FastAPI router, exposing it through the OpenBB extension protocol, and registering it in your package metadata.

  • Router Creation: Define endpoints using FastAPI's APIRouter with unique prefixes and descriptive tags.
  • Extension Interface: Expose the router in your package's __init__.py using a callable that returns the APIRouter instance.
  • Entry-Point Registration: Add the openbb.extension entry-point in pyproject.toml to enable automatic discovery.
  • Dynamic Loading: The ExtensionLoader validates and collects your router, while AppLoader.add_routers mounts it to the main FastAPI application during startup.

Frequently Asked Questions

How does OpenBB discover custom API extensions?

OpenBB uses the ExtensionLoader class in openbb_core/app/extension_loader.py to scan Python entry-points registered under the openbb.extension group. When the platform initializes, it imports each registered module and checks for APIRouter objects using isinstance(entry, APIRouter), then aggregates these routers for mounting onto the main FastAPI application.

Can I use FastAPI dependencies and authentication in my custom endpoints?

Yes. Since you are working with standard FastAPI APIRouter objects, you can use all FastAPI features including Depends() for dependency injection, OAuth2 authentication schemes, and middleware. The OpenBB platform applies its own authentication and security layers in openbb_core/api/rest_api.py, but your router can define additional dependencies that FastAPI will enforce when those specific endpoints are accessed.

What URL prefix should I choose for my custom endpoints?

You should specify a unique, descriptive prefix when creating your APIRouter to avoid collisions with existing OpenBB routes. For example, use prefix="/mycompany" or prefix="/custom/v1" rather than generic paths like /api or /data. The AppLoader.add_routers method in openbb_core/api/app_loader.py mounts your router under this prefix, making the full path immediately accessible once the server starts.

Do I need to restart the OpenBB server after installing a new extension?

Yes. The ExtensionLoader scans entry-points and AppLoader.add_routers mounts routers only during the application startup sequence defined in openbb_core/api/rest_api.py. After installing your package with pip install, you must restart the OpenBB server to trigger the discovery process and make your new endpoints available in the REST API.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →