Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you model a RESTful API for a single resource?

I am looking to expose some domain RESTful APIs on top of an existing project. One of the entities I need to model has a single document: settings. Settings are created with the application and is a singleton document. I'd like to expose it via a well-designed resource-based RESTful API.

Normally when modeling an API for a resource with many items its something like:

GET /employees/ <-- returns [] of 1-* items
GET /employees/{id}/ <-- returns 1 item
POST /employees/ <-- creates an item
PUT /employees/{id}/ <-- updates all fields on specific item
PATCH /employees/{id}/ <-- updates a subset of fields specified on an item
DELETE /employees/{id}/ <-- deletes a specific item

OPTION 1: If I modeled settings in the same way then the following API is built:

GET /settings/ <-- returns [] of 1-* items
[{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }]

GET /settings/{id}/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }

PUT /settings/{id}/
PATCH /settings/{id}/

This to me has a few nuances:

  1. We return an array when only 1 item CAN and EVER WILL exist. Settings are a singleton that the application creates.
  2. We require knowing the id to make a request only returning 1 item
  3. We require the id of a singleton just to PUT or PATCH it

OPTION 2: My mind then goes in this direction:

GET /settings/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }

PUT /settings/
PATCH /settings/

This design removes the nuances brought up below and doesn't require an id to PUT or PATCH. This feels the most consistent to me as all requests have the same shape.

OPTION 3: Another option is to add the id back to the PUT and the PATCH to require it to make updates, but then an API user must perform a GET just to obtain the id of a singleton:

GET /settings/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }

PUT /settings/{id}/
PATCH /settings/{id}/

This seems inconsistent because the GET 1 doesn't have the same shape as the UPDATE 1 request. It also doesn't require a consumer to perform a GET to find the identifier of the singleton.

  1. Is there a preferred way to model this?
  2. Does anyone have any good reference material on modeling RESTful APIs for singleton resources? I am currently leaning towards OPTION 2 but I'd like to know if there are good resources or standards that I can look into.
  3. Is there a compelling reason to require an API consumer to make a GET for the id of a resource to then use it in an update request, perhaps for security reasons, etc?
like image 282
gtaborga Avatar asked Mar 07 '17 22:03

gtaborga


People also ask

How do I create a resource in REST API?

Resources are typically created by sending a POST request to the parent collection resource. This creates a new subordinate resources with a newly generated id. For example, a POST request to /projects might be used to create a new project resource at /projects/123.

How would you structure a REST API?

In most cases, the design of a so-called RESTful API consists of: defining the resources accessible via HTTP. identifying such resources with URLs. mapping the CRUD (Create, Retrieve, Update, Delete) operations on these resources to the standard HTTP methods (POST, GET, PUT, DELETE)


3 Answers

The ID of the Resource is the Url itself and not necessarily a Guid or UUID. The Url should uniquely IDentify the Resource, in your case the Settings entity. But, in order to be RESTfull, you must point to this resource in your index Url (i.e. the / path) with an appropriate rel attribute, so the client will not hardcode the Url, such as this:

GET /
{ ....
"links": [
       { "url" : "/settings", "rel" : "settings" }
], ...
}

There are no specifics to accesing a singleton resource other than the Url will not contain a Guid, Uuid or any other numeric value.

like image 56
Constantin Galbenu Avatar answered Oct 07 '22 05:10

Constantin Galbenu


Option 2 is perfectly RESTful, as far as I can tell.

The core idea behind RESTful APIs is that you're manipulating "resources". The word "resource" is intentionally left vague so that it can refer to whatever is important to the specfic application, and so that the API can focus only on how content will be accessed regardless of what content will be accessed.

If your resource is a singleton, it does not make sense to attribute an ID value to it. IDs are very useful and commonly used in RESTful APIs, but they are not a core part of what makes an API RESTful, and, as you have noticed, would actually make accessing singleton resources more cumbersome.

Therefore, you should just do away with IDs and have both

GET /settings/

and

GET /settings/{id}

always return the settings singleton object. (access-by-id is not required, but it's nice to have just in case someone tries it). Also, be sure to document your API endpoint so consumers don't expect an array :)

Re: your questions,

I believe option 2 would be the preferred way of modeling this, and I believe requiring your consumer to make a GET for the id would actually be somewhat of an anti-pattern.

like image 4
Pedro Castilho Avatar answered Oct 07 '22 05:10

Pedro Castilho


I think the confusion here is because the word settings is plural, but the resource is a singleton.

Why not rename the resource to /configuration and go with option 2?

It would probably be less surprising to consumers of your API.

like image 4
MvdD Avatar answered Oct 07 '22 05:10

MvdD