Skip to main content

The FastAPI Application Class

The FastAPI class is the main entry point for creating an API. It inherits from Starlette, providing a high-level interface that automates OpenAPI schema generation, data validation, and interactive documentation.

In this tutorial, you will build a configured FastAPI application that includes custom metadata, global dependencies, and specialized response behavior.

1. Create a Basic Applicationโ€‹

The most minimal FastAPI application requires only an instantiation of the FastAPI class.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
return {"message": "Hello World"}

When you create an instance of FastAPI, it initializes an internal APIRouter (stored in self.router) and sets up default exception handlers for HTTPException and RequestValidationError. By default, it also prepares the endpoints for OpenAPI documentation.

2. Configure API Metadataโ€‹

You can customize how your API appears in the autogenerated documentation by passing metadata parameters to the FastAPI constructor. These values are used by self.openapi() to generate the schema.

from fastapi import FastAPI

app = FastAPI(
title="ChimichangApp",
summary="Deadpond's favorite app. Nuff said.",
description="""
ChimichangApp API helps you do awesome stuff. ๐Ÿš€

## Items
You can **read items**.
""",
version="0.0.1",
terms_of_service="http://example.com/terms/",
contact={
"name": "Deadpoolio the Amazing",
"url": "http://x-force.example.com/contact/",
"email": "dp@x-force.example.com",
},
license_info={
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html",
},
)

FastAPI uses these fields to populate the info object in the OpenAPI specification. The description field supports Markdown, which will be rendered in the Swagger UI.

3. Define Path Operationsโ€‹

While the FastAPI class inherits the routes parameter from Starlette, you should use the provided decorator methods like app.get(), app.post(), app.put(), and app.delete() to define your API endpoints.

@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}

@app.post("/items/")
async def create_item(item: dict):
return {"message": "Item created", "item": item}

These methods internally call self.router.add_api_route(). They handle the complex logic of converting your function signatures into OpenAPI path parameters, query parameters, and request bodies.

4. Manage Documentation Endpointsโ€‹

FastAPI automatically serves interactive documentation. You can configure the URLs for these endpoints or disable them entirely by setting them to None.

app = FastAPI(
docs_url="/documentation",
redoc_url=None,
openapi_url="/api/v1/openapi.json"
)

If you set openapi_url=None, both the Swagger UI (/docs) and ReDoc (/redoc) will be disabled because they depend on the OpenAPI schema.

5. Apply Advanced Configurationโ€‹

For larger applications, you can set global behaviors such as default response classes and global dependencies that apply to every route in the application.

from typing import Any
from fastapi import Depends, FastAPI
from fastapi.responses import JSONResponse

# Define a custom response class
class ORJSONResponse(JSONResponse):
media_type = "application/x-orjson"
def render(self, content: Any) -> bytes:
import orjson
return orjson.dumps(content)

# Define a simple dependency
async def common_parameters(q: str | None = None):
return {"q": q}

app = FastAPI(
default_response_class=ORJSONResponse,
dependencies=[Depends(common_parameters)]
)
  • default_response_class: Changes the default serialization behavior for the entire app.
  • dependencies: A list of Depends() objects that will be executed for every request, including those in sub-routers included via app.include_router().
  • root_path: If your app is behind a proxy (like Nginx) with a path prefix (e.g., /api/v1), set root_path="/api/v1" to ensure the documentation correctly resolves the OpenAPI URL.

Complete Working Resultโ€‹

Combining these steps, your final main.py looks like this:

from typing import Annotated
from fastapi import Depends, FastAPI
from fastapi.responses import ORJSONResponse

async def global_verify(x_token: str | None = None):
# Imagine logic to verify a header here
return x_token

app = FastAPI(
title="Production API",
version="1.2.0",
default_response_class=ORJSONResponse,
dependencies=[Depends(global_verify)],
root_path="/api/v1"
)

@app.get("/status")
async def get_status():
return {"status": "ok"}

@app.post("/data")
async def post_data(payload: dict):
return {"received": payload}

By following this structure, you have a production-ready application entry point that is documented, validated, and configured for deployment behind a proxy. To verify the result, run your application with an ASGI server like Uvicorn and visit /api/v1/docs.