A maneira fundamental de pensar sobre esse assunto é a seguinte:
Um URI é um identificador de recurso que identifica exclusivamente uma instância específica de um recurso TYPE. Como tudo na vida, todo objeto (que é algum tipo de instância), possui um conjunto de atributos que são invariantes ou temporais no tempo.
No exemplo acima, um carro é um objeto muito tangível que possui atributos como marca, modelo e VIN - que nunca mudam, e cor, suspensão etc. que podem mudar ao longo do tempo. Portanto, se codificarmos o URI com atributos que podem mudar ao longo do tempo (temporal), podemos acabar com vários URIs para o mesmo objeto:
GET /cars/honda/civic/coupe/{vin}/{color=red}
E anos depois, se a cor desse mesmo carro for alterada para preto:
GET /cars/honda/civic/coupe/{vin}/{color=black}
Observe que a instância do carro em si (o objeto) não mudou - é apenas a cor que mudou. Ter vários URIs apontando para a mesma instância de objeto forçará você a criar vários manipuladores de URI - esse não é um design eficiente e, é claro, não é intuitivo.
Portanto, o URI deve consistir apenas em partes que nunca serão alteradas e continuarão a identificar exclusivamente esse recurso durante toda a sua vida útil. Tudo o que pode mudar deve ser reservado para parâmetros de consulta, como:
GET /cars/honda/civic/coupe/{vin}?color={black}
Conclusão - pense no polimorfismo.