unsafe_where_true
unsafe_where_true

Reputation: 6310

Is this a valid REST API?

I am designing an API.

There's the user profile, accessible at

http://example.org/api/v1/users (resp. http://example.org/api/v1/users/:id)

Now, the user's profile will be dynamic. So we will allow an API function to add a new profile attribute.

Is the following a valid REST API URL for this?

POST http://example.org/api/v1/users/attributes

Indeed, to retrieve a specific user, the user's id would be appended to the .../users/ URL. Now if I use the "attributes" element after /users/, would that somehow break the user id pattern for the URL?

I'd like to keep the base URL to be api/v1/users though, because logically I am modifying the users profile still...

EDIT: The attributes would be added valid for all profiles, it's independent of a user. Say the profile has "name", "surname", "email", and I want to add "address" to all profiles (Of course I know that users with a missing "address" field would not get the new attribute)

What is a good practice to address such an issue?

Upvotes: 0

Views: 957

Answers (4)

inf3rno
inf3rno

Reputation: 26137

It is an acceptable solution to use the /api/v1/users/attributes as long as the :id cannot be the text: "attributes". However I recommend to create your own media type, microformat, or microdata for the attributes, because it is rather a type than a resource.

I think you should check these links:

If the user can set what attributes she can have, only then should you use a resource for attributes. But then each user should have one. But I don't think using resources will be necessary, microdata and microformats both contain more than enough person description attributes...

Some update after 5 months:

Now if I use the "attributes" element after /users/, would that somehow break the user id pattern for the URL?

From the perspective of the client that "id pattern" does not exist. The client follows links by checking the semantics annotated to them. So REST clients are completely decoupled from the URI structure of the actual REST API (aka. uniform interface constraint). If your pattern breaks, then it is completely a server side, link generation and routing issue, which is not a client side concern.

Say the profile has "name", "surname", "email", and I want to add "address" to all profiles. What is a good practice to address such an issue?

Address is an optional field in this case and probably a sub-resource, because it can have further fields, like city, postal code, street, etc... You can add address separately, for example with PUT /users/123/address {city: "", street: "", ...} or you can add those fields to your user form, and add a partial update to the user, like PATCH /users/123 {address: {city: "", street: "", ...}} if only the address changes.

Upvotes: 1

Eric Stein
Eric Stein

Reputation: 13682

While it is a valid URI, I would suggest avoiding POST http://example.org/api/v1/users/attributes. In my opinion, it violates the principle of least surprise when a collection endpoint has a child node which is not a member of the collection. If you want to track user attributes as shared by all users, then that's a separate collection, perhaps /user-attributes.

POST /user-attributes
{
    "name": "Email Address",
    "type": "String",
    ...
}

GET /user-attributes would return all the possible attributes, and GET /user-attributes/{id} would return all the metadata around an attribute.

If there's no metadata, then @inf3rno's suggestion to just PUT the attribute up and let the server deal with it is definitely worth considering.

This all presupposes you need to manage attributes through the API. If not, I agree with @inf3rno that media types are the way to go. Of course, in that case you may want a media type for the user-attributes resource ..

Upvotes: 0

Sebastian
Sebastian

Reputation: 17443

In case you want to update every resource in the entire collection I would send a PATCH request to /users.

Upvotes: 0

msurguy
msurguy

Reputation: 524

I think the id should be kept in the URL because you are adding the attributes to a specific user, right?

Upvotes: 1

Related Questions