Por qué es importante el versionado
Una API es una promesa. Una vez que los clientes dependen de ella, cambiarla descuidadamente rompe sus aplicaciones, y los clientes rotos resultan costosos para todos. El versionado es la forma de implementar mejoras mientras se ofrece a los clientes un contrato estable y un camino claro para migrar.
El objetivo no es evitar el cambio, sino hacer que sea predecible: saber qué cambios son seguros, exponer las versiones de manera consistente y retirar las antiguas siguiendo un calendario comunicado, en lugar de dar sorpresas.
Cambios disruptivos frente a cambios aditivos
La mayor parte de los problemas de versionado provienen de no clasificar los cambios. Empieza estableciendo una regla clara.
Generalmente seguros (aditivos):
- Añadir un nuevo campo opcional a una respuesta.
- Añadir un nuevo endpoint.
- Añadir un nuevo parámetro de solicitud opcional.
- Añadir un nuevo valor de enum, siempre que los clientes toleren valores desconocidos.
Disruptivos (requieren una versión):
- Eliminar o renombrar un campo.
- Cambiar el tipo o formato de un campo.
- Convertir un parámetro opcional en obligatorio.
- Cambiar el significado o el valor predeterminado de un comportamiento existente.
- Cambiar los códigos de estado o la estructura de los errores de los que dependen los clientes.
Diseñar los clientes para que ignoren los campos desconocidos es la mejor manera de garantizar que los cambios aditivos sean seguros. Documenta esta regla para que nadie tenga que adivinar.
Estrategias de versionado
Existen cuatro formas comunes de permitir que los clientes seleccionen una versión.
Versionado por URI — la versión forma parte de la ruta.
GET /v1/posts
GET /v2/posts
Es visible, fácil de rutear, fácil de cachear y fácil de probar en un navegador. Es la opción más común para APIs públicas, aunque los puristas argumentan que la URL no debería cambiar.
Versionado por Header — un header personalizado selecciona la versión.
GET /posts
X-API-Version: 2
Las URLs se mantienen estables, lo cual es ideal para el cacheo por recurso, pero la versión es invisible en los logs, enlaces y pruebas de navegador.
Versionado por Media-type — la negociación de contenido selecciona la versión.
GET /posts
Accept: application/vnd.example.v2+json
Este es el enfoque más alineado con REST y se integra con la negociación de contenido, pero es el más difícil de descubrir y depurar.
Parámetro de consulta (Query parameter) — ?version=2. Simple, pero es fácil de omitir y complicado para el cacheo.
Cualquiera que sea la opción que elijas, aplícala de manera consistente y documéntala. Mezclar estrategias es peor que elegir una que no esté tan de moda.
Depreciación y sunset
Eliminar una versión debe ser un proceso, no un evento.
Deprecation: true
Sunset: Wed, 31 Dec 2026 23:59:59 GMT
Link: </v2/posts>; rel="successor-version"
- Deprecation anuncia que una versión o endpoint va a desaparecer.
- Sunset indica la fecha exacta en la que dejará de funcionar.
- Link apunta al reemplazo.
Acompaña los headers con una guía de migración, entradas en el changelog y comunicación directa con los usuarios más activos. Luego, monitorea el uso: si una parte significativa del tráfico sigue utilizando la versión antigua cerca de la fecha de sunset, extiéndela en lugar de romper esos clientes.
Ejecutar versiones en paralelo
Soportar dos versiones significa que el código debe dar servicio a ambas. Algunos enfoques comunes son:
- Handlers versionados que mapean a servicios compartidos, para que la lógica de negocio resida en un solo lugar.
- Adapters que traducen la representación antigua a la nueva.
- Feature flags para el despliegue gradual de nuevos comportamientos.
- Especificaciones separadas por versión, generadas y publicadas junto con la API.
Mantén las diferencias entre versiones al mínimo. Los forks grandes de lógica son difíciles de mantener y es muy fácil que diverjan con el tiempo.
Comunicando los cambios
El versionado solo funciona si los clientes saben qué está ocurriendo.
- Publica un changelog y marca claramente los cambios disruptivos (breaking changes).
- Mantén una OpenAPI spec actualizada por cada versión.
- Envía avisos de deprecación en los headers y, siempre que sea posible, por correo electrónico.
- Proporciona una guía de migración con ejemplos de antes y después.
- Ofrece una ventana de soporte que se ajuste a los ciclos de lanzamiento de tus usuarios.
Mejores prácticas
- Clasifica cada cambio como aditivo o disruptivo (breaking change) antes de lanzarlo.
- Prioriza los cambios aditivos; incrementa la versión solo cuando sea estrictamente necesario.
- Elige una estrategia de versionado y aplícala en todo el proyecto.
- Nunca elimines un campo o endpoint sin un periodo de depreciación.
- Anuncia la depreciación mediante headers y una fecha de finalización (sunset date).
- Monitorea el tráfico por versión antes de retirar una.
- Mantén la lógica compartida detrás de adaptadores específicos para cada versión.
Errores comunes
- Romper los clientes de forma silenciosa al cambiar la estructura de una respuesta.
- Crear versiones para cada pequeño cambio, generando una carga de mantenimiento excesiva.
- Mezclar diferentes estrategias de versionado dentro de la misma API.
- Eliminar una versión sin previo aviso o sin ofrecer una ruta de migración.
- Permitir que versiones antiguas sigan ejecutándose indefinidamente sin un plan definido.
- Olvidar actualizar la documentación y las especificaciones de cada versión.
Próximos pasos
El versionado es lo que permite que una API sobreviva al contacto con clientes reales. Basa tu trabajo en un diseño REST limpio, describe cada versión con OpenAPI y utiliza HTTP headers para comunicar la obsolescencia. Después, redacta una política de una sola página para tu propia API: define qué se considera un cambio disruptivo (breaking change) y cuánto tiempo vivirán las versiones.