API RESTful con versionado y documentación automática
Diseñar una API RESTful con versionado y documentación automática para tu aplicación
Imagina que entregas una API sin versionado ni documentación estructurada. Lo que pasa después casi siempre es lo mismo: clientes que se rompen cuando despliegas, integraciones que fallan sin avisar y desarrolladores perdiendo tardes enteras intentando descifrar qué hace cada endpoint. Eso es deuda técnica pura, y empieza el día uno.
Diseñar bien una API REST desde el principio —con una estrategia de versionado y documentación que se genera sola— no es un capricho de proyectos enormes. Es algo que ahorra horas y dinero en cuanto tu API tiene más de un consumidor. En las próximas secciones te voy a llevar paso a paso por ese diseño: principios REST, OpenAPI y gestión de versiones a lo largo de la vida del producto.
Por qué el versionado es inseparable del diseño de la API
Piensa en tu API como un contrato. Tú prometes a quien la consume que ciertos endpoints se comportan de cierta forma. Si cambias ese contrato sin avisar, es como cambiar las reglas del juego a mitad de partida: alguien va a perder.
El versionado te permite tres cosas concretas:
- Que las integraciones existentes sigan vivas aunque el backend evolucione por debajo.
- Que tu equipo de producto pueda retirar funcionalidad poco a poco, sin roturas bruscas.
- Que los desarrolladores externos —o los equipos internos que consumen tu API— puedan planificar sus migraciones con margen.
Estrategias de versionado más utilizadas
Versionado en la URL. La versión va como segmento del path: /api/v1/usuarios, /api/v2/pedidos. Es la opción más visible y la más fácil de implementar. Stripe y GitHub la adoptan precisamente porque facilita la depuración y el enrutamiento.
Versionado por cabecera HTTP. El cliente manda algo así como Accept: application/vnd.miapp.v2+json. Es más limpio a nivel semántico, sí, pero ojo: cuesta más probarlo directamente desde un navegador o un curl rápido.
Versionado por parámetro de consulta. Añades ?version=2 al final. Esta casi nunca es buena idea en producción, porque mezclas parámetros de negocio con parámetros de infraestructura y acabas con un cajón de sastre.
Para la mayoría de proyectos web y aplicaciones a medida, el versionado en la URL es el que mejor balancea claridad, facilidad de caché y simplicidad operativa.
Versionado semántico aplicado a APIs
Si llevas el esquema MAJOR.MINOR.PATCH al mundo de las APIs, lo traduces así:
- MAJOR: cambios que rompen compatibilidad (modificar o eliminar campos obligatorios, cambiar el comportamiento de un endpoint existente).
- MINOR: nuevas funcionalidades retrocompatibles (añadir endpoints, añadir campos opcionales).
- PATCH: correcciones de bugs que no tocan la interfaz.
En la práctica, en la URL solo expones el MAJOR (/v1, /v2). El MINOR y el PATCH se gestionan de forma transparente, sin que el cliente tenga que hacer nada.
Principios de diseño RESTful que garantizan escalabilidad
Antes de meter versionado, la API tiene que estar bien estructurada. Y aquí muchos equipos tropiezan: etiquetan como "REST" lo que en realidad son endpoints RPC disfrazados con HTTP.
Recursos, no acciones
El error más típico es nombrar los endpoints con verbos: /getUsuario, /crearPedido, /borrarProducto. REST funciona con sustantivos —los recursos— y deja el verbo al método HTTP:
GET /usuarios/{id}— obtener un usuarioPOST /usuarios— crear un usuarioPUT /usuarios/{id}— reemplazar un usuarioPATCH /usuarios/{id}— actualizar parcialmenteDELETE /usuarios/{id}— eliminar
Jerarquía de recursos
Cuando dos recursos tienen relación de pertenencia directa, los anidas en la ruta:
GET /proyectos/{proyectoId}/tareas
POST /proyectos/{proyectoId}/tareas
GET /proyectos/{proyectoId}/tareas/{tareaId}
Ahora bien, no pases de dos niveles de anidación. A partir de ahí la URL se vuelve frágil, difícil de cachear y dolorosa de leer.
Códigos de estado HTTP correctos
HTTP ya trae un vocabulario completo de respuestas. Devolver siempre 200 OK con un campo error dentro del cuerpo obliga al cliente a parsear el JSON solo para saber si algo se rompió. Mal negocio.
Estos son los códigos que vas a usar más:
| Código | Situación típica |
|---|---|
| 200 | Éxito en GET, PUT, PATCH |
| 201 | Recurso creado con POST |
| 204 | Éxito sin cuerpo (DELETE) |
| 400 | Datos de entrada inválidos |
| 401 | No autenticado |
| 403 | Autenticado pero sin permiso |
| 404 | Recurso no encontrado |
| 409 | Conflicto (duplicado, estado incompatible) |
| 422 | Entidad no procesable (validación semántica) |
| 500 | Error interno del servidor |
Paginación, filtrado y ordenación
Cualquier listado de recursos acaba necesitando estas tres cosas. Una convención que funciona bien:
GET /productos?page=2&limit=20&sort=precio&order=asc&categoria=electronica
Para APIs con volúmenes grandes, la paginación por cursor (?cursor=abc123) escala mucho mejor que la de offset. La razón es simple: al saltar a la página 5000 con offset, la base de datos tiene que recorrer todo lo anterior. Con cursor, no.
Documentación automática con OpenAPI y Swagger
La documentación que se escribe a mano queda obsoleta en cuanto tocas el código. La solución que se ha asentado en el sector es describir la API con la especificación OpenAPI (antes Swagger) y generar la documentación desde el propio código o desde el esquema.
Qué es OpenAPI
OpenAPI es un estándar para describir APIs REST en YAML o JSON. Un fichero OpenAPI válido recoge:
- Todos los endpoints y sus métodos HTTP.
- Los parámetros que acepta cada operación (path, query, header, body).
- Los esquemas de los objetos de entrada y salida.
- Los mecanismos de autenticación.
- Los códigos de respuesta posibles y la estructura de cada uno.
Ese fichero lo leen las máquinas. Y de ahí salen muchas cosas gratis: documentación interactiva, SDKs en varios lenguajes, tests de contrato y mocks de servidor.
Integración en el flujo de desarrollo
Hay dos enfoques, y elegir uno u otro depende de tu equipo:
Design-first. Escribes el fichero OpenAPI antes de tocar código. El equipo acuerda el contrato, genera stubs del servidor y clientes de prueba, y luego implementa la lógica. Funciona muy bien cuando frontend y backend son equipos separados, porque elimina los malentendidos clásicos del "yo entendí que el campo se llamaba así".
Code-first. El desarrollador anota el código con decoradores o comentarios y una librería extrae el esquema OpenAPI cuando ejecutas o compilas. Es más ágil para equipos pequeños donde el contrato cambia rápido.
Herramientas por tecnología
Según el stack, tienes opciones maduras:
- Node.js con Express:
swagger-jsdocpara sacar el esquema desde comentarios JSDoc yswagger-ui-expresspara servir la interfaz interactiva. - Node.js con Fastify: el plugin oficial
@fastify/swagger, con soporte nativo. - Python con FastAPI: OpenAPI 3.x viene integrado en el framework. Cero configuración.
- Python con Django REST Framework:
drf-spectacularpara generar el esquema con cobertura completa. - Java con Spring Boot:
springdoc-openapi, basado en anotaciones estándar. - Go: librerías como
swaggo/swag, que leen comentarios del código fuente.
Swagger UI: documentación interactiva en producción (o staging)
Cuando ya tienes el fichero OpenAPI, Swagger UI lo convierte en una web donde cualquier desarrollador puede explorar endpoints, ver los esquemas y lanzar peticiones reales contra el servidor. Eso baja la barrera de entrada brutalmente, tanto para gente nueva en el equipo como para integradores externos.
Eso sí: en producción, protege la URL de Swagger UI con autenticación básica o restringe el acceso a IPs internas. Tu documentación no debería convertirse en un mapa para atacantes.
Gestionar la obsolescencia: deprecación de versiones
Ninguna API puede arrastrar versiones antiguas para siempre. Lo importante es que cuando vayas a retirar una versión, esto no sea una sorpresa para nadie. El proceso típico tiene cuatro pasos:
- Anuncio temprano: avisa con al menos 6-12 meses de antelación, tanto por cabeceras HTTP (
Deprecation: true,Sunset: fecha) como por comunicación directa a los consumidores registrados. - Período de solapamiento: mantén ambas versiones activas durante la transición para que los clientes migren sin agobios.
- Monitorización de uso: registra qué versiones siguen recibiendo tráfico, así detectas a los rezagados antes de apagar la luz.
- Sunset definitivo: en la fecha anunciada, desactiva los endpoints y devuelve
410 Goneen lugar de404. Estás diciendo "esto existió, lo retiramos a propósito", no "esto nunca existió".
Seguridad en el diseño de la API
Diseño y seguridad van de la mano. Estos son los puntos donde más conviene parar a pensar.
Autenticación y autorización
OAuth 2.0 con JWT es el estándar cuando tu API sirve a varios clientes distintos. El JWT viaja en la cabecera Authorization: Bearer <token> y el servidor lo valida sin tener que consultar la base de datos en cada petición. Eso te ahorra latencia.
Para APIs internas o integraciones B2B sencillas, las API Keys sobran, siempre que las rotes periódicamente y solo viajen por HTTPS.
Rate limiting
Pon un techo de peticiones por cliente y ventana de tiempo —por ejemplo, 1000 peticiones por hora y API Key— para protegerte de abusos y ataques de denegación de servicio. Y comunícaselo al cliente con cabeceras estándar:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 874
X-RateLimit-Reset: 1717200000
Validación de entrada
Nunca te fíes de lo que llega del cliente. Toda entrada se valida contra el esquema definido en OpenAPI antes de procesar nada. Frameworks como FastAPI lo hacen por ti aprovechando los tipos de Pydantic, y eso te ahorra una capa de código manual propensa a fallos.
Del diseño a la implementación: un checklist de partida
Antes de escribir la primera línea de código de tu API, intenta tener respuesta clara a estas preguntas:
- ¿Cuál es la estrategia de versionado y cómo se expone en la URL?
- ¿Vas con design-first o con code-first para OpenAPI?
- ¿Qué mecanismo de autenticación usas y cómo gestionas los tokens?
- ¿Dónde sirves Swagger UI y con qué control de acceso?
- ¿Cómo vas a registrar y comunicar las deprecaciones futuras?
- ¿Qué política de rate limiting aplica por plan o tipo de cliente?
Responder esto en la fase de diseño te evita refactors caros cuando ya hay integraciones vivas tirando de tu API.
Construye una API que escale con tu negocio
Diseñar una API REST con versionado semántico y documentación automática no significa sobrediseñar desde el día uno. Significa fijar las convenciones correctas antes de que aparezca el primer consumidor real. En cuanto hay clientes conectados, cambiar las reglas cuesta caro.
Si tu equipo está arrancando un proyecto nuevo o necesita modernizar una API que ya tiene años, en Tangram Consulting acompañamos a equipos técnicos en el diseño e implementación de arquitecturas backend robustas y documentadas. Cuéntanos tu proyecto y vemos juntos por dónde empezar.
Recursos y especificaciones de referencia
- Especificación oficial OpenAPI 3.1: https://spec.openapis.org/oas/v3.1.0
- Swagger UI: https://swagger.io/tools/swagger-ui/
- RFC 7807 — Problem Details for HTTP APIs: define un formato estándar para respuestas de error
- RFC 8594 — The Sunset HTTP Header: protocolo para anunciar la deprecación de endpoints