Module 1: Setup and First API
Primer Endpoint, JSON y Docs
Descripción de la cápsula
En esta cápsula escribes tu primer endpoint real en FastAPI, retornas JSON (diccionarios y listas), y exploras la documentación automática que FastAPI genera sin una sola línea extra.
Aprenderás qué es una path operation, cómo los decoradores conectan rutas HTTP con funciones Python, cómo FastAPI serializa automáticamente tu return a JSON, y cómo usar /docs (Swagger UI) y /redoc para probar endpoints desde el navegador. Al terminar, tendrás una API con múltiples endpoints y documentación interactiva lista para usar.
Path operations: El concepto fundamental
Una path operation es la combinación de:
- Path (ruta): La URL del endpoint (
/,/health,/items) - Operation (operación): El verbo HTTP (
GET,POST, etc.) - Function (función): La función Python que se ejecuta
from fastapi import FastAPI
app = FastAPI()
# Path: "/"
# Operation: GET
# Function: root()
@app.get("/")
def root():
return {"message": "Hello, World!"}
El decorador @app.get("/") le dice a FastAPI: "Registra la función root() como el handler para requests GET a la ruta /."
Tu primer endpoint GET
Código completo
# app/main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {
"message": "Welcome to my API",
"version": "1.0.0"
}
Levantar y probar
uvicorn app.main:app --reload
Abre http://127.0.0.1:8000 en tu navegador:
{
"message": "Welcome to my API",
"version": "1.0.0"
}
O con curl:
curl http://127.0.0.1:8000
curl -s http://127.0.0.1:8000 | python -m json.tool # Formato bonito
Retornar JSON: Dicts y listas
FastAPI convierte automáticamente varios tipos de Python a JSON:
| Tipo Python | JSON resultante |
|---|---|
dict | JSON object {} |
list | JSON array [] |
str | JSON string |
int, float | JSON number |
bool | JSON boolean |
None | JSON null |
Ejemplos
@app.get("/dict")
def return_dict():
return {"key": "value"}
# → {"key": "value"}
@app.get("/list")
def return_list():
return [1, 2, 3, "four"]
# → [1, 2, 3, "four"]
@app.get("/nested")
def return_nested():
return {
"user": {"name": "Ana", "age": 25},
"tags": ["python", "fastapi"]
}
En la práctica, la mayoría de endpoints retornan diccionarios. Es la convención estándar para APIs REST.
Tipos no estándar
Si retornas un objeto custom (ej: instancia de una clase propia), FastAPI intentará serializarlo. Para tipos estándar (datetime, UUID) Pydantic los convierte automáticamente. Para clases propias, define un modelo Pydantic o implementa __json__ si es necesario. En este módulo solo usarás dicts y listas.
Múltiples endpoints
Agrega más rutas al mismo archivo:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "Welcome to my API", "version": "1.0.0"}
@app.get("/health")
def health_check():
return {"status": "healthy"}
@app.get("/about")
def about():
return {
"name": "FastAPI Fundamentals API",
"description": "Learning FastAPI step by step",
"python_version": "3.12"
}
Cada decorador @app.get() registra una ruta diferente. FastAPI mantiene un router interno que mapea paths a funciones.
Probar todos
curl http://127.0.0.1:8000/
curl http://127.0.0.1:8000/health
curl http://127.0.0.1:8000/about
Documentación automática: /docs y /redoc
Swagger UI: /docs
Con el servidor corriendo, abre:
http://127.0.0.1:8000/docs
Verás una interfaz interactiva con todos tus endpoints. Para cada uno puedes:
- Ver el método y la ruta
- Hacer clic en "Try it out"
- Ejecutar el request
- Ver la respuesta (body, headers, status code)
Esto reemplaza curl y Postman para pruebas rápidas durante desarrollo.
ReDoc: /redoc
http://127.0.0.1:8000/redoc
ReDoc presenta la misma información con un diseño más orientado a documentación de referencia. No tiene "Try it out", pero es más legible para compartir con equipos.
Comparación rápida
| Aspecto | /docs (Swagger) | /redoc |
|---|---|---|
| Try it out | Sí | No |
| Uso ideal | Desarrollo, testing | Documentación para otros |
| Diseño | Funcional | Elegante |
Personalizar metadata de la API
Puedes personalizar el título, descripción y versión que aparecen en la documentación:
from fastapi import FastAPI
app = FastAPI(
title="FastAPI Fundamentals API",
description="API de ejemplo para aprender FastAPI. Incluye endpoints GET y documentación automática.",
version="1.0.0",
)
@app.get("/")
def root():
return {"message": "Welcome"}
Refresca /docs. Ahora verás tu título y descripción en la cabecera.
Documentar endpoints individuales
Puedes agregar summary, description y tags a cada endpoint:
@app.get(
"/health",
summary="Health Check",
description="Verifica que el servicio está corriendo. Útil para load balancers.",
tags=["System"]
)
def health_check():
return {"status": "healthy"}
@app.get(
"/about",
summary="About API",
description="Metadata de la API: nombre, descripción, versión.",
tags=["System"]
)
def about():
return {"name": "FastAPI Fundamentals API", "version": "1.0.0"}
Los tags agrupan endpoints en secciones en /docs. Organiza por categoría: "System", "Items", "Users", etc.
OpenAPI: El estándar detrás
FastAPI genera automáticamente un schema OpenAPI. Puedes verlo en:
http://127.0.0.1:8000/openapi.json
Es un archivo JSON que describe tu API. Tanto /docs como /redoc lo leen para generar las interfaces. Tu código Python es la fuente de verdad — OpenAPI se genera a partir de él.
Flujo de generación
Tu código Python (decoradores, type hints, docstrings)
↓ FastAPI analiza y construye el schema
openapi.json (schema OpenAPI 3.1)
↓ Swagger UI y ReDoc lo interpretan
Interfaces /docs y /redoc
Cada vez que agregas o modificas un endpoint, el schema se actualiza. No hay desincronización entre código y documentación.
Docstrings como documentación
Puedes usar docstrings en lugar de (o además de) description en el decorador:
@app.get("/health", tags=["System"])
def health_check():
"""
Verifica que el servicio está corriendo.
Útil para load balancers y monitoreo.
"""
return {"status": "healthy"}
FastAPI renderiza el docstring como Markdown en la documentación. Si defines tanto description como docstring, el docstring tiene prioridad.
Código completo del ejemplo
# app/main.py
from fastapi import FastAPI
app = FastAPI(
title="FastAPI Fundamentals API",
description="API de ejemplo con múltiples endpoints GET.",
version="1.0.0",
)
@app.get("/", tags=["General"])
def root():
return {"message": "Welcome to my API", "version": "1.0.0"}
@app.get("/health", tags=["System"], summary="Health Check")
def health_check():
return {"status": "healthy"}
@app.get("/about", tags=["System"], summary="About")
def about():
return {
"name": "FastAPI Fundamentals API",
"description": "Learning FastAPI step by step"
}
Desactivar o customizar URLs de documentación
En producción a veces se desactiva la documentación por seguridad:
app = FastAPI(
docs_url=None, # Desactiva /docs
redoc_url=None, # Desactiva /redoc
)
O cambiar las rutas:
app = FastAPI(
docs_url="/api-docs",
redoc_url="/api-reference",
)
Para desarrollo, déjalas activas. Son tu herramienta principal de pruebas.
Troubleshooting
Problema 1: 404 Not Found en un endpoint
Causa: La URL no coincide exactamente con la ruta definida.
Solución: Las rutas son case-sensitive y no incluyen trailing slash por defecto:
@app.get("/health")
# ✅ http://127.0.0.1:8000/health
# ❌ http://127.0.0.1:8000/Health
# ❌ http://127.0.0.1:8000/health/
Problema 2: Un endpoint no aparece en /docs
Causa: Error de sintaxis en el decorador o en la función.
Solución:
# ❌ Mal — falta ruta
@app.get
def root():
return {"message": "Hello"}
# ✅ Bien
@app.get("/")
def root():
return {"message": "Hello"}
Verifica que no hay errores en la terminal de uvicorn.
Problema 3: /docs muestra página en blanco
Causa: Problemas cargando assets (CDN bloqueado, sin internet).
Solución: Verifica conexión a internet. Swagger UI carga recursos desde un CDN. En entornos restringidos puede requerir configuración adicional.
Problema 4: La descripción no se muestra
Causa: Formato incorrecto en description o docstring.
Solución: Usa strings válidos:
@app.get("/health", description="Verifica que el servicio está activo.")
def health_check():
return {"status": "healthy"}
Ejercicios
Ejercicio 1: Endpoint de timestamp (Fácil)
Crea un endpoint GET en /time que retorne la fecha y hora actual del servidor en formato JSON.
Ver solución
from datetime import datetime
from fastapi import FastAPI
app = FastAPI()
@app.get("/time")
def current_time():
now = datetime.now()
return {
"date": now.strftime("%Y-%m-%d"),
"time": now.strftime("%H:%M:%S"),
"timestamp": now.isoformat()
}
Explicación: datetime.now() obtiene la fecha/hora actual. strftime la formatea. FastAPI serializa el dict a JSON.
Ejercicio 2: Retornar una lista (Fácil)
Crea un endpoint GET en /items que retorne una lista de 3 items con id y name. Usa una lista de diccionarios.
Ver solución
@app.get("/items")
def list_items():
return [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"},
{"id": 3, "name": "Item 3"},
]
Explicación: FastAPI convierte listas de dicts a arrays JSON automáticamente. La respuesta será [{...}, {...}, {...}].
Ejercicio 3: Personalizar documentación (Medio)
Configura tu aplicación con título "Mi Primera API", versión "0.1.0", y una descripción. Agrega tags "General" y "System" a tus endpoints. Verifica en /docs que todo se muestra correctamente.
Ver solución
from fastapi import FastAPI
app = FastAPI(
title="Mi Primera API",
description="API de aprendizaje con FastAPI. Endpoints básicos y documentación.",
version="0.1.0",
)
@app.get("/", tags=["General"])
def root():
return {"message": "Welcome"}
@app.get("/health", tags=["System"], summary="Health Check")
def health_check():
return {"status": "healthy"}
Explicación: title, description y version aparecen en la cabecera de Swagger. Los tags agrupan los endpoints en secciones.
Ejercicio 4: Probar con "Try it out" (Fácil)
Abre /docs, haz clic en un endpoint, "Try it out", "Execute". Anota qué información te muestra: Request URL, Response body, Response code. Compara con lo que verías usando curl.
Ver solución
En /docs con Try it out:
- Curl: El comando curl equivalente (puedes copiarlo)
- Request URL: La URL completa usada
- Response body: El JSON de la respuesta
- Response code: 200, 404, etc.
Con curl: Obtienes lo mismo pero manualmente. "Try it out" te da todo en una interfaz visual y genera el curl por ti.
Explicación: Swagger UI es una herramienta de desarrollo integrada. Para pruebas rápidas durante desarrollo, suele ser más cómoda que curl.
Ejercicio 5: API con 4 endpoints (Medio)
Crea una API con exactamente 4 endpoints: /, /health, /about, /items. El último debe retornar una lista vacía o con un item de ejemplo. Usa tags para organizar. Verifica que los 4 aparecen en /docs y funcionan.
Ver solución
from fastapi import FastAPI
app = FastAPI(title="Mi API", version="1.0.0")
@app.get("/", tags=["General"])
def root():
return {"message": "Hello, World!"}
@app.get("/health", tags=["System"])
def health():
return {"status": "healthy"}
@app.get("/about", tags=["System"])
def about():
return {"name": "Mi API", "version": "1.0.0"}
@app.get("/items", tags=["Items"])
def items():
return []
Explicación: Cada @app.get() registra un endpoint. /items retorna una lista vacía [] que se serializa a [] en JSON.
Ejercicio 6: openapi.json (Medio)
Abre http://127.0.0.1:8000/openapi.json en tu navegador. Busca la sección paths. ¿Cuántas rutas hay? ¿Qué información tiene cada una?
Ver solución
En paths verás un objeto donde cada key es una ruta (/, /health, etc.). Cada ruta tiene un objeto con los métodos permitidos (get, post, etc.) y sus detalles (summary, parameters, responses).
Contar rutas: Cuenta las keys en paths. Si tienes 4 endpoints, habrá 4 keys.
Información típica:
summary: Título del endpointresponses: Códigos de respuesta (200, 422, etc.)operationId: Identificador único
Explicación: openapi.json es el schema que /docs y /redoc interpretan. Es la representación estándar de tu API en formato legible por máquinas.
Flujo completo: De código a respuesta
Cuando escribes:
@app.get("/health")
def health_check():
return {"status": "healthy"}
Y un cliente hace GET /health:
- uvicorn recibe el request
- FastAPI busca la ruta en el router
- Encuentra
health_checkasociada a GET /health - Ejecuta la función (sin argumentos en este caso)
- Recibe
{"status": "healthy"} - Serializa a JSON con Content-Type: application/json
- Retorna HTTP 200 con el body
Todo esto ocurre en milisegundos. Tú solo defines la función; el framework maneja el resto.
Resumen
- ✅ Una path operation combina ruta + verbo HTTP + función Python
- ✅
@app.get("/ruta")registra un endpoint GET - ✅ Retornar diccionarios o listas se serializa automáticamente a JSON
- ✅ /docs (Swagger UI) permite probar endpoints con "Try it out"
- ✅ /redoc ofrece documentación de referencia
- ✅ Puedes personalizar metadata (title, description, version) y documentar cada endpoint (summary, tags)
- ✅ openapi.json es el schema que alimenta ambas interfaces
Próxima cápsula: Proyecto Hello World API — integrarás todo en una API con 4 endpoints, código completo y rúbrica de evaluación.
Recursos Adicionales
- FastAPI - First Steps - Tutorial oficial
- FastAPI - Metadata - Personalización de documentación
- Swagger UI - Herramienta detrás de /docs
- ReDoc - Herramienta detrás de /redoc
- OpenAPI 3.1 - Especificación OpenAPI
- JSON.org - Formato JSON
Módulo 1, Cápsula 05 — FastAPI Fundamentals Guide