Modelado de recursos, colecciones y relaciones en rutas REST

Capítulo 2

Tiempo estimado de lectura: 6 minutos

+ Ejercicio

Convenciones de rutas: colecciones y elementos

Al modelar rutas REST, el objetivo es que la URL describa recursos (sustantivos) y su estructura (colecciones, elementos y relaciones) de forma predecible. Una convención consistente reduce ambigüedades, facilita el consumo por clientes y evita que la API “se vuelva única” en cada endpoint.

Colecciones en plural

Use sustantivos en plural para representar colecciones. Esto hace que sea evidente que el recurso puede listar/crear elementos.

  • /users
  • /orders
  • /invoices

Elementos con identificador

Para un elemento específico, agregue un identificador como segmento de ruta.

  • /users/{userId}
  • /orders/{orderId}

El identificador debe ser opaco para el cliente cuando sea posible (por ejemplo, UUID). Si usa IDs numéricos, mantenga el formato estable y no “codifique” significado adicional en la ruta.

Relaciones y pertenencia: anidamiento controlado

El anidamiento expresa pertenencia o contexto: “estos pedidos pertenecen a este usuario”. Es útil cuando el recurso hijo no tiene sentido sin el padre o cuando el acceso está naturalmente acotado por el padre.

Continúa en nuestra aplicación.
  • Escuche el audio con la pantalla apagada.
  • Obtenga un certificado al finalizar.
  • ¡Más de 5000 cursos para que explores!
O continúa leyendo más abajo...
Download App

Descargar la aplicación

Ejemplo típico de pertenencia

  • /users/{userId}/orders (colección de pedidos del usuario)
  • /users/{userId}/orders/{orderId} (un pedido específico del usuario)

Cuándo anidar y cuándo no

Use anidamiento cuando:

  • La relación es fuerte (composición o pertenencia clara).
  • Necesita restringir el ámbito por permisos o multitenencia (p. ej., un usuario solo puede ver sus pedidos).
  • El recurso hijo se identifica naturalmente dentro del contexto del padre.

Evite anidar cuando:

  • El recurso hijo es global y puede consultarse sin el padre (p. ej., /orders/{orderId} existe por sí mismo).
  • El anidamiento empieza a crecer en profundidad y complejidad.
  • La relación es más bien una asociación (muchos-a-muchos) y no “pertenencia”.

Límites de profundidad y alternativas al anidamiento

Una regla práctica común es limitar el anidamiento a 1 nivel (padre/hijo) y, como máximo, 2 niveles en casos excepcionales. A partir de ahí, la ruta se vuelve difícil de mantener, de documentar y de consumir.

Ejemplos de profundidad excesiva (a evitar)

  • /companies/{companyId}/users/{userId}/orders/{orderId}/items/{itemId}

En su lugar, combine rutas más planas con filtros, parámetros de consulta y enlaces.

Alternativa 1: parámetros de consulta para filtrar por relación

Si orders es un recurso global, puede filtrar por usuario:

  • /orders?userId={userId}
  • /orders?userId={userId}&status=paid

Esto evita rutas profundas y mantiene un punto de entrada consistente para búsquedas.

Alternativa 2: subrecursos “de relación” explícitos

Para relaciones muchos-a-muchos o asociaciones, considere un recurso de relación:

  • /users/{userId}/roles (roles asignados)
  • /user-roles?userId={userId} (colección de asignaciones)

La elección depende de si la relación tiene atributos propios (por ejemplo, fecha de asignación). Si los tiene, un recurso de relación suele ser más claro.

Alternativa 3: enlaces (HATEOAS ligero) para navegar

Sin entrar en formalismos, es muy útil devolver enlaces para que el cliente descubra rutas relacionadas sin construirlas manualmente.

{  "id": "u_123",  "name": "Ada",  "links": {    "self": "/users/u_123",    "orders": "/users/u_123/orders"  }}

Esto ayuda a mantener la estabilidad: si en el futuro cambia la forma de acceder a orders, puede ajustar el enlace sin romper clientes que lo consumen.

Coherencia de nombres: kebab-case vs snake_case

Defina una convención y aplíquela en toda la API. En rutas, lo más importante es la consistencia (no mezclar estilos).

Recomendación práctica

  • Para segmentos de ruta con varias palabras, use kebab-case: /payment-methods, /order-items.
  • Evite mezclar con snake_case en rutas: /payment_methods.

Si su organización ya usa snake_case en rutas por legado, manténgalo, pero no lo mezcle con kebab-case. Reserve la discusión de estilos para un estándar interno y documente la decisión.

Tabla de consistencia de nombres

ConceptoConsistenteInconsistente (evitar)
Colección/users/user
Elemento/users/{userId}/users?id={userId} (para obtener un elemento)
Segmento compuesto/payment-methods/payment_methods y /paymentMethods mezclados
Anidamiento/users/{userId}/orders/users/{userId}/order-list

Estabilidad de rutas: cómo evitar romper clientes

Las rutas deben ser estables en el tiempo. Cambios frecuentes en URLs obligan a migraciones costosas.

Buenas prácticas para estabilidad

  • No incluya detalles de implementación en la ruta: evite /sql/, /legacy/, /v2new/.
  • Evite rutas “verbales” que reflejen acciones cambiantes: /users/{id}/getOrders.
  • Use nombres de dominio que sobrevivan a cambios internos: /orders en lugar de /purchases si el negocio lo llama “orders” y es estable.
  • Planifique alias o redirecciones si debe renombrar: mantenga temporalmente la ruta antigua y devuelva enlaces a la nueva.

Ejemplos comparativos: rutas correctas e incorrectas

Colecciones y elementos

  • Correcta: /products
  • Incorrecta: /getProducts
  • Correcta: /products/{productId}
  • Incorrecta: /product/{productId} (singular si el resto está en plural)

Relaciones y anidamiento

  • Correcta: /users/{userId}/orders (pertenencia clara)
  • Incorrecta: /users/{userId}/orders/{orderId}/payments/{paymentId}/refunds/{refundId} (profundidad excesiva)
  • Alternativa correcta (más plana): /refunds?paymentId={paymentId} o /refunds/{refundId} con enlace desde /payments/{paymentId}

Consistencia de estilo

  • Correcta (kebab-case): /order-items
  • Incorrecta (mezcla): /order_items en un módulo y /order-items en otro

Evitar “acciones” en la ruta

  • Correcta: /orders/{orderId}/status (si el estado es un subrecurso)
  • Incorrecta: /orders/{orderId}/changeStatus

Guía práctica paso a paso para diseñar rutas de recursos y relaciones

Paso 1: liste recursos principales (colecciones)

Escriba los sustantivos del dominio que el cliente necesita manipular o consultar. Ejemplo: users, orders, products, payments.

Paso 2: defina identificadores y formato

Decida el patrón de IDs por recurso (UUID, numérico, prefijo). Manténgalo consistente y documente ejemplos: u_123, ord_456.

Paso 3: identifique relaciones de pertenencia (candidatas a anidamiento)

Pregunte: “¿tiene sentido listar X sin Y?” Si no, anide: /users/{userId}/orders. Si sí, mantenga X como recurso global y use filtros o enlaces.

Paso 4: aplique un límite de profundidad

Establezca una regla interna (por ejemplo, máximo 1 nivel) y úsela como criterio de revisión. Si necesita más, reevalúe: ¿puede resolverse con ?filter o con un recurso de relación?

Paso 5: estandarice el estilo de nombres

Elija kebab-case o snake_case para rutas y aplíquelo a todos los segmentos compuestos. Cree una lista de nombres canónicos (glosario) para evitar sinónimos: orders vs purchases.

Paso 6: valide estabilidad y crecimiento

Simule cambios futuros: ¿qué pasa si orders se asocia a organizations además de users? Una ruta plana /orders/{orderId} con enlaces a su propietario suele resistir mejor que rutas profundamente contextuales.

Checklist de consistencia para revisar rutas

  • ¿Todas las colecciones están en plural?
  • ¿Los elementos se acceden como /{collection}/{id} y no con parámetros para “obtener uno”?
  • ¿El anidamiento se usa solo para pertenencia clara y no supera el límite acordado?
  • ¿Existen alternativas planas con parámetros de consulta para búsquedas y filtros?
  • ¿Se evita mezclar kebab-case y snake_case en rutas?
  • ¿Los nombres de recursos son consistentes (sin sinónimos) en toda la API?
  • ¿Las rutas evitan verbos/acciones (/get, /create, /do)?
  • ¿Las rutas no exponen detalles de implementación y son estables ante cambios internos?
  • ¿Las respuestas incluyen enlaces útiles para navegar a recursos relacionados cuando aplica?

Ahora responde el ejercicio sobre el contenido:

Al diseñar rutas REST para representar pedidos de un usuario, ¿cuál enfoque es más adecuado cuando la relación es de pertenencia clara y se busca evitar ambigüedades?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

Cuando existe pertenencia clara, el anidamiento (padre/hijo) comunica el contexto de forma predecible. Se deben evitar rutas verbales y la mezcla de estilos (kebab-case vs snake_case) porque reducen consistencia y estabilidad.

Siguiente capítulo

Semántica de verbos HTTP en APIs REST mantenibles

Arrow Right Icon
Portada de libro electrónico gratuitaDiseño de APIs REST: buenas prácticas, errores comunes y estándares
20%

Diseño de APIs REST: buenas prácticas, errores comunes y estándares

Nuevo curso

10 páginas

Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.