API - do I need the parent resource? - api

A person can have many reviews. My endpoint to CREATE a new review is:
post /person/{id}/reviews
How about the endpoint to UPDATE a review? I see two options:
Stick to the parent resource: patch /person/{person_id}/reviews/{id}
Only have reviews in the URI: patch /reviews/{id}
I could be sold on using either of them:
It's consistent with the previously defined endpoint, but {person_id} is not needed.
It's 'efficient' as we're not specifying a parameter ({person_id}) that is not really needed. However, it breaks the API convention.
Which one is preferable and why?

The client shouldn't have to know about ids at all. After a client creates the review, the response should include the URI to the new review like this:
HTTP/1.1 201 Created
Location: /person/4/reviews/5
The client now has the full URL to the review, making it completely irrelevant how it looks like and what information is here.
Don't forget that the URL itself is a system to create globally unique IDs, that embed not just it's own unique identity but also information on how to access the data. If you introduce a separate 'id' and 'person_id' field you are not taking advantage of how the web is supposed to work.

In terms of API design, without knowing too much detail about OP's situation I'd walk along these guideposts:
Only have reviews in the URI: patch /reviews/{id}
It's 'efficient' as we're not specifying a parameter ({person_id})
that is not really needed. However, it breaks the API convention
The "efficiency" allows for a more flexible design. There's no existing API convention broken at this point. Moreover, this approach gives you the flexibility to avoid the need of always needing the parent resource ID whenever you display your items.
Stick to the parent resource: patch /person/{person_id}/reviews/{id}
It's consistent with the previously defined endpoint, but {person_id}
is not needed.
The consistency aspect here can be neglected. It's not beneficial to design endpoints similarly to other endpoints just because the previous ones were designed in a certain way.
The key when deciding one way or the other is the intent you communicate and the following restrictions that are put on the endpoint.
The crucial question here is:
Can the reviews ever exist on their own or will they always have a parent person?
If you don't know for sure, go for the more flexible design: PATCH /reviews/{id}
If you do know for sure that it always will be bound to a particular person and never can have a null value for person_id in the database, then you could embed it right into your endpoint design with: PATCH /person/{person_id}/reviews/{id}
By the way, the same is true for other endpoints, like the creation endpoint POST /person/{person_id}/reviews/{id}. Having an endpoint like this removes the flexibility of creating reviews without a person, which may be desirable or not.

Related

REST: handling nested resources and paths

I have three resources, owner, dog, and puppy and I am designing the REST endpoints for the puppy. I already know who the owner is with every request via JWT authentication, so I never need to expose their ID through API paths or request bodies.
I would like a owner to be able to POST, PATCH, DELETE, GET all, or GET one on puppy when they make requests to the API. The POST (creation) of a puppy requires the ID of the dog because they have a parent-child relationship, but all of the other operations do not. In addition, I would like a owner be able to GET all of their puppies and filter this by dog if they need to.
Given these constraints, how would you design your API:
Option #1 (un-nested, passing the dog ID in the POST body)
POST /puppies
- include `dogId` in the POST body
PATCH /puppies/{puppyId}
DELETE /puppies/{puppyId}
GET (one) /puppies/{puppyId}
GET (all) /puppies
- allow for a query string of ?dog={dogId} to be passed to filter on dog
Option #2 (nested, even though it may be unnecessary for several verbs)
POST /dogs/{dogId}/puppies
- include `dogId` in the path
PATCH /dogs/{dogId}/puppies/{puppyId}
DELETE /dogs/{dogId}/puppies/{puppyId}
GET (one) /dogs/{dogId}/puppies/{puppyId}
GET (all) /dogs/{dogId}/puppies
- lose ability to get all puppies per owner
Option #3 (mix nested/un-nested wherever necessary)
POST /dogs/{dogId}/puppies
GET (all) /dogs/{dogId}/puppies
PATCH /puppies/{puppyId}
DELETE /puppies/{puppyId}
GET (one) /puppies/{puppyId}
GET (all) /puppies
- extra endpoint so we can get all puppies per owner
I like option #1 for its simplicity and conciseness, but am unsure if sending dogId in the POST body would be considered bad practice. I like #3 for its accuracy, but I think it makes finding endpoints difficult (especially in documentation) because the root resource in the path switches between puppy and dog.
First thought: Alice's list of puppies and Bob's list of puppies are different lists of information, so they should normally be treated as different resources, with different identifiers.
HTTP has different caching rules for caching responses to authorized requests and caching responses unauthorized requests, so you'll probably get away with using the same resource identifier and changing the representations. Think carefully about whether a single identifier really offers significant benefits over the "just be normal" case.
Second thought: the target uri used to change the representation of a resource should normally be the same as the target uri used to fetch the representation of the resource.
You don't have to do it this way, of course, but if you do you get standardized cache invalidation "for free". (How important is that? probably less important than it was in the 90s).
So if
GET /ABCDE
returns a document with a list of Spot's puppies, and you are trying to register a new puppy sired by Spot, then:
POST /ABCDE
Is a natural way to do that - the target uri of the edit request matches the document you are editing.
The machines don't care what design you actually use for your resource model, or what conventions you use for identifying resources, which is good, it means that you can instead choose spellings that make life easier for the human beings that you care about.
I like #3 for its accuracy, but I think it makes finding endpoints difficult
That's what hyperlinks are for. Instead of the client playing "guess the URI", or using some out of band information, you "just" share links, and let the client follow the links to navigate through the graph of resources.
(That's not to say that you should or shouldn't use style #3, only that you shouldn't compromise your URI design to address problems that already have standardized solutions.)
I would not seperate the puppies from the dogs. After a few years they become adult dogs and you'd need to move them to the dog category. I think it would be something like this:
POST /dogs
PATCH /dogs/{dogId}
DELETE /dogs/{dogId}
GET (one) /dogs/{dogId}
GET (all) /dogs
GET (puppies) /dogs?puppies=true
GET (dogs) /dogs?puppies=false
GET (parent) /dogs/{dogId}/parent
GET (owner) /dogs/{dogId}/owner
GET (dogs & puppies of the owner) /dogs?owner={ownerId}
GET (puppies of the owner) /dogs?puppies=true&owner={ownerId}
GET (dogs of the owner) /dogs?puppies=false&owner={ownerId}
As of listing the dogs of an owner you can use authorization based on your JWT. I am not sure why you think the owner id is a secret. Better to have proper cache control headers if you don't want the client to store it. You can use some sort of uuid generator if you don't want it to be guessable.

RESTful API Design: ID values for "owned" resources

When designing a restful API, resource ownership is a consideration when designing the URIs. In my case, I'm working on an API where two of my entities will be people and addresses. Each person can have more than one address, so in the database they'll be in separate tables.
Normally I just use auto incrementing keys, so each new record adding increases the ID number.
A thought I had was that if I uses this approach, it would effectively produce a URI like this:
/people/11/addresses/52
In that case, person 11 doesn't have 52 addresses. It's just person 11, who has an address with an ID of 52.
The other side of it is whether I would even be using a URI like that. Addresses generally won't be retrieved on their own by the client, but as part of a person object retrieved by a single API call (/people/11 would retrieve all addresses associated with that person).
Anyway, I guess the question here is about best practices. Is it common to see an entity owned by another with ID values like that? What are the general practices with this?
Your method is correct.
Also These are general rules (reference):
- An API is a user interface for a developer - so put some effort into making it pleasant
- Use RESTful URLs and actions
- Use SSL everywhere, no exceptions
- An API is only as good as its documentation - so have great documentation
- Version via the URL, not via headers
- Use query parameters for advanced filtering, sorting & searching
- Provide a way to limit which fields are returned from the API
- Return something useful from POST, PATCH & PUT requests
- HATEOAS isn't practical just yet
- Use JSON where possible, XML only if you have to
- You should use camelCase with JSON, but snake_case is 20% easier to read
- Pretty print by default & ensure gzip is supported
- Don't use response envelopes by default
- Consider using JSON for POST, PUT and PATCH request bodies
- Paginate using Link headers
- Provide a way to autoload related resource representations
- Provide a way to override the HTTP method
- Provide useful response headers for rate limiting
- Use token based authentication, transported over OAuth2 where delegation is needed
- Include response headers that facilitate caching
- Define a consumable error payload
- Effectively use HTTP Status codes
Also there are lots of references on web. This page is a good start.
and these are also useful: slide1, devzone tutorial
You would normally use a resource like: /people/11/addresses/52 when you return the details of an address in a personalised manner for the people entity.
If for example, you have entities: people and office which can have addresses, and for people you want to display only the country and for offices you want to display all the details of addresses.
On the other hand, if you don't need customization you can also use an url like: /address/12 , since it will be easier to cache a response like that.
Addresses generally won't be retrieved on their own by the client,
but as part of a person object retrieved by a single API call
(/people/11 would retrieve all addresses associated with that person).
If this is the case you can leave out the detailed addresses url.
Yes, That's correct way to apply many to many relation in APIs. Just remember to check id2 belongs to id1 when returning the value.
For retrieving all the addresses the correct call is /people/11/addresses. Then you know you have to call a join query.

WCF REST Resource Design - POSTing vs. GETing

I am designing a REST service for my company. No one here has had much experience with REST so I read through a few books on the subject but I am stuck on resource design of a POST vs. the resource design of a GET request for the same data. Particularly in the case of foreign relationships.
For instance I have a class PurchaseRequest which represents a request to purchase some fixed asset. Behind the scenes my service is an interface to a relational DB. There is a PURCHASE_REQUEST table which has a foreign key to an ASSET table (Defining which of a fixed list of assets are being requested) and a PERSON table (Defining which of the users is doing the requesting). Currently in my service when a GET command is issued for a purchase request, the service returns the whole thing: An XML representation of the PURCHASE_REQUEST table entry along with a list of asset entries like so:
<PurchaseRequest>
<ID></ID>
<RequestDate></RequestDate>
<Requestor href="/requestors/requestorID">
<RequestorID></RequestorID>
<FirstName></FirstName>
<LastName></LastName>
</Requestor>
<RequestedAssets>
<RequestedAsset href="/assets/AssetNumber" >
<AssetNumber></AssetNumber>
<Year></Year>
<Make></Make>
<Model></Model>
<Cost></Cost>
</RequestedAsset>
<RequestedAsset href="/assets/AssetNumber" >
<AssetNumber></AssetNumber>
<Year></Year>
<Make></Make>
<Model></Model>
<Cost></Cost>
</RequestedAsset>
<RequestedAsset href="/assets/AssetNumber" >
<AssetNumber></AssetNumber>
<Year></Year>
<Make></Make>
<Model></Model>
<Cost></Cost>
</RequestedAsset>
</RequestedAssets>
</PurchaseRequest>
This works pretty efficiently. The consuming application makes a single request and gets the whole thing and links to the full resource requestor resource or asset resource if they need them.
The problem comes on a POST. My gut tells me to try to use the same resource layout for POSTing a new purchase request as I used to retrieve an existing one. This is what all the examples in the books I have read do anyway. I don’t need to know anything more than the Asset Number and Requestor ID to fulfill the POST. That means that data is not necessary but the inefficiency alone is not what bothers me. The main thing is you should not be able to edit the year, make or model of an asset when creating a purchase request, those fields are pre-defined. You also should be able to create a new asset definition when creating a purchase request. Similarly you should not be able to update/create a person's details when creating a purchase request. There are separate services for creating/updating people and assets.
The only thing I can think of is to define a different DataContract class for the POST which has the minimum info to identify an asset or a person and does not expose those fields which cannot be updated. I really don’t love this option because it is going to create a large number of DataContracts classes (nearly all of the tables in my DB have foreign relationships, this is not isolated to one request or I would not be worrying about it) However I really don’t love my current design because REST does not have read-only fields.The burden is now on the consumers of my service to constantly be checking, "does it save this field… what about this one?..." Has anyone else ran into this issue? Is it common to have to define a separate DataContract class for POSTing and GETing? Seems like a pretty basic design question but I don’t see a lot of posts out there on the subject so I am hoping I just missed something. Any help is appreciated.

RESTfully creating object graphs

I'm trying to wrap my head around how to design a RESTful API for creating object graphs. For example, think of an eCommerce API, where resources have the following relationships:
Order (the main object)
Has-many Addresses
Has-many Order Line items (what does the order consist of)
Has-many Payments
Has-many Contact Info
The Order resource usually makes sense along with it's associations. In isolation, it's just a dumb container with no business significance. However, each of the associated objects has a life of it's own and may need to be manipulated independently, eg. editing the shipping address of an order, changing the contact info against an order, removing a line-item from an order after it has been placed, etc.
There are two options for designing the API:
The Order API endpoint intelligently creates itself AND its associated resources by processing "nested resource" in the content sent to POST /orders
The Order resource only creates itself and the client has to make follow-up POST requests to newly created endpoints, like POST /orders/123/addresses, PUT /orders/123/line-items/987, etc.
While the second option is simpler to implement at the server-side, it makes the client do extra work for 80% of the use-cases.
The first option has the following open questions:
How does one communicate the URL for the newly created resource? The Location header can communicate only one URL, however the server would've potentially created multiple resources.
How does one deal with errors? What if one of the associons has an error? Do we reject the entire object graph? How is that error communicated to the client?
What's the RESTful + pragmatic way of dealing with this?
How I handle this is the first way. You should not assume that a client will make all the requests it needs to. Create all the entities on the one request.
Depending on your use case you may also want to enforce an 'all-or-nothing' approach in creating the entities; ie, if something falls, everything rolls back. You can do this by using a transaction on your database (which you also can't do if everything is done through separate requests). Determining if this is the behavior you want is very specific to your situation. For instance, if you are creating an order statement you may which to employ this (you dont want to create an order that's missing items), however if you are uploading photos it may be fine.
For returning the links to the client, I always return a JSON object. You could easily populate this object with links to each of the resources created. This way the client can determine how to behave after a successful post.
Both options can be implemented RESTful. You ask:
How does one communicate the URL for the newly created resource? The Location header can communicate only one URL, however the server would've potentially created multiple resources.
This would be done the same way you communicate linkss to other Resources in the GET case. Use link elements or what ever your method is to embed the URL of a Resource into a Representation.

The REST-way to check/uncheck like/unlike favorite/unfavorite a resource

Currently I am developing an API and within that API I want the signed in users to be able to like/unlike or favorite/unfavorite two resources.
My "Like" model (it's a Ruby on Rails 3 application) is polymorphic and belongs to two different resources:
/api/v1/resource-a/:id/likes
and
/api/v1/resource-a/:resource_a_id/resource-b/:id/likes
The thing is: I am in doubt what way to choose to make my resources as RESTful as possible. I already tried the next two ways to implement like/unlike structure in my URL's:
Case A: (like/unlike being the member of the "resource")
PUT /api/v1/resource/:id/like maps to Api::V1::ResourceController#like
PUT /api/v1/resource/:id/unlike maps to Api::V1::ResourceController#unlike
and case B: ("likes" is a resource on it's own)
POST /api/v1/resource/:id/likes maps to Api::V1::LikesController#create
DELETE /api/v1/resource/:id/likes maps to Api::V1::LikesController#destroy
In both cases I already have a user session, so I don't have to mention the id of the corresponding "like"-record when deleting/"unliking".
I would like to know how you guys have implemented such cases!
Update April 15th, 2011: With "session" I mean HTTP Basic Authentication header being sent with each request and providing encrypted username:password combination.
I think the fact that you're maintaining application state on the server (user session that contains the user id) is one of the problems here. It's making this a lot more difficult than it needs to be and it's breaking a REST's statelessness constraint.
In Case A, you've given URIs to operations, which again is not RESTful. URIs identify resources and state transitions should be performed using a uniform interface that is common to all resources. I think Case B is a lot better in this respect.
So, with these two things in mind, I'd propose something like:
PUT /api/v1/resource/:id/likes/:userid
DELETE /api/v1/resource/:id/likes/:userid
We also have the added benefit that a user can only register one 'Like' (they can repeat that 'Like' as many times as they like, and since the PUT is idempotent it has the same result no matter how many times it's performed). DELETE is also idempotent, so if an 'Unlike' operation is repeated many times for some reason then the system remains in a consistent state. Of course you can implement POST in this way, but if we use PUT and DELETE we can see that the rules associated with these verbs seem to fit our use-case really well.
I can also imagine another useful request:
GET /api/v1/resource/:id/likes/:userid
That would return details of a 'Like', such as the date it was made or the ordinal (i.e. 'This was the 50th like!').
case B is better, and here have a good sample from GitHub API.
Star a repo
PUT /user/starred/:owner/:repo
Unstar a repo
DELETE /user/starred/:owner/:repo
You are in effect defining a "like" resource, a fact that a user resource likes some other resource in your system. So in REST, you'll need to pick a resource name scheme that uniquely identifies this fact. I'd suggest (using songs as the example):
/like/user/{user-id}/song/{song-id}
Then PUT establishes a liking, and DELETE removes it. GET of course finds out if someone likes a particular song. And you could define GET /like/user/{user-id} to see a list of the songs a particular user likes, and GET /like/song/{song-id} to see a list of the users who like a particular song.
If you assume the user name is established by the existing session, as #joelittlejohn points out, and is not part of the like resource name, then you're violating REST's statelessness constraint and you lose some very important advantages. For instance, a user can only get their own likes, not their friends' likes. Also, it breaks HTTP caching, because one user's likes are indistinguishable from another's.