[{"data":1,"prerenderedAt":104},["ShallowReactive",2],{"qa-\u002Ffastapi\u002Ffundamentals\u002Fopenapi-docs":3},{"page":4,"siblings":87,"blog":78},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":77,"related":78,"seo":79,"seoDescription":80,"stem":81,"subtopic":82,"topic":83,"topicSlug":84,"updated":85,"__hash__":86},"qa\u002Ffastapi\u002Ffundamentals\u002Fopenapi-docs.md","Openapi Docs",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"easy","md","FastAPI","fastapi",{},true,5,"\u002Ffastapi\u002Ffundamentals\u002Fopenapi-docs",[23,27,31,35,40,44,48,52,56,60,65,69,73],{"id":24,"difficulty":14,"q":25,"a":26},"openapi-auto-generation","How does FastAPI generate an OpenAPI schema automatically?","At application startup FastAPI inspects every registered route — its path,\nHTTP method, type annotations, Pydantic models, `Query`\u002F`Body`\u002F`Header`\ndefinitions and docstrings — and assembles an **OpenAPI 3.x** JSON document.\n\n```python\napp = FastAPI(title=\"My API\", version=\"1.0.0\")\n\n@app.get(\"\u002Fitems\u002F{id}\", summary=\"Fetch an item\")\nasync def get_item(id: int) -> Item:\n    \"\"\"Return a single item by its numeric ID.\"\"\"\n    ...\n# OpenAPI schema available at \u002Fopenapi.json\n```\n\nThe schema drives:\n- `\u002Fdocs` — Swagger UI (interactive browser)\n- `\u002Fredoc` — ReDoc (readable reference)\n- Client code generators (`orval`, `openapi-generator`)\n\nRule of thumb: treat the auto-generated schema as the source of truth for your\nAPI contract; add `summary`, `description`, `responses` and tags to keep it accurate.\n",{"id":28,"difficulty":14,"q":29,"a":30},"swagger-vs-redoc","What is the difference between Swagger UI (`\u002Fdocs`) and ReDoc (`\u002Fredoc`) in FastAPI?","Both render the same OpenAPI schema, but for different audiences:\n\n| | Swagger UI | ReDoc |\n|---|---|---|\n| URL | `\u002Fdocs` | `\u002Fredoc` |\n| Primary use | Interactive testing (try-it-out) | Readable documentation |\n| Layout | Split-pane, request builder | Three-panel, prose-first |\n| Authentication | OAuth2\u002FBearer flow built-in | Read-only |\n\n```python\napp = FastAPI(\n    docs_url=\"\u002Fdocs\",       # default\n    redoc_url=\"\u002Fredoc\",     # default\n)\n```\n\nBoth can be moved or disabled:\n```python\napp = FastAPI(docs_url=None, redoc_url=\"\u002Fapi-docs\")\n```\n\nRule of thumb: expose both; use Swagger UI for development\u002Ftesting, share ReDoc\nlinks for external consumer documentation.\n",{"id":32,"difficulty":14,"q":33,"a":34},"disable-docs-production","How do you disable the API docs in production?","Set `docs_url=None` and `redoc_url=None` (and optionally `openapi_url=None`)\nin the `FastAPI()` constructor. Typically done via an environment flag:\n\n```python\nimport os\nfrom fastapi import FastAPI\n\nDEBUG = os.getenv(\"DEBUG\", \"false\").lower() == \"true\"\n\napp = FastAPI(\n    docs_url=\"\u002Fdocs\" if DEBUG else None,\n    redoc_url=\"\u002Fredoc\" if DEBUG else None,\n    openapi_url=\"\u002Fopenapi.json\" if DEBUG else None,\n)\n```\n\nSetting `openapi_url=None` prevents schema scraping even if someone guesses the\n`\u002Fdocs` URL, since the UI needs the schema to render.\n\nRule of thumb: disable the schema endpoint (`openapi_url=None`) in production —\nleaking your API structure is a security surface even if no credentials are exposed.\n",{"id":36,"difficulty":37,"q":38,"a":39},"custom-openapi","medium","How do you customise the generated OpenAPI schema in FastAPI?","Override `app.openapi()` to intercept and modify the schema dict before it's served:\n\n```python\nfrom fastapi.openapi.utils import get_openapi\n\ndef custom_openapi():\n    if app.openapi_schema:\n        return app.openapi_schema\n    schema = get_openapi(\n        title=\"My API\",\n        version=\"2.0.0\",\n        description=\"Full API description with Markdown\",\n        routes=app.routes,\n    )\n    # add a custom security scheme\n    schema[\"components\"][\"securitySchemes\"] = {\n        \"ApiKey\": {\"type\": \"apiKey\", \"in\": \"header\", \"name\": \"X-API-Key\"}\n    }\n    app.openapi_schema = schema\n    return schema\n\napp.openapi = custom_openapi\n```\n\nRule of thumb: override `app.openapi()` only for cross-cutting schema changes\n(logos, extra security schemes); use per-route `responses={}` for endpoint-level docs.\n",{"id":41,"difficulty":14,"q":42,"a":43},"openapi-tags-metadata","How do you add descriptions to OpenAPI tags?","Pass `openapi_tags` to `FastAPI()`. Each entry maps a tag name to a description\nand optional external documentation link.\n\n```python\ntags_metadata = [\n    {\"name\": \"users\", \"description\": \"Operations with users. The **login** flow.\"},\n    {\"name\": \"items\", \"description\": \"Manage items. So _fancy_\", \"externalDocs\": {\n        \"description\": \"More docs\", \"url\": \"https:\u002F\u002Fexample.com\"\n    }},\n]\n\napp = FastAPI(openapi_tags=tags_metadata)\n```\n\nTags that appear in routes but not in `openapi_tags` still show up in the docs —\nthey just won't have descriptions.\n\nRule of thumb: define `openapi_tags` whenever the API has more than three resource\ngroups — it makes the Swagger UI navigable for external consumers.\n",{"id":45,"difficulty":37,"q":46,"a":47},"bearer-auth-swagger","How do you add Bearer token authentication to Swagger UI in FastAPI?","Declare an `OAuth2PasswordBearer` or `HTTPBearer` security scheme. FastAPI\nadds the \"Authorize\" button to Swagger UI automatically.\n\n```python\nfrom fastapi.security import HTTPBearer\n\nbearer = HTTPBearer()\n\n@app.get(\"\u002Fsecure\", dependencies=[Depends(bearer)])\nasync def secure_endpoint():\n    return {\"ok\": True}\n```\n\nFor a full OAuth2 password flow with the Swagger \"Authorize\" dialog:\n\n```python\nfrom fastapi.security import OAuth2PasswordBearer\n\noauth2_scheme = OAuth2PasswordBearer(tokenUrl=\"\u002Ftoken\")\n\n@app.get(\"\u002Fme\")\nasync def me(token: str = Depends(oauth2_scheme)):\n    ...\n```\n\nRule of thumb: using `OAuth2PasswordBearer` (not just `HTTPBearer`) gives you\nthe full username\u002Fpassword login form in Swagger UI — useful for manual testing.\n",{"id":49,"difficulty":14,"q":50,"a":51},"openapi-version","Which version of the OpenAPI specification does FastAPI generate by default?","FastAPI generates **OpenAPI 3.1.0** schemas by default as of v0.99+\n(previously 3.0.x). OpenAPI 3.1 uses JSON Schema 2020-12 for component schemas,\nwhich means it properly supports `null` types, `$ref` alongside other keywords, etc.\n\n```python\napp = FastAPI()\n# GET \u002Fopenapi.json → {\"openapi\": \"3.1.0\", ...}\n```\n\nIf you need 3.0.x compatibility (e.g., older code generators):\n```python\napp = FastAPI(openapi_version=\"3.0.3\")\n```\n\nRule of thumb: stay on 3.1.0 for new projects; pin to 3.0.x only if your\ntoolchain doesn't support 3.1 yet.\n",{"id":53,"difficulty":37,"q":54,"a":55},"schema-extra-example","How do you add examples to the OpenAPI schema for a Pydantic model?","In Pydantic v2, use `model_config` with `json_schema_extra`:\n\n```python\nfrom pydantic import BaseModel, ConfigDict\n\nclass Item(BaseModel):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"examples\": [{\"name\": \"Widget\", \"price\": 9.99}]\n        }\n    )\n    name: str\n    price: float\n```\n\nFor field-level examples, use `Field(examples=[...])`:\n\n```python\nfrom pydantic import Field\n\nclass Item(BaseModel):\n    name: str = Field(examples=[\"Widget\", \"Gadget\"])\n    price: float = Field(gt=0, examples=[9.99])\n```\n\nRule of thumb: add at least one realistic example per model — Swagger UI's\n\"Try it out\" pre-fills request bodies from examples, saving testers time.\n",{"id":57,"difficulty":14,"q":58,"a":59},"path-operation-include-in-schema","How do you hide a route from the OpenAPI schema?","Set `include_in_schema=False` in the route decorator. The endpoint still works\n— it just won't appear in `\u002Fopenapi.json` or the docs UI.\n\n```python\n@app.get(\"\u002Finternal\u002Fhealth\", include_in_schema=False)\nasync def health():\n    return {\"status\": \"ok\"}\n```\n\nCommon uses: health-check endpoints, internal debug routes, legacy redirects\nthat you don't want to document publicly.\n\nRule of thumb: use `include_in_schema=False` for infra\u002Fops endpoints that aren't\npart of the public API contract.\n",{"id":61,"difficulty":62,"q":63,"a":64},"api-versioning-strategies","hard","What are the common strategies for API versioning in FastAPI?","**URL prefix versioning** (most common):\n```python\nv1 = APIRouter(prefix=\"\u002Fv1\")\nv2 = APIRouter(prefix=\"\u002Fv2\")\napp.include_router(v1)\napp.include_router(v2)\n```\n\n**Multiple FastAPI apps mounted with `Mount`**:\n```python\nfrom starlette.routing import Mount\nv1_app = FastAPI()\nv2_app = FastAPI()\napp = FastAPI()\napp.mount(\"\u002Fv1\", v1_app)\napp.mount(\"\u002Fv2\", v2_app)\n# Each sub-app has its own \u002Fdocs\n```\n\n**Header versioning** (clean URLs, harder to implement):\n```python\n@app.get(\"\u002Fitems\")\nasync def items(accept_version: str = Header(default=\"v1\")):\n    if accept_version == \"v2\":\n        ...\n```\n\nURL prefix is recommended for REST APIs because it's cacheable, bookmarkable\nand obvious in logs.\n\nRule of thumb: use URL prefix (`\u002Fv1`, `\u002Fv2`) with separate `APIRouter` instances\nper version; mounted sub-apps are the cleanest option when versions diverge significantly.\n",{"id":66,"difficulty":37,"q":67,"a":68},"openapi-response-headers","How do you document custom response headers in the OpenAPI schema?","Add the headers to the `responses` dict in the route decorator under the status\ncode's `headers` key:\n\n```python\n@app.get(\n    \"\u002Fitems\",\n    responses={\n        200: {\n            \"headers\": {\n                \"X-Total-Count\": {\n                    \"description\": \"Total number of items\",\n                    \"schema\": {\"type\": \"integer\"},\n                }\n            }\n        }\n    },\n)\nasync def list_items(response: Response):\n    items = await db.all()\n    response.headers[\"X-Total-Count\"] = str(len(items))\n    return items\n```\n\nRule of thumb: document custom response headers in `responses={}` so consumers\nknow to look for them; set them at runtime by injecting `Response`.\n",{"id":70,"difficulty":62,"q":71,"a":72},"openapi-callbacks","What are OpenAPI callbacks and when would you define them in FastAPI?","**Callbacks** document webhooks that your API will call on the consumer's server\nafter a certain event. They're outbound HTTP calls your API makes, documented\nas if they were inbound routes.\n\n```python\nfrom fastapi import APIRouter\n\ninvoicing_callback = APIRouter()\n\n@invoicing_callback.post(\"{$callback_url}\u002Finvoice\")\ndef invoice_notification(body: InvoiceEvent): ...\n\n@app.post(\"\u002Fsubscriptions\", callbacks=invoicing_callback.routes)\nasync def create_subscription(subscription: Subscription):\n    # after payment succeeds, your server will POST to subscription.callback_url\n    ...\n```\n\nRule of thumb: define callbacks when your API sends webhook notifications —\nit lets consumers generate typed handlers for the events you'll push to them.\n",{"id":74,"difficulty":62,"q":75,"a":76},"swagger-ui-oauth2-config","How do you configure Swagger UI's OAuth2 settings (client ID, scopes) in FastAPI?","Pass `swagger_ui_init_oauth` to `FastAPI()`:\n\n```python\napp = FastAPI(\n    swagger_ui_init_oauth={\n        \"clientId\": \"my-client-id\",\n        \"scopes\": \"openid profile email\",\n        \"usePkceWithAuthorizationCodeGrant\": True,\n    }\n)\n```\n\nThis pre-fills the \"Authorize\" dialog in Swagger UI so developers don't have\nto type the client ID on every test session.\n\nFor full Swagger UI parameter control:\n```python\napp = FastAPI(\n    swagger_ui_parameters={\n        \"deepLinking\": True,\n        \"persistAuthorization\": True,   # keeps auth token across page refreshes\n    }\n)\n```\n\nRule of thumb: set `persistAuthorization: True` in development environments so\ntesters don't lose their JWT token every time they reload Swagger UI.\n",13,null,{"description":11},"FastAPI OpenAPI and docs interview questions — Swagger UI, ReDoc, schema customisation, security schemes, tags, versioning and disabling docs in production.","fastapi\u002Ffundamentals\u002Fopenapi-docs","OpenAPI & Docs","Fundamentals","fundamentals","2026-06-20","1i7CKl5qMzgKHDOxS30S_FxxsQvYZtjaUErzhfUAl5A",[88,92,95,99,103],{"subtopic":89,"path":90,"order":91},"Async Basics","\u002Ffastapi\u002Ffundamentals\u002Fasync-basics",1,{"subtopic":93,"path":94,"order":12},"Request Lifecycle","\u002Ffastapi\u002Ffundamentals\u002Frequest-lifecycle",{"subtopic":96,"path":97,"order":98},"Path Operations","\u002Ffastapi\u002Ffundamentals\u002Fpath-operations",3,{"subtopic":100,"path":101,"order":102},"Type Hints & FastAPI","\u002Ffastapi\u002Ffundamentals\u002Ftype-hints",4,{"subtopic":82,"path":21,"order":20},1782244112630]