POST /eff/you/this/is/the/right/url - RESTful API Design

By Josh Wyse in GET/technical Posted Mar 4, 2015


When starting to design and build a RESTful API, there are a lot of decisions to be made. How do you handle authentication? Which data transfer formats do you support? How do you document your APIs? How do you handle versioning? When we started our initial design to migrate from version one to version two of our own API, these were a lot of the questions that we had to answer. Some of them were easy and others incited passionate debates (read: “yelling”) amongst our engineering team.

RESTful API Design


We all spent a lot of time reading about API design. The main issue we commonly ran into was deciding on a URL when it’s not one of your standard CRUDS (create, retrieve, update, delete and search) operation. What I mean by that, is that the REST basics are easy to follow when you’re exposing these standard operations on a resource. Your URLs are nouns, and you use the standard HTTP verbs to show the action you’re performing on this noun. For example, say we have a resource called foo. To CRUDS this resource, the URLs are going to be as below, and there’s really no debating this if you’re trying to design a RESTful API:

POST /foo
GET /foo/{id}
PUT /foo/{id}
PATCH /foo/{id}
DELETE /foo/{id}
GET /foo (With search parameters, which will be another blog post)

It’s also straight-forward when you have a sub-resource of foo. Vinay Sahni’s blog (one of my favorites) does a great job illustrating the standard practice here. This is relatively straight-forward, and any trustworthy documentation on RESTful best practices is going to say the same thing. However, where you hear lots of different opinions is when you need to perform some other, non-standard, operation on a resource.

Some things we often try to do, if it makes sense, are:
– Restructure the verb to seem like a field on the resource.
– Make the verb seem like a sub-resource and then use standard HTTP verbs and RESTful practices to represent the action you’re taking.

When encountering APIs like this, we also always try to ask “what will be the most intuitive for our customers?” as opposed to “how do we do our best to be a RESTafarian?”. A good example of this is in our Documents Hub, we have an API that allows a user to copy a file. We wrestled with how to represent this copy file API. We were set on using POST because we were creating a new resource and, more importantly, this operation was not idempotent.

POST /files - This didn't work because we already had this URL taken to upload a file.
POST /files/{id} - Create a new file from the file with the given ID?
POST /files/{id}/{pathToNewFile} - Huh?

What we eventually ended up with might make some RESTafarians begin to curse under their breath, so if that’s you, I apologize (but not really):

POST /files/{id}/copy - (For real, I'm not lying)

I know, I know, there’s a verb in the URL. But, as developers, when we were browsing our API documentation, we looked at that API and we immediately knew what it was doing. It tooks some of us awhile to come around to it, but it also helped us set the stage going forward, that whenever we encounter APIs like this, we always ask the same question: “what will be the most intuitive for our customers?”. If you have encountered similar issues and have any good advice or resources, we’d love to hear from you!

Check out the next two posts in the series to learn more about RESTful API design!

Some other technical resources that provide some great insight and helped us at Cloud Elements:

Other blogs from Cloud Elements Developers

Get the definitive guide