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

> Learn how to add custom API endpoints to the OpenBB REST API. This guide shows developers how to create extensions and integrate them seamlessly into the main FastAPI application.

- Repository: [OpenBB/OpenBB](https://github.com/OpenBB-finance/OpenBB)
- Tags: how-to-guide
- Published: 2026-03-06

---

**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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_famafrench/famafrench_router.py).

Create a new Python module for your extension, for example [`my_custom_api/router.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/my_custom_api/router.py):

```python

# 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`](https://github.com/OpenBB-finance/OpenBB/blob/main/my_custom_api/__init__.py):

```python

# 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`](https://github.com/OpenBB-finance/OpenBB/blob/main/pyproject.toml) under the `openbb.extension` group.

Add the following to your [`pyproject.toml`](https://github.com/OpenBB-finance/OpenBB/blob/main/pyproject.toml):

```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`](https://github.com/OpenBB-finance/OpenBB/blob/main/setup.cfg):

```ini
[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:

```bash
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**:

```bash

# 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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_core/api/rest_api.py) | Creates the main `FastAPI` app and adds routers via `AppLoader` |
| [`openbb_core/api/app_loader.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_core/api/app_loader.py) | Helper that injects routers into the app (`add_routers`) |
| [`openbb_core/app/extension_loader.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_core/app/extension_loader.py) | Loads installed extensions from `openbb.extension` entry-points |
| [`openbb_core/app/router.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_core/app/router.py) | Holds the internal `Router` class that aggregates all extension routers |
| [`my_custom_api/router.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/my_custom_api/router.py) *(your file)* | Defines the custom FastAPI endpoints |
| [`my_custom_api/__init__.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/my_custom_api/__init__.py) *(your file)* | Exposes the router to the ExtensionLoader |
| [`pyproject.toml`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/__init__.py) using a callable that returns the `APIRouter` instance.
- **Entry-Point Registration**: Add the `openbb.extension` entry-point in [`pyproject.toml`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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`](https://github.com/OpenBB-finance/OpenBB/blob/main/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.