Bird
Raised Fist0
FastAPIframework~10 mins

OpenAPI schema customization in FastAPI - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - OpenAPI schema customization
Start FastAPI app
↓
Define API endpoints
↓
Customize OpenAPI schema function
↓
Assign custom schema to app.openapi
↓
Run app and access /openapi.json
↓
See customized schema output
This flow shows how FastAPI lets you replace the default OpenAPI schema with your own custom version.
Execution Sample
FastAPI
from fastapi import FastAPI
app = FastAPI()

@app.get("/items")
async def read_items():
    return [{"item_id": "foo"}]

# Custom OpenAPI schema
original_openapi = app.openapi

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema
    openapi_schema = original_openapi()
    openapi_schema["info"]["title"] = "Custom API"
    app.openapi_schema = openapi_schema
    return app.openapi_schema

app.openapi = custom_openapi
This code creates a FastAPI app with one endpoint and replaces the OpenAPI schema to change the API title.
Execution Table
StepActionFunction CalledSchema StateOutput
1Start appFastAPI()NoneApp instance created
2Define /items endpoint@app.getNoneEndpoint registered
3Save original openapiapp.openapiNoneOriginal schema function saved
4Define custom_openapicustom_openapi()NoneFunction ready to override
5Assign custom_openapiapp.openapi = custom_openapiNoneOverride set
6Call app.openapi()custom_openapi()NoneCalls original_openapi()
7Generate default schemaoriginal_openapi()NoneDefault schema dict created
8Modify schema titlecustom_openapi()Default schemaTitle changed to 'Custom API'
9Cache schemacustom_openapi()Modified schemaSchema cached in app.openapi_schema
10Return schemacustom_openapi()Modified schemaCustom schema returned
11Subsequent callscustom_openapi()Cached schemaCached schema returned
12Access /openapi.jsonFastAPI internalCached schemaCustom schema JSON served
💡 Custom schema cached and served instead of default after first call
Variable Tracker
VariableStartAfter Step 6After Step 8After Step 9Final
app.openapi_schemaNoneNoneNoneModified schema dictModified schema dict
original_openapiFunctionFunctionFunctionFunctionFunction
openapi_schemaNoneDefault schema dictModified schema dictModified schema dictModified schema dict
Key Moments - 3 Insights
Why does the custom_openapi function check if app.openapi_schema exists before generating the schema?
To avoid regenerating the schema multiple times, it returns the cached schema if available, as shown in step 6 and 11 of the execution_table.
How does assigning app.openapi = custom_openapi change the behavior of the FastAPI app?
It replaces the default schema generator with the custom function, so when the schema is requested (step 6), the custom logic runs instead of the default.
What happens if you don't cache the modified schema in app.openapi_schema?
The schema would be regenerated on every request, causing unnecessary computation and possibly inconsistent results, unlike the caching shown in step 9.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 8, what change is made to the schema?
AThe API title is changed to 'Custom API'
BThe endpoint path is removed
CThe schema is deleted
DThe schema version is changed
💡 Hint
Check the 'Schema State' and 'Output' columns at step 8 in the execution_table
At which step does the custom schema get cached to avoid regeneration?
AStep 6
BStep 9
CStep 3
DStep 11
💡 Hint
Look for when app.openapi_schema is assigned in the execution_table
If you remove the line 'app.openapi = custom_openapi', what happens when accessing /openapi.json?
AAn error occurs
BNo schema is served
CThe default schema is served
DThe custom schema is still served
💡 Hint
Refer to step 5 where the override is assigned and what happens if it is missing
Concept Snapshot
FastAPI lets you replace the default OpenAPI schema by assigning a custom function to app.openapi.
This function can call the original schema generator, modify the schema dict, and cache it.
The custom schema is then served at /openapi.json instead of the default.
Caching the schema avoids repeated computation.
This is useful to change titles, descriptions, or add metadata.
Full Transcript
This visual execution trace shows how to customize the OpenAPI schema in FastAPI. First, you create a FastAPI app and define endpoints. Then you save the original openapi function. Next, you define a custom function that calls the original, modifies the schema (like changing the title), caches it, and returns it. You assign this custom function to app.openapi. When the app runs and the schema is requested, the custom function runs, returning the modified schema. The schema is cached to avoid regenerating it on every request. This process lets you change how the API schema looks without changing endpoint code.

Practice

(1/5)
1. What is the main purpose of customizing the OpenAPI schema in a FastAPI application?
easy
A. To provide clear API documentation with custom titles, descriptions, and versions
B. To speed up the API response time
C. To change the database connection settings
D. To automatically generate frontend UI components

Solution

  1. Step 1: Understand OpenAPI schema role

    The OpenAPI schema defines how the API is documented and described for users and tools.
  2. Step 2: Identify customization benefits

    Customizing it lets you add titles, descriptions, versions, and contact info to make docs clearer.
  3. Final Answer:

    To provide clear API documentation with custom titles, descriptions, and versions -> Option A
  4. Quick Check:

    OpenAPI schema customization = clear docs [OK]
Hint: Think: OpenAPI schema = API documentation details [OK]
Common Mistakes:
  • Confusing schema customization with performance tuning
  • Thinking it changes database or backend logic
  • Assuming it auto-generates frontend code
2. Which of the following is the correct way to set a custom title and version for your FastAPI app's OpenAPI schema?
easy
A. app = FastAPI(schema_title="My API", schema_version="1.0.0")
B. app = FastAPI(openapi_title="My API", openapi_version="1.0.0")
C. app = FastAPI(title="My API", version="1.0.0")
D. app = FastAPI(api_title="My API", api_version="1.0.0")

Solution

  1. Step 1: Recall FastAPI app parameters

    FastAPI accepts title and version as direct parameters in its constructor.
  2. Step 2: Match correct parameter names

    The correct parameters are exactly title and version, not schema_title or openapi_title.
  3. Final Answer:

    app = FastAPI(title="My API", version="1.0.0") -> Option C
  4. Quick Check:

    FastAPI(title, version) = correct syntax [OK]
Hint: Use 'title' and 'version' directly in FastAPI() [OK]
Common Mistakes:
  • Using incorrect parameter names like openapi_title
  • Trying to set schema properties after app creation
  • Confusing app config with route decorators
3. Given this FastAPI app code, what will be the OpenAPI docs URL by default?
from fastapi import FastAPI
app = FastAPI(title="Test API")

@app.get("/items/")
async def read_items():
    return [{"item_id": "foo"}]
medium
A. /api-docs
B. /openapi.json
C. /swagger
D. /docs

Solution

  1. Step 1: Recall FastAPI default docs path

    FastAPI by default serves Swagger UI at the path /docs.
  2. Step 2: Differentiate docs and schema URLs

    /openapi.json is the raw schema JSON, not the interactive docs UI.
  3. Final Answer:

    /docs -> Option D
  4. Quick Check:

    Default docs URL = /docs [OK]
Hint: Swagger UI docs default path is /docs in FastAPI [OK]
Common Mistakes:
  • Confusing /openapi.json with docs UI
  • Assuming /swagger or /api-docs are default
  • Not knowing FastAPI defaults for docs
4. What is wrong with this FastAPI app code if the goal is to hide the automatic docs UI?
app = FastAPI(docs_url=None)

@app.get("/users")
async def get_users():
    return [{"name": "Alice"}]
medium
A. docs_url should be set to False, not None
B. You must also set redoc_url=None to hide all docs
C. docs_url parameter does not exist in FastAPI
D. docs_url=None is correct and will hide docs UI

Solution

  1. Step 1: Understand docs_url and redoc_url

    FastAPI has two docs UIs: Swagger UI at docs_url and ReDoc at redoc_url.
  2. Step 2: Check hiding docs UI fully

    Setting docs_url=None hides Swagger UI but ReDoc remains unless redoc_url=None is also set.
  3. Final Answer:

    You must also set redoc_url=None to hide all docs -> Option B
  4. Quick Check:

    Hide all docs = docs_url=None + redoc_url=None [OK]
Hint: Set both docs_url and redoc_url to None to hide docs [OK]
Common Mistakes:
  • Assuming docs_url=None hides all docs
  • Using invalid values like False for docs_url
  • Not knowing about ReDoc docs URL
5. You want to customize your FastAPI app's OpenAPI schema to include a contact email and license info. Which code snippet correctly achieves this?
hard
A. app = FastAPI(contact={"email": "support@example.com"}, license_info={"name": "MIT"})
B. app = FastAPI(openapi_info={"contact": {"email": "support@example.com"}, "license": {"name": "MIT"}})
C. app = FastAPI(openapi_contact={"email": "support@example.com"}, openapi_license={"name": "MIT"})
D. app = FastAPI(openapi_contact_email="support@example.com", openapi_license_name="MIT")

Solution

  1. Step 1: Recall FastAPI parameters for contact and license

    FastAPI uses contact and license_info parameters to customize OpenAPI schema contact and license sections.
  2. Step 2: Match correct parameter names and structure

    contact and license_info expect dictionaries with keys like email and name respectively.
  3. Final Answer:

    app = FastAPI(contact={"email": "support@example.com"}, license_info={"name": "MIT"}) -> Option A
  4. Quick Check:

    Use contact and license_info dicts in FastAPI() [OK]
Hint: Use contact and license_info dicts in FastAPI() constructor [OK]
Common Mistakes:
  • Using openapi_contact or openapi_license which are invalid
  • Trying to nest contact inside openapi_info
  • Passing strings instead of dicts for contact/license
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard