Aikido

Cómo evitar romper los contratos de API públicas: mantener la compatibilidad con versiones anteriores

Mantenibilidad

Regla

Evite romper público API pública.
Cambia a público API públicos que podría romper
existente cliente solicitudes son rompiendo cambios.
Piense en en la API contrato como a promesa - cambiando
en después de clientes dependen de que se rompe su código.

Lenguajes soportados: PHP, Java, C#, Python, JavaScript, TypeScript

Introducción

Las API públicas son contratos entre su servicio y sus consumidores. Una vez que los clientes dependen del formato de solicitud, la estructura de respuesta o el comportamiento de un punto final, cambiarlo rompe su código. Los cambios que rompen el código obligan a todos los clientes a actualizarse simultáneamente, lo que suele ser imposible cuando no se controlan los clientes. Las aplicaciones móviles no pueden actualizarse a la fuerza, las integraciones de terceros necesitan tiempo de migración y es posible que los sistemas heredados no se actualicen nunca.

Por qué es importante

Interrupción y confianza del cliente: Los cambios en las API provocan fallos inmediatos en las aplicaciones cliente de producción. Los usuarios experimentan errores, pérdida de datos o cortes completos del servicio. Esto daña la confianza entre los proveedores de API y los consumidores, y viola el contrato implícito de que las API estables permanecen estables.

Costes de coordinación: Coordinar cambios de última hora entre varios equipos de clientes es caro y lento. Cada equipo necesita tiempo para actualizar el código, probar los cambios y desplegarlos. En el caso de las API públicas con clientes desconocidos (aplicaciones móviles, integraciones de terceros), la coordinación es imposible.

Proliferación de versiones: Los cambios de última hora mal gestionados llevan a mantener varias versiones de la API simultáneamente. Cada versión requiere rutas de código, pruebas, documentación y correcciones de errores independientes, lo que multiplica exponencialmente la carga de mantenimiento.

Ejemplos de códigos

❌ No conforme:

// Version 1: Original API
app.get('/api/users/:id', async (req, res) => {
    const user = await db.users.findById(req.params.id);
    res.json({ id: user.id, name: user.name });
});

// Version 2: Breaking change - renamed field
app.get('/api/users/:id', async (req, res) => {
    const user = await db.users.findById(req.params.id);
    res.json({
        id: user.id,
        fullName: user.name  // Breaking: 'name' renamed to 'fullName'
    });
});

Por qué es incorrecto: Cambiar el nombre a fullName rompe todos los clientes existentes que esperan el campo nombre. El código cliente que accede a response.name recibirá undefined, causando errores. Este cambio obliga a todos los clientes a actualizar simultáneamente o fallar.

✅ Conforme:

// Version 2: Additive change - keeps old field, adds new
app.get('/api/users/:id', async (req, res) => {
    const user = await db.users.findById(req.params.id);
    res.json({
        id: user.id,
        name: user.name,           // Keep for backward compatibility
        fullName: user.name        // Add new field (deprecated 'name')
    });
});

// Or use API versioning
app.get('/api/v2/users/:id', async (req, res) => {
    const user = await db.users.findById(req.params.id);
    res.json({ id: user.id, fullName: user.name });
});

Por qué es importante: Conservar lo antiguo nombre mantiene la compatibilidad con versiones anteriores al tiempo que añade fullName para nuevos clientes. Alternativamente, la creación de un nuevo endpoint versionado (/api/v2/) permite realizar cambios de última hora sin afectar a los clientes existentes que aún utilizan /api/v1/.

Conclusión

Haga evolucionar las API mediante cambios aditivos: añada nuevos campos, nuevos puntos finales o parámetros opcionales. Cuando los cambios de última hora sean inevitables, utilice el control de versiones de la API para ejecutar simultáneamente versiones antiguas y nuevas. Deje obsoletos los campos antiguos con plazos claros y guías de migración antes de eliminarlos.

Preguntas frecuentes

¿Tiene alguna pregunta?

¿Qué cambios se consideran rupturistas?

Eliminar campos de las respuestas, cambiar el nombre de los campos, cambiar los tipos de campo (de cadena a número), hacer obligatorios los parámetros opcionales, cambiar los códigos de estado HTTP para las condiciones existentes, alterar los requisitos de autenticación y modificar los formatos de las respuestas de error. La adición de nuevos parámetros de solicitud obligatorios o la eliminación completa de puntos finales también son cambios de última hora.

¿Cómo añado nuevos campos obligatorios sin romper clientes?

Haga que el nuevo campo sea opcional al principio, con un valor por defecto razonable. Documente el cambio y dé tiempo a los clientes para adoptarlo. Transcurrido un tiempo suficiente (de 6 a 12 meses en el caso de las API públicas), haga que el campo sea obligatorio en una nueva versión de la API. Nunca convierta en obligatorios los campos opcionales existentes sin un control de versiones.

¿Cuál es la diferencia entre el versionado de APIs y la depreciación?

El versionado crea un nuevo punto final (/v2/users) junto al antiguo, permitiendo la coexistencia de ambos. La desaprobación marca un antiguo punto final o campo como obsoleto, aunque lo mantiene funcional, con un calendario para su eventual eliminación. Utiliza el versionado para los cambios importantes y la eliminación gradual de las funciones menores.

¿Cuánto tiempo debo mantener las versiones obsoletas de la API?

En el caso de las API públicas, mantenga las versiones obsoletas durante al menos 12-18 meses. Para las API internas, coordine con los equipos de los clientes un calendario de migración. Avise siempre con antelación (de 3 a 6 meses como mínimo) antes de eliminar los puntos finales obsoletos. Supervise las métricas de uso para asegurarse de que los clientes han migrado antes del cierre.

¿Puedo cambiar el orden de los campos de respuesta?

Sí, el orden de los campos de los objetos JSON no forma parte del contrato de la API. Los clientes bien escritos analizan JSON por nombre de campo, no por posición. Sin embargo, hay que realizar pruebas exhaustivas, ya que algunos clientes mal escritos pueden depender del orden de los campos. En el caso de las matrices, el orden suele ser importante y no debería cambiar a menos que esté documentado.

¿Cómo versiono las API sin cambiar la ruta URL?

Utilice cabeceras HTTP: Accept: application/vnd.myapi.v2+json o cabeceras personalizadas como API-Version: 2. Los parámetros de consulta también funcionan: /api/users?version=2. La negociación del contenido mediante cabeceras es más limpia, pero más difícil de probar en los navegadores. Elija una estrategia y utilícela sistemáticamente.

Asegúrese gratis

Proteja el código, la nube y el tiempo de ejecución en un sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No requiere tarjeta de crédito | Escanea resultados en 32segs.