4

I am wondering how to deal with nested resources in a REST API. I've seen other questions on the subject here, but I didn't find one that answered my question. More specifically, should POSTing/PUTting of the parent resource should POST/PUT/DELETE the nested resources?

For example, I have a REST API with Persons and their Cars. So "cars" is a nested array of a Person. Also of note, the server should assign ids to the Persons as well as it should for Cars.

Should I POST a person and their cars in one API call or should I POST the person and then POST each one of their cars?

Option 1

POST /persons
{
  name: "Roger",
  cars: [{
    make: "Ford",
    model: "F-150"
  },{
    make: "Chevrolet",
    model: "Silverado"
  }
}

Option 2

POST /persons
{
  name: "Roger"
}
POST /persons/30954058645/cars
{
  make: "Ford",
  model: "F-150"
}
POST /persons/30954058645/cars
{
  make: "Chevrolet",
  model: "Silverado"
}

If there is a person with cars, what should be the behavior of PUTting a person? Should I include their cars in the PUT /persons call or should I only allow adding,updating,deleting cars in the POST,PUT,DELETE /persons/:id/cars call?

Is it expected from REST APIs to be able to POST/PUT/DELETE nested resources from making a PUT call on the parent resource?

2 Answers 2

3

It looks to me like your "nested resource" is closely analogous to a secondary resource as described in RFC 3986. Which is to say, it's just a bit of named information enclosed within the representation of the primary resource.

For instance, in this URI

https://www.rfc-editor.org/rfc/rfc3986#section-3.5

The fragment "section-3.5" identifies a secondary resource within the representation of https://www.rfc-editor.org/rfc/rfc3986

We perform edits on the secondary resource using the semantics of edits to the primary. For example, if I wanted to fix a spelling error in section-3.5, I would POST/PUT/PATCH the changes to https://www.rfc-editor.org/rfc/rfc3986.


What REST/HTTP don't tell you is how to design your resources. Should there be one resource, or many? Should information about cars be included in the representation of person as a secondary resource, or should it be in a separate primary resource that is linked from person, or both?

The best heuristic I know of is to ask: how would you do this on the web? Would you prefer one HTML form for submitting the person, and then another web form for submitting a single vehicle? Or one web form that accepts all of the information in one go? Do you want one web page that shows all of the information? or several pages linked together?

There's no single "right answer" here, just a bunch of different trade offs (mostly centering around caching).


If there is a person with cars, what should be the behavior of PUTting a person? Should I include their cars in the PUT /persons call or should I only allow adding,updating,deleting cars in the POST,PUT,DELETE /persons/:id/cars call?

PUT /persons should have the same semantics as it does for every other resource on the web; it is a request to replace the representation of /persons with the representation included in the payload of the request.

PUT /persons
Content-Type: application/json

{
  name: "Roger"
}

What this message means is "the next time somebody requests GET /persons, there shouldn't be a cars member"; in other words, exactly the same thing that would happen if we were just writing documents into a dumb document store. That's the point of "uniform interface" - HTTP messages have the same semantics no matter what the target-uri is.

(What the server chooses to do with that request is a separate question; you don't have to satisfy every request you receive, and you don't have to fulfill the request the same way that a dumb document store does. You do have to describe your response using the same semantics that a dumb document store uses, and so on.)

0

The thing to remember is that the HTTP verb is just a string header. You can put whatever you like in it as long as your server knows what to do and your documentation tells the user. Or better yet you publish a client.

If you want to be RESTful then the spec isn't clear on this point. You can choose either and then argue about it on the internet for the "REST" of time (see what I did there? :))

3
  • Haha! Clever! Yes, I see, I was just wondering if there was a clear choice between the two or if one is usually expected from API users
    – samdouble
    Mar 5, 2021 at 13:19
  • This is bad advice. The HTTP method is a contract. If you break that contract, you run the risk of your API not working with intermediate services like an HTTP cache layer. Mar 6, 2021 at 20:25
  • no you dont. besides you should use the cache control stuff to ensure your responses are cached the way you specify anyway
    – Ewan
    Mar 7, 2021 at 7:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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