¿Cuáles son las principales estrategias de versionado de APIs (URI, header, content negotiation) y sus contrapartidas?
Toda API tarde o temprano rompe un contrato con alguien: versionar es decidir, de antemano, con qué frecuencia y qué tan fuerte va a doler.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
¿Cuáles son las principales estrategias de versionado de APIs (URI, header, content negotiation) y sus contrapartidas?
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Por qué una API necesita una estrategia de versionado
No todo cambio en una API es una ruptura. Agregar un campo opcional nuevo en una respuesta JSON, agregar un endpoint nuevo, o agregar un parámetro de query opcional son cambios aditivos — un cliente bien escrito ignora los campos que no reconoce y sigue funcionando. Lo que sí requiere subir de versión es un cambio disruptivo (breaking change): eliminar un campo, renombrarlo, cambiar su tipo, cambiar el significado de un código de estado, o cambiar los datos requeridos de entrada. El objetivo entero de una estrategia de versionado es darte un mecanismo para lanzar un cambio disruptivo a algunos clientes mientras el resto sigue funcionando contra el contrato con el que fueron construidos, y una señal clara de cuándo el contrato viejo desaparece.
#Estrategia 1: versionado por URI
La versión pasa a formar parte del path.
GET /v1/users/42GET /v2/users/42
// Express, routers en paraleloapp.use("/v1/users", usersRouterV1);app.use("/v2/users", usersRouterV2);
Es la estrategia más común en APIs públicas (Stripe, GitHub y Twilio exponen alguna variante) porque es imposible de romper por accidente: la versión es visible en cada línea de log, en la barra de direcciones del navegador y en cada comando curl que un desarrollador pega en un ticket de soporte. Su costo es que, en términos estrictos de REST, deja de ser "el mismo recurso" — /v1/users/42 y /v2/users/42 son dos URIs distintas para lo que conceptualmente es un mismo usuario, lo cual rompe la idea de que una URI identifica a un recurso.
#Estrategia 2: versionado por header
El path se mantiene estable; un header personalizado lleva la versión.
GET /users/42 HTTP/1.1Host: api.example.comApi-Version: 2
app.get("/users/:id", (req, res) => {const version = req.header("Api-Version") ?? "1";if (version === "2") return getUserV2(req, res);return getUserV1(req, res);});
Esto mantiene la URI estable y "pura" — un recurso, una dirección — lo cual convive mejor con caches indexados solo por la URL y con clientes que tratan la URL como la identidad del recurso. La contrapartida es la descubribilidad: la versión es invisible a menos que ya sepas que hay que buscar el header, no se puede probar pegando una URL en el navegador, y un cache HTTP compartido que no varía según ese header (Vary: Api-Version) puede servir en silencio la respuesta de la versión equivocada al cliente equivocado.
#Estrategia 3: negociación de contenido (versionado por media type)
La versión se codifica en el header Accept como parte de un media type personalizado — el enfoque que popularizó la API de GitHub.
GET /users/42 HTTP/1.1Host: api.example.comAccept: application/vnd.example.v2+json
En el papel, es la opción "más RESTful": HTTP ya tiene un mecanismo estándar, la negociación de contenido, para que un cliente diga "dame este recurso, pero en esta representación" — y una versión es simplemente otra representación. En la práctica es la que tiene el soporte de herramientas más débil de las tres: casi nadie configuró nunca un header Accept a mano, es incómodo de probar desde la barra de direcciones de un navegador, y los API gateways y CDNs varían con menos confiabilidad según Accept que según el path.
#Lado a lado
| Estrategia | Visible en la URL | Amigable con el cache | Fácil de probar/curl | Pureza REST | Usada por |
|---|---|---|---|---|---|
URI (/v1/...) | Sí | Sí (URL distinta = entrada de cache distinta) | Muy fácil | Baja (mismo recurso, distinta URI) | Stripe, Twilio, GitHub (legado) |
| Header personalizado | No | Necesita disciplina con Vary | Moderado | Más alta | Muchas APIs internas/empresariales |
| Negociación de contenido | No | Necesita disciplina con Vary: Accept | La más difícil | La más alta | API de GitHub (actual) |
Parámetro de query (?version=2) | Sí | Sí, pero contamina las claves de cache con parámetros no relacionados | Muy fácil | Baja | Algunas APIs legadas/internas |