Let's say an API has the method DELETE for the endpoint /authors/:id, which also deletes all posts by said author.
I understand that, when an author is deleted from the database, all GET requests to /authors/:id/posts should respond with 410 GONE, indicating that said resource is no longer available.
How should the API understand that the resource used to exist but no longer does? After all, the query SELECT * FROM posts WHERE author_id = id; is empty.
The only "solution" I thought of was to not delete the posts, but check the existence of the author in the database and act accordingly.
In most business applications, you don't really want to delete records during the normal flow of operation, especially if you then have to cascade those deletes.
For instance, in a finance application, when a customer stops doing business with you, you don't want to delete that customer record and all the sales in the past - you want to set a flag saying "this customer is no longer active".
That's often referred to as a soft delete.
Your REST API can interpret the deleted status to issue the correct status code (GONE, rather than NOT FOUND)
Related
I have an endpoint that inserts a stock ticker into a table in a DB. I personally don't care if this endpoint gets hit with a ticker that already exists in the DB. I'd like to just return a 201 no matter what. If it doesn't exists, it gets created. If it does exist, just no op and tell the user it was created.
I feel like this is Ok because it's just a simple lookup table that is being controlled internally. If I had others consuming the API that were trying to create their own stock tickers in an app then that's a scenario when I don't want it to be idempotent and alert the user.
Does this break REST standard though? Should a POST, used in this context, not be idempotent? What are potential downsides to doing this?
I asked a similar question but perhaps it was too complicated - https://stackoverflow.com/questions/26900550/rest-api-design-for-performing-different-actions-on-an-underlying-object?noredirect=1#comment42354797_26900550
The business rules for my system are as follows:
Users can create/update a job with customer and site address (address changes for each job). A new quote automatically creates a new quote with status = new (1 quote per job only)
Users can update the quote details - total, markup etc..
There are several quote statuses (new, sent, on hold, won, lost). Each status needs to be accompanied by data unique to the status e.g. 'sent' requires a sent date, 'won' and 'lost' requires a decision date. When jobs are marked as won, one or more purchase order records are required against the job, so I would like to receive an array of purchase order records along with status=won.
I am trying to use nouns and sub-resources as a best practice and not necessarily make the rest api match my database model but it is new and scary.
jobs (get, post)
jobs/{id} (get, put)
jobs/{id}/status (post, delete)
jobs/{id}/quote (post, put, delete)
jobs/{id}/quote/decision (post, delete)
The last endpoint is where the quote status will change to won/lost etc.. The delete functionality is in case the job was accidentally marked as won/lost and needs to be returned to sent.
Can anyone offer recommendations or insights into whether this is a good way to architect the api or am I overdoing it?
PUT always requires the whole representation of a resource, if you want to do partial update, you need PATCH.
If you already know the URI of a resource, for example jobs/{id}/quote then use PUT or PATCH for the creation instead of POST. POST is rather for creation of item resources in a collection and not for creation of sub-resources.
Be aware that you are defining links, e.g. GET jobs, POST jobs and so on... The responses you give for a GET should contain these links, so the client can use them. You need to add metadata to these links, for example link relations or RDF attributes from a related vocab, etc... So the client will know what the links does. The nouns in the URIs are just for checking whether we are really talking about resources and not operations, the clients have nothing to do with the URI structure.
I suggest you to read the REST constraints at first. After that you should read the basics of the HTTP standard. You should find a proper hypermedia format as well, for example HAL+JSON or JSONLD+Hydra if you prefer RDF. After that you can work.
Does anyone know how to detect deleted posts in using the Disqus API?
I'm syncrhonizing posts from Disqus using the forums.listPosts method of the API.
The listPosts method does not update the date of a deleted post, so when retrieving posts incrementaly using the since parameter, deleted posts are never retrieved again, thus I cannot delete them (They have an isDeleted attribute).
Any idea, besides brute force, on how to obtain deleted post when they're deleted?
Thanks!
There is no way to sort data by the date it was modified, so there's no direct way to get comments that have been most recently deleted.
About the only option is to occasionally page through all the deleted comments on the site (by only using the "include=deleted" parameter) and update any comments that have changed states the last time they were added to your database.
I'm making a REST interface to a management system (let's call this system A) for network equipment and I have everything working. A fetches the equipment information from another backend system (let's call this system B) and index it in a database and then whenever a client asks for the information over the REST interface it returns it as JSON.
However sometimes a client needs to forcefully make A refresh some equipment information by requesting it from B (without the client being involved besides asking A to refresh it). Refreshing the information for a single node takes several seconds so the information should probably not be returned in the same request as in which it is requested. Currently we've modeled this as that you create a job of a "refresh information" type using POST /jobs with some data. But this feels very over engineered and we'd much rather want something like POST /equipment/<id>/refresh but this feels to go against the "REST way"?
Is there any other solution to this than the one mentioned with jobs above but still follow the "REST way"?
I would use GET /equipment/<id>?since=<timestamp>, where the since parameter is optional. Semantically this means:
Get the equipment with the given id as of whenever it happened to be last refreshed (when timestamp not given), or
Get the equipment with the given id refreshed no earlier than the given timestamp
Each equipment in your system would have a last_refreshed timestamp. The GET with the since=<timestamp> parameter would refresh the equipment if last_refreshed < since and then return the equipment.
A user of your service could then say GET /equipment/123?since=<15 minutes ago> and be sure they're always getting info that's no older than 15 minutes. GET /equipment/123?since=<now> means "force a refresh."
Keep in mind that POST in Rest services means that you will create some object.
To refresh one object, or update, it's recommended the PUT method.
Like um CRUD, when you have Create, Read, Update, and Delete, in REST will be POST, GET, PUT, DELETE (in order).
Maybe in your case the best URL for this is a PUT to /equipment/<id>.
URLs:
POST to /equipment/ : Create equipment
GET to /equipment/<id>: Read equipment with id <id>
PUT to /equipment/<id>: Update equipment with id <id>
DELETE to /equipment/<id>: Delete the equipment with id <id>
I hope that solve you doubt.
Anyway, a good reference it's the Apigee ebooks
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.