0

I'm working on an API that allows users to invite each other for events. When someone is searching for users to invite, I want to include in the response information about whether a user has already been invited. One way to do this would be to have the response return objects that look like:

{
    "is_invited": false,
    "user": {
        "id": 1,
        "name": "John Doe"
    }
}

This requires an additional model on the server and client side, so I was also considering formatting the response like a normal user response:

"user": {
    "id": 1,
    "name": "John Doe",
    "is_invited": false
}

Where the is_invited property would only appear on responses requested from the context of a particular event. I was curious if this sort of contextually-conditional structure for responses is considered an anti-pattern in API design. If so, would the first structure be the best way to accomplish my goal, or is there another approach I haven't thought of?

  • 1
    I think you're accidentally inventing GraphQL – Alexander - Reinstate Monica Apr 16 at 1:06
  • I would recommend the 1. approach, since in the future you might want to include the event name, or maybe the event is taking place multiple places and the user is invited to a specific one; At some point your user object contains very confusing properties – TryingToImprove Apr 17 at 13:28
3

It's not an anti-pattern but it's most likely a bad idea.

REST offers a set of guidelines an constraints but it says nothing about specific details like these, what is good, what is bad, what should you do, what you should avoid. So from a REST point of view it's irrelevant if you chose option 1 or option 2.

However, from a design point of view adding the is_invited property to users is a bad idea. Why? Because this is not a property of an user. To add in some REST parlance in the mix, the is_invited property is not part of the representation of a user.

You mention here two resources: event and user. As the other existing answer mentions, this is not a property of neither an event nor a user, it's a property of the relation between an event and an user. So, your option 2 is definitely a bad idea. Don't do that.

Option 1 looks better and you might create a new resource that represents this relation between events and users. But I might dare to suggest another approach.

If you think about the is_invited property a bit, you'll see that it's an indirect property of an event. An event has participants, so it will make sense for it to have a property of participants. Then, your option 1 might transform into something like:

{
  "eventName": "whatever",
  "eventStart": "2020-05-03"
  "participants": [
     {
        "id": 1,
        "name": "John Doe"
     },
     {
        "id": 2,
        "name": "Jane Smith"
     }
     ...
  ]
}

The point is not to minimize models used by the server and client, but to create an API that is clean and intuitive to use. A list of users already attending the event is more intuitive that playing with boolean flags in various places.

| improve this answer | |
  • Unfortunately, a participants list is slightly orthogonal to the issue here. The use case is searching for users to invite to the event. From a UX perspective, it's undesirable to have this list just contain not-yet-invited users, since someone searching for a particular person can't differentiate between "spelled the name wrong" and "already invited". The goal is to have a list containing all users, with a visual indicator of whether that user has already been invited. The rest of your answer offers clear reasoning against the second approach, though, is I'll accept! – Jumhyn May 3 at 14:58
  • @Jumhyn: The list of participants of the event contains the participants that are already invited. In the UI, to add other users to the event is just a matter of listing all users, then see which users are within the already invited participants list. i.e. checking which elements of one list are also present in the other list and add a visual indicator for those present. – Bogdan May 3 at 15:14
  • Right, I understand that the information content is the same, but that's not feasible since the participants list may grow unboundedly large. The full list of participants isn't even a first-order property on event objects since it would make them arbitrarily large. Using that list to annotate each entry in the results would require either fetching the entire participants list, or making a separate query for each entry in the "potential invitees" list. – Jumhyn May 3 at 15:19
0

Probably.

The property set is relevant to a given context. A different path a different context.

The is_invited property is not a property of the event strictly, nor is it a property of the user. It is a property of a relation between user and event (like AttendingEvent).

You could probably get away with solution 2 by treating user as a sub path of event. eg: /api/event/1234567/user/12345.

If you don't like the idea of supporting two kinds of user struct, keep the vanila kind and only return it from within an event if they were invited. This also makes registration nice, put the user struct under the event to invite them.

Similarly you can invert it and have events under users following similar rules.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.