Search code examples
restapi-design

How to design a REST API for resources that depend on each other?


I'm having troubles with designing a rest api for the following scenarios:


  1. When a new user registers he/she also creates a new group.
  2. New users can also join an existing group using a unique group code.
  3. Existing users can create new groups.
  4. Existing users can join existing groups.

I was thinking of doing it as below:


  1. POST https://api.myapp.com/users (creates new user and new group, adds user to the group)

  2. PATCH https://api.myapp.com/groups/{id} (creates new user, adds user to existing group) I don't like it that I create a new user via /groups endpoint.

  3. POST https://api.myapp.com/groups/{id} (creates new group, adds user to the group)

  4. PATCH https://api.myapp.com/groups/{id} (adds user to existing group)


I don't know how and if I should express in the api that users and groups depend on each other. Something like:


/users/{id}/groups /groups/{id}/users


If this is better approach then what should come first groups or users?


Solution

  • Groups should come first in URLs when you are adding a user to a group.

    Group Resource:

    {
        "id": "group1",
        "name": "Developers",
        "users": [
            {
              "id": "user1",
              "name": "John1"
            },
            {
              "id": "user2",
              "name": "John2"
            }
        ] 
    }
    

    User Resource:

    {
        "id": "user1",
        "groups": "John1",
        "users": [
            {
              "id": "group1",
              "name": "Developers"
            },
            {
              "id": "group2",
              "name": "Testers"
            }
        ] 
    }
    
    1. Create a new group: POST https://api.myapp.com/groups

       Request URL: https://api.myapp.com/groups
      
       Request Body:
       {
           "name": "Developers",
       }
      
       Response Body:
       {
           "id": "group1",
           "name": "Developers"
       }
      
       HTTP Status Code: 201
      
    2. Create a new user and add him to existing group: POST https://api.myapp.com/groups/{groupId}/users

       Request URL: https://api.myapp.com/groups/{group1}/users
      
       Request Body:       
       {
           "name": "John3"
       }
      
       Response Body:
       {
           "id": "user3",
           "name": "John3",
           "groups": [
               {
                 "id": "group1",
                 "name": "Developers"
               }
           ] 
       }
      
       HTTP Status Code: 201
      
    3. Create a new user & group: POST https://api.myapp.com/users

       Request URL: https://api.myapp.com/users        
      
       Request Body:
       {
           "name": "John4",
           "groups": [
               {
                 "name": "Testers"
               }
           ]
       }
      
       Response Body:
       {
           "id": "user4",
           "name": "John4",
           "groups": [
               {
                 "id": "group2",
                 "name": "Testers"
               }
           ] 
       }
      
    4. Add an existing user to an existing group: POST https://api.myapp.com/groups/{groupId}/users/{userId}

       Request URL: https://api.myapp.com/groups/{group2}/users/{user1}
       Request Body: No Body
       Response Body: No Body
       HTTP Status Code: 200
      
    5. Get a group: GET https://api.myapp.com/groups/{groupId}

       Request URL: https://api.myapp.com/groups/{group1}
       Response Body:
       {
           "id": "group1",
           "name": "Developers",
           "users": [
               {
                 "id": "user1",
                 "name": "John1"
               },
               {
                 "id": "user2",
                 "name": "John2"
               },
               {
                 "id": "user3",
                 "name": "John3"
               }
           ]
       }
      
    6. Get a user: GET https://api.myapp.com/users/{userId}

       Request URL: https://api.myapp.com/users/{user1}
      
       Response Body:
       {
           "id": "user1",
           "name": "John1",
           "groups": [
               {
                 "id": "group1",
                 "name": "Developers"
               },
               {
                 "id": "group2",
                 "name": "Testers"
               }
           ] 
       }