Chapter 1, Basic
What is an API and why FastAPI
An API is a contract between the requester and the responder. FastAPI transforms this contract, written as Python types, into automatic validation, conversion, and documentation.
What is an API
When an application shows its list of orders, it does not have the orders. It asks a server, which queries a database and responds. This question and this answer follow a contract: which address to call, with which verb, with which data, and what comes back. This contract is the API (Application Programming Interface).
Almost every web API speaks HTTP. A request has a verb, a path, headers, and sometimes a body. The response has a status code, headers, and generally a body in JSON:
POST /produtos HTTP/1.1
Host: api.exemplo.com
Content-Type: application/json
{"nome": "Caneta", "preco": 3.5}
HTTP/1.1 201 Created
Content-Type: application/json
{"id": 7, "nome": "Caneta", "preco": 3.5}
The four verbs that form the CRUD are the basis of almost everything you will build:
| Operation | HTTP Verb | Purpose | Typical success |
|---|---|---|---|
| Create | POST | Create a new resource | 201 Created |
| Read | GET | Read, without changing anything | 200 OK |
| Update | PUT or PATCH | Replace or modify part of a resource | 200 OK |
| Delete | DELETE | Remove a resource | 204 No Content |
What is FastAPI
FastAPI is a web framework for Python. It is built on top of two libraries: Starlette, which handles HTTP, routing, and middleware, and Pydantic, which handles data validation and conversion. Its central idea is that type annotation is the source of truth: you write it idade: int once, and FastAPI uses that to convert input, reject anything invalid, and describe the parameter in the documentation.
from fastapi import FastAPI
app = FastAPI(title="Loja", version="1.0")
@app.get("/produtos")
def listar_produtos():
return ["caneta", "caderno"]
documento = app.openapi()
print(documento["openapi"])
print(list(documento["paths"]))
print(documento["info"]["title"], documento["info"]["version"])
3.1.0
['/produtos']
Loja 1.0
The app.openapi() returns the complete API description in the format OpenAPI, an industry standard. We didn't write any of this: FastAPI built it from the route and the types. It is this document that feeds the page /docs (Swagger UI) and the /redoc, and that other tools use to generate clients and tests.
FastAPI, Django, and Flask
The three solve different problems, and choosing between them is not a matter of "which is faster":
| FastAPI | Django | Flask | |
|---|---|---|---|
| Focus | APIs, with data validated by types | Complete applications (admin, ORM, authentication, templates) | Small and flexible applications |
| Input validation | Automatic, by types | Forms and serializers (Django REST Framework) | Manual or by extensions |
| Interactive documentation | Automatic (OpenAPI) | By extensions | By extensions |
| Asynchronous code | Native (async def) | Supported in views and in ASGI | Supported in views, with limitations |
A common mistake in old materials is to say that Django and Flask "do not support async". Today both have some, to different degrees. What FastAPI offers is a way to write the code asynchronous from the start and integrated validation. For a large system with an admin panel and many screens, Django remains a great choice. For an API that serves an application or other services, FastAPI is often the shortest path.
The two most significant resources
Automatic validation. If the client sends text where you asked for a number, FastAPI responds with an error 422 explaining which field failed. You don't write any if.
Automatic documentation. When you open /docs, you see all the routes, the fields of each one, and a button to test the route right there. During development, this replaces Postman most of the time.
Documentation is not just for you
The OpenAPI document is read by machines. Frontend teams generate typed clients from it, and testing tools generate test cases. The more faithful your type annotation is, the more useful it is.
Exercise 1
Which verb, which status?
Write verbo_e_status(acao), which receives "criar", "ler", "atualizar" or "remover" and returns the pair (verbo, status de sucesso típico) from the table above. For "atualizar", use PUT.