Respuesta rápida
El desarrollo de APIs con Python utiliza frameworks como FastAPI y Django REST para crear servicios web escalables. Python ofrece tipado opcional, documentación automática con OpenAPI y alto rendimiento con async/await. Es la opción preferida por startups y empresas tecnológicas en España.
¿Por qué Python para el desarrollo de APIs?
En el ecosistema de desarrollo backend, Python ocupa un lugar privilegiado por razones que van más allá de la popularidad. Para equipos que priorizan velocidad de entrega sin sacrificar calidad, pocas combinaciones son tan eficientes como Python junto a un framework moderno.
La sintaxis concisa y el ecosistema maduro reducen drásticamente el tiempo de implementación. Una API funcional con autenticación puede estar lista en horas, no días.
pip cuenta con más de 400.000 paquetes. Desde clientes HTTP hasta librerías de machine learning, todo está disponible y bien documentado.
Los type hints de Python 3.10+ permiten que frameworks como FastAPI generen documentación Swagger interactiva de forma automática, sin configuración adicional.
Python 3.7+ incluye asyncio en la librería estándar. Con async/await y ASGI, las APIs Python manejan miles de conexiones concurrentes con bajo uso de recursos.
FastAPI vs Django REST Framework
La elección del framework condiciona la arquitectura del proyecto, las convenciones del equipo y el rendimiento en producción. Ambas opciones son sólidas; la decisión correcta depende del contexto.
Para APIs modernas y rendimiento
Construido sobre Starlette y Pydantic. Ideal para APIs puras, microservicios y proyectos donde el rendimiento es crítico.
- Documentación OpenAPI automática desde los tipos
- ASGI nativo: 50k+ req/s con Uvicorn
- Validación de datos con Pydantic v2
- Inyección de dependencias elegante
- Ideal: microservicios, ML APIs, startups
Para proyectos con lógica de negocio compleja
ORM maduro, admin panel, sistema de permisos y migraciones. Ecosistema de 20+ años probado en producción.
- ORM con migraciones automáticas
- Panel de administración incluido
- Sistema de permisos granular
- Serializers con validación avanzada
- Ideal: SaaS, plataformas, ERPs
Regla práctica
Si el proyecto es una API pura sin necesidad de admin panel y el equipo conoce los tipos de Python, elige FastAPI. Si el proyecto tiene una base de datos relacional compleja, flujos de aprobación y necesitas prototipar rápido con un admin funcional, elige Django REST Framework. En muchos proyectos grandes, ambos conviven: DRF gestiona el backoffice y FastAPI expone los endpoints de alto tráfico.
Arquitectura de una API profesional
Una API bien estructurada separa responsabilidades en capas. El objetivo es que cada capa sea testeable de forma independiente y que los cambios en una no rompan las demás.
mi_api/
├── app/
│ ├── api/
│ │ ├── v1/
│ │ │ ├── routes/
│ │ │ │ ├── users.py # Endpoints HTTP
│ │ │ │ └── products.py
│ │ │ └── router.py
│ ├── core/
│ │ ├── config.py # Settings (pydantic-settings)
│ │ ├── security.py # JWT, hashing
│ │ └── dependencies.py # Inyección de dependencias
│ ├── models/
│ │ └── user.py # Modelos SQLAlchemy / Pydantic
│ ├── schemas/
│ │ └── user.py # Request / Response schemas
│ ├── services/
│ │ └── user_service.py # Lógica de negocio
│ ├── repositories/
│ │ └── user_repo.py # Acceso a base de datos
│ └── main.py # Punto de entrada
├── tests/
│ ├── unit/
│ └── integration/
├── Dockerfile
├── docker-compose.yml
└── pyproject.toml
Patrón de inyección de dependencias en FastAPI
FastAPI tiene soporte nativo para inyección de dependencias, lo que permite separar la lógica de autenticación, acceso a base de datos y otras preocupaciones transversales del código de negocio.
from fastapi import APIRouter, Depends, HTTPException, status
from app.schemas.user import UserCreate, UserResponse
from app.services.user_service import UserService
from app.core.dependencies import get_current_user, get_user_service
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int,
service: UserService = Depends(get_user_service),
current_user = Depends(get_current_user),
) -> UserResponse:
"""Retrieve a user by ID. Requires authentication."""
user = await service.get_by_id(user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return user
El servicio contiene la lógica de negocio y el repositorio abstrae el acceso a datos. Esto hace que los tests unitarios no necesiten una base de datos real: basta con mockear el repositorio.
Autenticación y seguridad
La autenticación es la primera línea de defensa de cualquier API. Una implementación incorrecta puede exponer datos de todos tus clientes. Aquí están las prácticas que seguimos en producción.
JWT con OAuth2 Password Flow
FastAPI incluye soporte integrado para OAuth2 con JWT. El flujo estándar: el cliente envía credenciales al endpoint /auth/token, recibe un access token y lo incluye en cada petición como Authorization: Bearer <token>.
from datetime import datetime, timedelta, UTC
from jose import jwt, JWTError
from passlib.context import CryptContext
from app.core.config import settings
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(subject: str) -> str:
expire = datetime.now(UTC) + timedelta(
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
)
payload = {"sub": subject, "exp": expire}
return jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
Lista de controles de seguridad
allow_origins=["*"] en producción. Lista los dominios permitidos de forma explícita.
Testing y calidad del código
Una API sin tests no está terminada. Los tests no son opcionales en un proyecto profesional: son la documentación ejecutable que demuestra que el código hace lo que dice que hace.
Estructura de tests con pytest y httpx
Para APIs FastAPI, la combinación de pytest con httpx.AsyncClient es la elección estándar. El cliente asíncrono permite testear endpoints async sin levantar un servidor real.
import pytest
from httpx import AsyncClient, ASGITransport
from app.main import app
from app.core.security import create_access_token
@pytest.fixture
def auth_headers():
token = create_access_token(subject="test-user-id")
return {"Authorization": f"Bearer {token}"}
@pytest.mark.asyncio
async def test_get_user_authenticated(auth_headers):
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as client:
response = await client.get("/api/v1/users/1", headers=auth_headers)
assert response.status_code == 200
data = response.json()
assert "id" in data
assert "email" in data
@pytest.mark.asyncio
async def test_get_user_unauthenticated():
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as client:
response = await client.get("/api/v1/users/1")
assert response.status_code == 401
Los tests unitarios se enfocan en los servicios y repositorios de forma aislada, mockeando las dependencias externas. Los tests de integración verifican el flujo completo incluyendo base de datos (con una DB de test en memoria o contenedor Docker).
CI/CD integration
En un pipeline de CI/CD sano, los tests corren en cada push. Con GitHub Actions, un job típico instala dependencias, ejecuta pytest --cov y bloquea el merge si la cobertura cae por debajo del umbral configurado (recomendamos mínimo 80% en rutas críticas). Usa pytest-xdist para paralelizar y mantener el pipeline por debajo de 2 minutos.
Despliegue en producción
Una API que funciona en local pero no en producción no es una API terminada. El despliegue forma parte del producto.
Containerización con Docker
Docker garantiza que el entorno de desarrollo, staging y producción sean idénticos, eliminando la mayoría de los "funciona en mi máquina". Un Dockerfile bien escrito para una API FastAPI es directo:
FROM python:3.12-slim
# Prevent Python from writing .pyc files
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir .
COPY . .
# Run as non-root user for security
RUN adduser --disabled-password appuser
USER appuser
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
Opciones de hosting en producción
Independientemente del proveedor, implementa health checks (GET /health), structured logging con JSON (facilita la ingesta en ELK, Datadog o CloudWatch) y alertas sobre p95 de latencia y tasa de error 5xx.
Preguntas frecuentes
¿FastAPI o Django REST para mi proyecto?
Depende de tu caso. FastAPI es ideal si priorizas rendimiento, tipado estricto y documentación automática sin overhead. Django REST Framework es mejor si necesitas un ORM maduro, un panel de administración integrado o un ecosistema más amplio de librerías. Para APIs puras de alto rendimiento, FastAPI gana. Para aplicaciones con lógica de negocio compleja y base de datos relacional, Django REST es una elección sólida. En proyectos grandes, ambos pueden convivir.
¿Cómo manejar la autenticación en una API Python?
La opción más común es JWT. El cliente envía credenciales, recibe un token firmado y lo incluye en cada petición en el header Authorization: Bearer <token>. FastAPI incluye soporte OAuth2 nativo con python-jose y passlib. Usa tokens de corta duración (15-30 min) con refresh tokens de larga duración. Para APIs internas máquina a máquina, las API keys son una alternativa más simple y eficiente.
¿Cuánto cuesta desarrollar una API profesional?
Una API REST básica con autenticación, 10-15 endpoints, tests y documentación puede costar entre 3.000 y 8.000 euros en un plazo de 3-6 semanas. APIs con integraciones múltiples, microservicios o pipelines de datos complejos pueden superar los 20.000 euros y varios meses de desarrollo. El factor más relevante es la complejidad de la lógica de negocio, no el número de endpoints. En NextrategIA damos estimaciones detalladas tras una primera llamada gratuita.
¿Python es suficientemente rápido para APIs en producción?
Sí. FastAPI con Uvicorn alcanza 50.000-100.000 peticiones por segundo en benchmarks estándar, comparable a frameworks de Node.js o Go para la mayoría de casos de uso empresariales. El cuello de botella rara vez es el framework en sí, sino la base de datos o la lógica de negocio. Con async/await y connection pooling (asyncpg, SQLAlchemy async), Python maneja perfectamente cargas de producción reales. Empresas como Instagram, Dropbox y Spotify usan Python en sus backends.