gtaborga
gtaborga

Reputation: 833

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?

Upvotes: 10

Views: 7944

Answers (4)

guillaume31
guillaume31

Reputation: 14064

You're probably overthinking it. There's no concept of singleton in HTTP or REST.

GET /settings/ is perfectly fine.

By the way, we can hardly relate this to DDD - at least not if you don't give more context about what settings means in your domain.

It might also be that you're trying to tack an "Entity with ID" approach on Settings when it's not appropriate. Not all objects in a system are entities.

Upvotes: 3

MvdD
MvdD

Reputation: 23436

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.

Upvotes: 4

Constantin Galbenu
Constantin Galbenu

Reputation: 17683

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.

Upvotes: 6

Pedro Castilho
Pedro Castilho

Reputation: 10532

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.

Upvotes: 6

Related Questions