0

I am building an API with Loopback.io, and I have been thinking about how should I design some of the endpoints. To get in context:

a Person hasMany Groups,
a Group hasMany People (and one of them is the admin),
a Member is the "Through" model for Person and Group,
a Group hasMany Sessions.

Now I have (A):

  1. /People
  2. /People/{id}/Groups
  3. /Groups
  4. /Groups/{id}/Sessions

which is the API generated by Loopback. 2 and 3 are "repeated" endpoints, however 2 creates a Member instance and 3 does not.

Option B:

  1. /People
  2. /People/{id}/Groups
  3. /People/{id}/Groups/{groupId}/Sessions

Option C:

  1. /People
  2. /Groups
  3. /Groups/{id}/Sessions

I would like to know which is the best approach and if the A solution would be good enough. Thank you very much.

Enric A.
  • 893
  • 10
  • 18

1 Answers1

1

Go with something closest to Option C:

/people
/people/{person_id}
/groups
/groups/{group_id}
/sessions
/sessions/{session_id}

Your resources then look something like this:

GET /people/1
{
  "person_id": 1,
  "groups": [
    "/groups/5",
    "/groups/7"
  ]
}

GET /groups/5          (Option 1 - if every group has exactly one admin)
{
  "group_id": 5,
  "admin": "/people/1",
  "members": [
    "/people/1",
    "/people/4",
    "/people/5"
  ],
  "sessions": [
    "/sessions/2",
    "/sessions/3"
  ]
}

GET /groups/5          (Option 2 - if groups can have any number of admins)
{
  "group_id": 5,
  "members": [
    {
      "person": "/people/1",
      "is_admin": true,
    },
    {
      "person": "/people/4",
      "is_admin": false
    },
    {
      "person": "/people/5",
      "is_admin": false
    }
  ],
  "sessions": [
    "/sessions/2",
    "/sessions/3"
  ]
}

GET /sessions/3
{
  "session_id": 3,
  "group": "/groups/5"
}

My advice is always to avoid nesting URIs unless there is a very good argument for doing so.

Timothy Shields
  • 75,459
  • 18
  • 120
  • 173
  • I like your approach. However, is there any concrete reason for it? I thought that nesting URIs was the most elegant way to design an API when possible. – Enric A. Apr 07 '15 at 17:19
  • @EnricAyguadé Every resource should have a single, unique URI. A URI like `/gizmos/{gizmo_id}/widgets/{widget_id}` then implies that every widget has exactly 1 related gizmo, and that a widget cannot be identified without also identifying its related gizmo. What if in the future you want to change that? Now the URIs for all of your widgets need to change! If instead you take the route I am suggesting, only the *resources* change, not the *URIs*. A concrete example of where this could come up is in your statement "a Group hasMany People (and one of them is the admin)". – Timothy Shields Apr 07 '15 at 19:20