Your First FastAPI Route
Start with one Python file. Define an async function, decorate it with @app.get, visit it in the browser. This is the atom of every web app.
# The basic concept: a function that returns data
def health():
return {'status': 'ok'}
print(health()) # {'status': 'ok'}
# FastAPI adds two things:
# 1. @app.get('/path') decorator -> registers the function as a route
# 2. async -> the function can await I/O without blocking other requests
# Step 1: A FastAPI app with one route
from fastapi import FastAPI
import uvicorn
app = FastAPI(title='OpenBenchML')
@app.get('/health')
async def health():
return {'status': 'ok'}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
# Install FastAPI + uvicorn
pip install fastapi uvicorn
# Run the server
python main.py
# In another terminal (or browser):
curl http://localhost:8000/health
# {"status":"ok"}
# FastAPI also gives you free docs at:
# http://localhost:8000/docs
How it works
Every web app is just functions that return data when a URL is hit. FastAPI's job is to (a) listen for HTTP requests, (b) match the URL to a registered function, (c) call that function, and (d) send the return value back as JSON. The @app.get('/health') decorator is what registers the function — without it, health() is just a regular Python function that nothing calls. The async keyword means the function can yield control to the event loop while waiting for I/O (database, HTTP, file) — so one worker can handle thousands of concurrent requests. In step 1, there's no I/O, so async is just a convention; it becomes essential in step 3 when we add a database.
- Forgetting `async` (or `def`) — the function must be one or the other, FastAPI won't accept a bare expression.
- Running `python main.py` without installing fastapi + uvicorn first — `pip install fastapi uvicorn`.
- Using `return` with a string — FastAPI wraps dicts as JSON, but a bare string gets quoted twice. Always return a dict (or a Pydantic model).
- Binding to `host='127.0.0.1'` in production — use `0.0.0.0` so the app listens on all interfaces, or it's unreachable from outside the container.