La primera versión de una API JSON suele ser fácil: se devuelven los campos que la pantalla necesita y el cliente los consume. La dificultad aparece después, cuando hay aplicaciones móviles antiguas, integraciones externas, dashboards, jobs y socios que dependen de la forma original. Diseñar para el cambio significa aceptar que el contrato vivirá más que la implementación inicial. JSON permite flexibilidad, pero solo si se usa con disciplina.
Agregar es más seguro que cambiar
Un cliente bien escrito debería ignorar campos desconocidos. Eso permite que el servidor agregue propiedades sin romper versiones antiguas. Cambiar el tipo de un campo existente, renombrarlo o eliminarlo es mucho más peligroso. Si total era número y luego pasa a string, algunos clientes fallarán de inmediato y otros producirán resultados incorrectos.
La compatibilidad debe probarse con ejemplos reales de clientes, no solo con intención. Contract tests y fixtures históricos ayudan a confirmar que los payloads antiguos siguen siendo aceptados y que las respuestas nuevas conservan promesas básicas.
Null y ausencia no son equivalentes por accidente
Una propiedad ausente puede significar “este servidor no envía ese dato”. Una propiedad con null puede significar “se conoce el campo, pero no hay valor”. Si la API no define la diferencia, cada cliente inventará una interpretación. El resultado serán pantallas inconsistentes, filtros rotos y migraciones difíciles.
Conviene documentar cuándo un campo es requerido, opcional o nullable. Para listas vacías, normalmente un array vacío comunica mejor que null. Para objetos parciales, puede ser útil separar endpoints de resumen y detalle en lugar de mezclar estados incompletos en un mismo shape.
Los identificadores deben viajar como strings cuando importa precisión
JSON tiene un único tipo numérico, pero muchos entornos, especialmente JavaScript, no representan con seguridad todos los enteros grandes. Un identificador de 64 bits puede perder precisión si se trata como number. Por eso IDs, números de cuenta y valores que no se calculan deberían viajar como strings.
La regla no es estética. Un ID no es una cantidad matemática; es una etiqueta. Tratarlo como string evita redondeos, conserva ceros iniciales y deja claro que no se debe sumar ni ordenar como número salvo que el contrato lo defina.
Fechas y horas necesitan formato explícito
Un campo created_at puede parecer claro, pero sin zona horaria, precisión y semántica no lo es. ¿Es un instant UTC, una fecha local o una hora programada? JSON no lo sabe. La API debe usar formatos inequívocos, como ISO 8601 con offset para instants, y separar local date cuando el dominio lo requiera.
También conviene documentar precisión: segundos, milisegundos o microsegundos. Si un consumidor guarda menos precisión que el productor, el orden de eventos cercanos puede cambiar. El contrato debe reflejar lo que el sistema puede sostener.
Los errores también son parte de la API
Muchas APIs diseñan cuidadosamente la respuesta exitosa y dejan los errores como texto libre. Eso complica clientes, traducciones y soporte. Un error JSON duradero suele incluir código estable, mensaje humano, detalles opcionales y un identificador de request para diagnóstico.
El código estable no debe cambiar con la redacción. Los clientes pueden reaccionar a payment_method_expired, mientras el mensaje se traduce o mejora. Esta separación permite construir interfaces robustas sin parsear frases.
Versionar no siempre significa cambiar la URL
Algunos cambios pueden gestionarse con campos nuevos, flags o media types. Otros requieren una versión mayor en la ruta o en cabeceras. Lo importante es que el equipo tenga una política. Sin política, cada cambio incompatible se negocia tarde, cuando un cliente ya se rompió.
Las versiones antiguas necesitan lifecycle: soporte, deprecation, métricas de uso y fecha de retiro. Mantener versiones para siempre puede ser costoso, pero retirarlas sin datos es irresponsable. Los logs deben mostrar qué clientes siguen usando cada contrato.
La tolerancia de entrada debe ser consciente
Aceptar varios formatos puede facilitar migraciones, pero también ensancha la superficie de bugs. Si un endpoint acepta números y strings para el mismo ID, debe normalizar de forma explícita y registrar qué forma llegó. Si corrige silenciosamente nombres mal escritos, puede ocultar errores de integración durante meses.
Una API pública suele ser estricta en los datos que recibe y compatible en lo que emite. Esa combinación ayuda a que los productores corrijan problemas temprano y que los consumidores sobrevivan a extensiones futuras.
Los ejemplos son parte del contrato
La documentación abstracta no basta. Ejemplos reales con campos opcionales, null, errores y fechas muestran cómo se espera usar la API. También sirven como fixtures de prueba. Cuando cambia un ejemplo, debería quedar claro si el cambio es editorial o contractual.
Los ejemplos deben incluir casos límite: lista vacía, permisos insuficientes, entidad eliminada, valor desconocido y paginación. Una API que solo documenta el caso feliz deja a los clientes adivinando justo donde más se rompen.
Diseñar para cambio reduce drama operativo
Una API JSON resistente no depende de suerte ni de clientes perfectos. Usa campos estables, tipos claros, null documentado, fechas inequívocas, errores estructurados, versionado con métricas y pruebas de contrato. El formato ofrece flexibilidad; el diseño decide si esa flexibilidad será una ventaja o una fuente de regresiones.
La meta no es congelar la API para siempre. Es permitir que evolucione sin convertir cada release en una negociación de emergencia entre equipos.