Estructura tu FastAPI con APIRouter

Resumen

Cuando tu aplicación crece, mantener todos los endpoints en un solo archivo se vuelve un dolor de cabeza. Aquí aprenderás a estructurar tu proyecto FastAPI con APIRouter, separar responsabilidades por recursos y agrupar rutas con tags para que tu documentación se mantenga clara y tu código sea fácil de mantener.

Esta guía es útil si ya construiste tus primeros endpoints y quieres llevar tu API a un nivel profesional, listo para producción y para trabajar en equipo.

¿Por qué dividir tu aplicación FastAPI en módulos?

Un archivo único con cientos de líneas hace que cualquier cambio sea engorroso. Separar el proyecto en módulos te permite tocar solo lo necesario, hacer pull requests limpios y escalar sin perder el control.

La idea central es simple: cada recurso (clientes, transacciones, facturas) vive en su propio archivo dentro de una carpeta dedicada. Y aquí entra la pieza clave, el APIRouter, que funciona como una miniaplicación de FastAPI capaz de agrupar endpoints relacionados.

¿Qué es APIRouter en FastAPI? Es una clase que actúa como una miniaplicación dentro de tu app principal. Te deja agrupar endpoints por recurso y aplicarles configuraciones comunes sin tocar uno por uno [02:15].

¿Cómo se organiza la estructura de carpetas recomendada?

La documentación oficial sugiere una estructura clara que separa la aplicación, los routers y la configuración. Esta es la base que vas a replicar.

Dentro de tu proyecto necesitas estos elementos [01:30]:

  • Carpeta app que agrupa los archivos de la aplicación.
  • Archivo __init__.py dentro de app para convertirla en módulo y permitir imports.
  • Archivo main.py con la instancia principal de FastAPI.
  • Archivo dependencies.py para inyectar dependencias compartidas.
  • Subcarpeta routers con su propio __init__.py y un archivo por recurso (customer.py, transactions.py, invoices.py).
  • Archivo db.py fuera de app con la configuración de base de datos.
  • Archivo models.py para modelos pequeños, o una carpeta models/ cuando son muchos.
  • Archivo requirements.txt para reproducir el entorno en otro servidor.

Un detalle importante: el __init__.py solo va dentro de app y routers, nunca en la raíz del proyecto, porque convertirías el root en un módulo y romperías los imports.

¿Cuándo conviene separar los modelos en una carpeta?

Si tienes uno, dos o tres modelos, mantenlos en un solo archivo models.py. Es más simple y evitas imports innecesarios. Cuando la cantidad crece, conviene crear una carpeta models/ con su __init__.py y un archivo por modelo.

¿Cómo crear un router para customer paso a paso?

El flujo es directo: mover los endpoints del recurso a su propio archivo y reemplazar la instancia app por una instancia de APIRouter.

Dentro de routers/customer.py haces los imports relativos hacia atrás con dos puntos para alcanzar models y db desde la carpeta superior [04:20]:

python from ..models import Customer, CustomerCreate, CustomerUpdate from ..db import SessionDB from fastapi import APIRouter, status, HTTPException from sqlmodel import select

router = APIRouter()

Luego reemplazas todos los decoradores @app.get, @app.post, etc., por @router.get, @router.post. Los endpoints siguen funcionando igual, solo cambia quién los registra.

¿Qué hace el archivo __init__.py? Convierte una carpeta en un módulo de Python para que puedas importar sus archivos desde otras partes del proyecto. Sin él, los imports fallan [01:55].

¿Cómo registrar el router en la aplicación principal?

En main.py eliminas los imports que ya no usas (porque los endpoints se movieron) e incluyes el router con include_router:

python from fastapi import FastAPI from .routers import customer

app = FastAPI() app.include_router(customer.router)

Fíjate en el punto antes de routers: indica un import relativo dentro del paquete app. Si lo olvidas, verás un error de módulo no encontrado.

¿Cómo agrupar endpoints en la documentación con tags?

Por defecto, los endpoints aparecen bajo el grupo default en la documentación de Swagger. Para agruparlos por recurso, agregas el parámetro tags al crear el router [07:40]:

python router = APIRouter(tags=["customers"])

Al recargar la documentación, todos los endpoints del archivo aparecen agrupados bajo customers, plegables con un clic. Esto mejora la lectura para cualquier persona que consuma tu API.

¿Cómo ejecutar la aplicación con la nueva estructura?

Antes ejecutabas fastapi apuntando a un archivo en la raíz. Ahora debes indicar la ruta completa al main.py dentro de app [06:10]:

bash fastapi dev app/main.py

Si ves un error que menciona models, revisa dos cosas: que no exista un __init__.py en la raíz del proyecto y que los imports relativos en tus routers usen la cantidad correcta de puntos.

Los errores de imports en Python son comunes cuando reorganizas archivos. Tómalos como parte natural del proceso y verifica siempre la jerarquía de carpetas.

¿Qué ganas al estructurar tu API de esta forma?

Al separar cada recurso en su propio router obtienes ventajas concretas para el día a día del desarrollo:

  • Cambios más específicos: tocas solo el archivo del recurso afectado.
  • Pull requests más limpios y fáciles de revisar.
  • Documentación organizada por grupos lógicos.
  • Posibilidad de aplicar dependencias o prefijos a todo un grupo de endpoints desde el APIRouter.

Como reto, replica el proceso para los módulos de transactions e invoices. Crea sus archivos en routers/, mueve los endpoints correspondientes, registra cada router en main.py con include_router y no olvides agregar su tags para que queden agrupados en la documentación.

¿En qué parte de la reorganización te trabaste? Cuéntame en los comentarios cómo resolviste los imports relativos.