Skip to main content

Quickstart - Workspace Custom Backend

The OpenBB Platform can be used as a Workspace custom backend, both as a fully-loaded data source, or as the bare shell and launcher of a FastAPI application.

The sections below will outline a few scenarios.

Launch Platform App

To include all installed OpenBB extensions as widgets in the custom backend connector:

info

Open a terminal, activate the environment where openbb was installed, then enter:

openbb-api
  • Next, open your browswer and login to pro.openbb.co.

  • From the sidebar, click "Data Connectors".

  • Then, click the "Add Data" button.

Add Data

  • Enter a name for the connection, and use the server address displayed in the console.

  • Then, click the "Test" button.

tip

If a connection error displays after pressing the "Test" button, your browser might be blocking access because of "mixed content". Browsers such as Safari, and Brave, do not permit HTTP connections.

Try using Chrome, specifically, or start the server over HTTPS.

See the page here for the steps to do it.

  • Finally, click the "Add" button.

All data endpoints are now configured to use and are available to the Search.

Launch Custom Platform App

Let's say, you want to create a custom backend that presents data differently, and you don't want any of the built-in widgets to populate. You want complete control over the generated view.

In this scenario, use the --exclude argument to ignore the entire /api/* path.

Widgets will now only populate from endpoints added to the imported app instance.

from openbb_platform_api.main import app

from openbb import obb


@app.get("/company_description")
async def company_description(symbol: str = "AAPL") -> str:
"""Reference data for the given company using yFinance."""
response = obb.equity.profile(symbol, provider="yfinance")

description = response.results[0].long_description

md = f"""

# **{response.results[0].name}**
## **{response.results[0].sector}**
### **{response.results[0].industry_category}**

<details>
<summary mdxType="summary">Company Description</summary>
{description}
</details>

{response.results[0].company_url}
"""
return md

Launch the backend by including the path to the Python file as the --app argument.

openbb-api --app /Users/path/to/some/folder/some_file.py --exclude '"/api/v1/*"' --reload
Screenshot 2025-02-06 at 1 40 43 PM

Launch Any FastAPI App

For this, the only requirements are:

  • Python version between 3.9 and 3.12, inclusively.
  • openbb-platform-api package, installable from PyPI.

Add the path to the Python file with the FastAPI instance to launch.

openbb-api --app /Users/path/to/some/folder/some_file.py
important

At this time, only "GET" methods are supported by custom backends.

from fastapi import FastAPI

app = FastAPI()

@app.get("/hello")
async def hello() -> str:
"""Widget Description Generated By Docstring"""
return "Hello, from OpenBB!"

Function arguments will populate as widget parameters.

Parameters With Dropdown

Literal types of function parameters will automatically be recognized as choices in a dropdown menu.

from typing import Literal, Optional

app = FastAPI()

@app.get("/hello")
async def hello(param1: Optional[str] = None, param2: Literal["Choice 1", "Choice 2"] = None, param3: bool = False) -> str:
"""Widget Description Generated By Docstring"""
if not param1 and not param2 and not param3:
return "Enter a parameter or make a choice!"
if param3:
return f"Param3 enabled!"
if param2:
return f"You selected: {param2}"
if param1:
return f"You entered: {param1}"

return "Nothing to return!"

Table Widget

Create a table widget by returning data shaped as a list of dictionaries (records)

from fastapi import FastAPI

app = FastAPI()

@app.get("/hello")
async def hello() -> list:
"""Widget Description Generated By Docstring"""
return [{"Column 1": "Hello", "Column 2": "from OpenBB!"}]

Annotated Functions

Annotated parameters and responses will create column definitions and hover descriptions.

For data responses, return a list of Pydantic models to get the most bang-for-the-buck.

from typing import Annotated
from fastapi import FastAPI, Query
from openbb_core.provider.abstract.data import Data # Inherit this instead of pydantic.BaseModel to represent 1 row of data.
from pydantic import Field

app = FastAPI()

class MyData(Data):
"""MyData Response Model."""
column_1: str = Field(title="Some Text", description="Hover text for Column 1")
column_2: int = Field(title="Some Number", description="Hover text for Column 2")
column_3: float = Field(
title="Some Percent",
description="Hover text for Column 3",
json_schema_extra={"x-unit_measurement": "percent"},
)
column_4: float = Field(
title="Some Normalized Percent",
description="Hover text for Column 4",
json_schema_extra={"x-unit_measurement": "percent", "x-frontend_multiply": 100},
)


@app.get("/table")
async def table(
param1: Annotated[str, Query(description="Hover text for param1")] = None,
param2: Annotated[int, Query(description="Some Number")] = None,
date: Annotated[str, Query(description="Date selector")] = None,
) -> list[MyData]:
"""Widget Description Generated By Docstring"""
return [
MyData.model_validate(
{
"column_1": "Hello",
"column_2": 10,
"column_3": 33.345,
"column_4": -0.33345,
}
),
]
Screenshot 2025-02-06 at 8 00 30 PM