Você provavelmente deve escolher a opção 1, mas fez mais RESTful. Também pode fazer sentido fornecer algo como a opção 3/4. Não há nada que obrigue você a escolher apenas um.
No entanto, o que você deve fazer é substituir os IDs pelos links . Em vez de ter um "sender_id", você deve ter apenas um URI apontando para esse recurso do usuário. Observe como isso significa que não preciso saber para qual URI anexar o "sender_id" ou como formatá-lo. Infelizmente, o JSON não possui um tipo de links. Você vai querer olhar para formatos hipermídia embutidos em JSON , por exemplo. HAL ou JSON-LD.
Agora você está certo de que, se eu quiser buscar o registro, preciso fazer duas solicitações. A boa notícia, porém, é que essas solicitações serão armazenadas em cache pelos mecanismos normal do HTTP. Uma rede de entrega de conteúdo pode até armazenar recursos em cache entre os usuários, reduzindo a carga nos servidores e a latência para os usuários. Naturalmente, não estou impedido de ter um recurso que retorne todos os usuários ou os dados para todos os usuários que receberam uma lista de URIs do usuário para que eu possa solicitações em lote. Você pode considerar o OData como um meio organizado de fornecer esses recursos de consulta, mas certamente pode fazer algo mais simples. Por exemplo, ao retornar as mensagens, você também pode adicionar um link para, digamos, "contatos recentes" que tenham os dados expandidos para todos os usuários na lista atual de mensagens. Observe como eu digo fornecer um link e não adicionar um recurso messages/users/
. Você pode adicionar esse recurso, mas não preciso saber sua estrutura de URI para encontrá-lo. Isso facilita para mim e permite que você altere seus URIs no futuro sem prejudicar os consumidores.
Às vezes, haverá garantias transacionais que você vai querer impor. Por exemplo, no exemplo acima, eu poderia receber as mensagens, solicitar os contatos recentes e essa lista pode ser diferente da lista de URIs de remetente que possuo nas mensagens devido a uma condição de corrida. Nos casos em que é importante garantir esse tipo de atomicidade, você deve incorporar os recursos. Alguns dos formatos hipermídia mencionados acima fornecem um mecanismo para isso. Normalmente, essas situações corresponderão naturalmente a um novo recurso. Lembre-se, você não precisa de uma correspondência 1-1 entre recursos e "entidades" ou qualquer outra coisa. De fato, tal correspondência 1-1 provavelmente significa que você está fazendo algo errado. No geral, porém, você deve tentar minimizar os pontos que precisam de tais garantias transacionais. No exemplo acima, seria desnecessário, pois mesmo que um remetente estivesse faltando na lista de "contatos recentes", eu poderia apenas solicitar suas informações individualmente.